nspr-4.11/nspr/.hg_archival.txt0000644000000000000000000000020112623070344014611 0ustar 00000000000000repo: a4b34919bf34db2ee22acbbc305693c8980b6dc6 node: ebae38973a1a7241482448091e96e4e4fe5dbc27 branch: default tag: NSPR_4_11_RTM nspr-4.11/nspr/.cvsignore0000644000000000000000000000007512623070344013534 0ustar 00000000000000Makefile config-defs.h config.cache config.log config.status nspr-4.11/nspr/.hgignore0000644000000000000000000000006212623070344013333 0ustar 00000000000000syntax: glob *~ *OPT.OBJ/* *DBG.OBJ/* *DBG.OBJD/* nspr-4.11/nspr/LICENSE0000644000000000000000000004052612623070344012546 0ustar 00000000000000Mozilla Public License Version 2.0 ================================== 1. Definitions -------------- 1.1. "Contributor" means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. 1.2. "Contributor Version" means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor's Contribution. 1.3. "Contribution" means Covered Software of a particular Contributor. 1.4. "Covered Software" means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. 1.5. "Incompatible With Secondary Licenses" means (a) that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or (b) that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. 1.6. "Executable Form" means any form of the work other than Source Code Form. 1.7. "Larger Work" means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. 1.8. "License" means this document. 1.9. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. 1.10. "Modifications" means any of the following: (a) any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or (b) any new file in Source Code Form that contains any Covered Software. 1.11. "Patent Claims" of a Contributor means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. 1.12. "Secondary License" means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. 1.13. "Source Code Form" means the form of the work preferred for making modifications. 1.14. "You" (or "Your") means an individual or a legal entity exercising rights under this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. License Grants and Conditions -------------------------------- 2.1. Grants Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: (a) under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and (b) under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. 2.2. Effective Date The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. 2.3. Limitations on Grant Scope The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: (a) for any code that a Contributor has removed from Covered Software; or (b) for infringements caused by: (i) Your and any other third party's modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or (c) under Patent Claims infringed by Covered Software in the absence of its Contributions. This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). 2.4. Subsequent Licenses No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). 2.5. Representation Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. 2.6. Fair Use This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. 2.7. Conditions Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. 3. Responsibilities ------------------- 3.1. Distribution of Source Form All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients' rights in the Source Code Form. 3.2. Distribution of Executable Form If You distribute Covered Software in Executable Form then: (a) such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and (b) You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients' rights in the Source Code Form under this License. 3.3. Distribution of a Larger Work You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). 3.4. Notices You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. 3.5. Application of Additional Terms You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. 4. Inability to Comply Due to Statute or Regulation --------------------------------------------------- If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Termination -------------- 5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. 5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. 5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. ************************************************************************ * * * 6. Disclaimer of Warranty * * ------------------------- * * * * Covered Software is provided under this License on an "as is" * * basis, without warranty of any kind, either expressed, implied, or * * statutory, including, without limitation, warranties that the * * Covered Software is free of defects, merchantable, fit for a * * particular purpose or non-infringing. The entire risk as to the * * quality and performance of the Covered Software is with You. * * Should any Covered Software prove defective in any respect, You * * (not any Contributor) assume the cost of any necessary servicing, * * repair, or correction. This disclaimer of warranty constitutes an * * essential part of this License. No use of any Covered Software is * * authorized under this License except under this disclaimer. * * * ************************************************************************ ************************************************************************ * * * 7. Limitation of Liability * * -------------------------- * * * * Under no circumstances and under no legal theory, whether tort * * (including negligence), contract, or otherwise, shall any * * Contributor, or anyone who distributes Covered Software as * * permitted above, be liable to You for any direct, indirect, * * special, incidental, or consequential damages of any character * * including, without limitation, damages for lost profits, loss of * * goodwill, work stoppage, computer failure or malfunction, or any * * and all other commercial damages or losses, even if such party * * shall have been informed of the possibility of such damages. This * * limitation of liability shall not apply to liability for death or * * personal injury resulting from such party's negligence to the * * extent applicable law prohibits such limitation. Some * * jurisdictions do not allow the exclusion or limitation of * * incidental or consequential damages, so this exclusion and * * limitation may not apply to You. * * * ************************************************************************ 8. Litigation ------------- Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party's ability to bring cross-claims or counter-claims. 9. Miscellaneous ---------------- This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. 10. Versions of the License --------------------------- 10.1. New Versions Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. 10.2. Effect of New Versions You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. 10.3. Modified Versions If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. Exhibit A - Source Code Form License Notice ------------------------------------------- This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. You may add additional accurate notices of copyright ownership. Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as defined by the Mozilla Public License, v. 2.0. nspr-4.11/nspr/Makefile.in0000644000000000000000000000776312623070344013614 0ustar 00000000000000#! gmake # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOD_DEPTH = . topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk DIRS = config pr lib ifdef MOZILLA_CLIENT # Make nsinstall use absolute symlinks by default for Mozilla OSX builds # http://bugzilla.mozilla.org/show_bug.cgi?id=193164 ifeq ($(OS_ARCH),Darwin) ifndef NSDISTMODE NSDISTMODE=absolute_symlink export NSDISTMODE endif endif endif DIST_GARBAGE = config.cache config.log config.status all:: config.status export include $(topsrcdir)/config/rules.mk config.status:: configure ifeq ($(OS_ARCH),WINNT) sh $(srcdir)/configure --no-create --no-recursion else ./config.status --recheck && ./config.status endif # # The -ll option of zip converts CR LF to LF. # ifeq ($(OS_ARCH),WINNT) ZIP_ASCII_OPT = -ll endif # Delete config/autoconf.mk last because it is included by every makefile. distclean:: @echo "cd pr/tests; $(MAKE) $@" @$(MAKE) -C pr/tests $@ rm -f config/autoconf.mk rm -f `cat unallmakefiles` unallmakefiles release:: echo $(BUILD_NUMBER) > $(RELEASE_DIR)/$(BUILD_NUMBER)/version.df @if test -f imports.df; then \ echo "cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \ cp -f imports.df $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \ else \ echo "echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df"; \ echo > $(RELEASE_DIR)/$(BUILD_NUMBER)/imports.df; \ fi cd $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME); \ rm -rf META-INF; mkdir META-INF; cd META-INF; \ echo "Manifest-Version: 1.0" > MANIFEST.MF; \ echo "" >> MANIFEST.MF; \ cd ..; rm -f mdbinary.jar; zip -r mdbinary.jar META-INF bin lib; \ rm -rf META-INF; \ cd include; \ rm -rf META-INF; mkdir META-INF; cd META-INF; \ echo "Manifest-Version: 1.0" > MANIFEST.MF; \ echo "" >> MANIFEST.MF; \ cd ..; rm -f mdheader.jar; zip $(ZIP_ASCII_OPT) -r mdheader.jar *; \ rm -rf META-INF ifeq ($(OS_ARCH),WINNT) @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)"; \ mkdir -p $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \ fi @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); then \ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)"; \ mkdir -p $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ fi else @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); then \ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)"; \ $(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \ chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \ fi @if test ! -d $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); then \ rm -rf $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ echo "making directory $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)"; \ $(NSINSTALL) -D $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ chmod 775 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ fi endif cd $(RELEASE_DIR)/$(BUILD_NUMBER); \ cp -f version.df imports.df $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER); \ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/version.df; \ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/imports.df; \ cd $(OBJDIR_NAME); \ cp -f mdbinary.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)/mdbinary.jar; \ cd include; \ cp -f mdheader.jar $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME); \ chmod 664 $(MDIST)/$(MOD_NAME)/$(BUILD_NUMBER)/$(RELEASE_OBJDIR_NAME)/mdheader.jar package: @echo "cd pkg; $(MAKE) publish" $(MAKE) -C pkg publish depend: @echo "NSPR20 has no dependencies. Skipped." nspr-4.11/nspr/admin/explode.pl0000644000000000000000000000252712623070344014625 0ustar 00000000000000#!/bin/perl # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------- # # explode.pl -- Unpack .jar files into bin, lib, include directories # # syntax: perl explode.pl # # Description: # explode.pl unpacks the .jar files created by the NSPR build # procedure. # # Suggested use: After copying the platform directories to # /s/b/c/nspr20/. CD to /s/b/c/nspr20/ and # run explode.pl. This will unpack the jar files into bin, lib, # include directories. # # ----------------------------------------------------------------- @dirs = `ls -d *.OBJ*`; foreach $dir (@dirs) { chop($dir); if (-l $dir) { print "Skipping symbolic link $dir\n"; next; } print "Unzipping $dir/mdbinary.jar\n"; system ("unzip", "-o", "$dir/mdbinary.jar", "-d", "$dir"); system ("rm", "-rf", "$dir/META-INF"); mkdir "$dir/include", 0755; print "Unzipping $dir/mdheader.jar\n"; system ("unzip", "-o", "-aa", "$dir/mdheader.jar", "-d", "$dir/include"); system ("rm", "-rf", "$dir/include/META-INF"); } # --- end explode.pl ---------------------------------------------- nspr-4.11/nspr/admin/makeTargetDirs.sh0000644000000000000000000000267312623070344016074 0ustar 00000000000000#!/bin/sh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------- # makeTargetDirs.sh -- Create target directories for building NSPR # # syntax: makeTargetDirs.sh # # Description: # makeTargetDirs.sh creates a set of directories intended for use # with NSPR's autoconf based build system. # # The enumerated directories are the same as those built for NSPR # 4.1.1. Adjust as needed. # # ----------------------------------------------------------------- mkdir AIX4.3_64_DBG.OBJ mkdir AIX4.3_64_OPT.OBJ mkdir AIX4.3_DBG.OBJ mkdir AIX4.3_OPT.OBJ mkdir HP-UXB.11.00_64_DBG.OBJ mkdir HP-UXB.11.00_64_OPT.OBJ mkdir HP-UXB.11.00_DBG.OBJ mkdir HP-UXB.11.00_OPT.OBJ mkdir IRIX6.5_n32_PTH_DBG.OBJ mkdir IRIX6.5_n32_PTH_OPT.OBJ mkdir Linux2.2_x86_glibc_PTH_DBG.OBJ mkdir Linux2.2_x86_glibc_PTH_OPT.OBJ mkdir Linux2.4_x86_glibc_PTH_DBG.OBJ mkdir Linux2.4_x86_glibc_PTH_OPT.OBJ mkdir OSF1V4.0D_DBG.OBJ mkdir OSF1V4.0D_OPT.OBJ mkdir SunOS5.6_DBG.OBJ mkdir SunOS5.6_OPT.OBJ mkdir SunOS5.7_64_DBG.OBJ mkdir SunOS5.7_64_OPT.OBJ mkdir WIN954.0_DBG.OBJ mkdir WIN954.0_DBG.OBJD mkdir WIN954.0_OPT.OBJ mkdir WINNT4.0_DBG.OBJ mkdir WINNT4.0_DBG.OBJD mkdir WINNT4.0_OPT.OBJ # --- end makeTargetDirs.sh --------------------------------------- nspr-4.11/nspr/admin/symlinks.sh0000644000000000000000000000257512623070344015040 0ustar 00000000000000#!/bin/sh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # ----------------------------------------------------------------- # symlinks.sh -- create links from NSPR builds # # syntax: symlinks.sh # # Description: # symlinks.sh creates some symbolic links for NSPR build targets # that are not actually build, but for which there are NSPR # binaries suitable for running on the intended target. ... got # that? # # Suggested use: After copying NSPR binaries to # /s/b/c/nspr20/ run symlinks.sh to create the links # for all supported platforms. # # The symlinks in this script correspond to the NSPR 4.1.1 # release. Adjust as necessary. # # ----------------------------------------------------------------- ln -s SunOS5.6_DBG.OBJ SunOS5.7_DBG.OBJ ln -s SunOS5.6_OPT.OBJ SunOS5.7_OPT.OBJ ln -s SunOS5.6_DBG.OBJ SunOS5.8_DBG.OBJ ln -s SunOS5.6_OPT.OBJ SunOS5.8_OPT.OBJ ln -s SunOS5.7_64_DBG.OBJ SunOS5.8_64_DBG.OBJ ln -s SunOS5.7_64_OPT.OBJ SunOS5.8_64_OPT.OBJ ln -s OSF1V4.0D_DBG.OBJ OSF1V5.0_DBG.OBJ ln -s OSF1V4.0D_OPT.OBJ OSF1V5.0_OPT.OBJ ln -s WINNT4.0_DBG.OBJ WINNT5.0_DBG.OBJ ln -s WINNT4.0_DBG.OBJD WINNT5.0_DBG.OBJD ln -s WINNT4.0_OPT.OBJ WINNT5.0_OPT.OBJ # --- end symlinks.sh --------------------------------------------- nspr-4.11/nspr/build/autoconf/README0000644000000000000000000000050312623070344015325 0ustar 00000000000000The config.guess and config.sub scripts were downloaded from http://git.savannah.gnu.org/cgit/config.git/tree/config.guess?id=6947a35648e577c2e3a12d5c88d488c6ea94e1c0 http://git.savannah.gnu.org/cgit/config.git/tree/config.sub?id=6947a35648e577c2e3a12d5c88d488c6ea94e1c0 Our private patches are in the patches/ directory. nspr-4.11/nspr/build/autoconf/config.guess0000755000000000000000000012353612623070344017001 0ustar 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-02-12' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nspr-4.11/nspr/build/autoconf/config.sub0000755000000000000000000010530512623070344016436 0ustar 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2014 Free Software Foundation, Inc. timestamp='2014-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -android*) os=-android ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; *-android*|*-linuxandroid*) vendor=linux- ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nspr-4.11/nspr/build/autoconf/install-sh0000755000000000000000000000452212623070344016456 0ustar 00000000000000#!/bin/sh # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # install - install a program, script, or datafile # This comes from X11R5; it is not part of GNU. # # $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $ # # This script is compatible with the BSD install script, but was written # from scratch. # # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" instcmd="$mvprog" chmodcmd="" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; *) if [ x"$src" = x ] then src=$1 else dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` fi # Make a temp file name in the proper directory. dstdir=`dirname $dst` dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp # and set any options; do chmod last to preserve setuid bits if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi # Now rename the file to the real destination. $doit $rmcmd $dst $doit $mvcmd $dsttmp $dst exit 0 nspr-4.11/nspr/build/autoconf/patches/config.sub.patch0000644000000000000000000000320112623070344021150 0ustar 00000000000000--- config.sub.orig 2014-03-09 18:34:03 -0700 +++ config.sub 2014-03-14 19:49:48 -0700 @@ -115,7 +115,7 @@ # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ @@ -123,10 +123,6 @@ os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -1367,7 +1363,7 @@ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -mingw32* | -mingw64* | -linux-gnu* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ @@ -1508,6 +1504,9 @@ ;; -nacl*) ;; + -android*) + os=-android + ;; -none) ;; *) @@ -1777,6 +1776,9 @@ -vos*) vendor=stratus ;; + *-android*|*-linuxandroid*) + vendor=linux- + ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; nspr-4.11/nspr/build/cygwin-wrapper0000755000000000000000000000443112623070344015537 0ustar 00000000000000#!/bin/sh # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # Stupid wrapper to avoid win32 dospath/cygdrive issues # Try not to spawn programs from within this file. If the stuff in here looks royally # confusing, see bug: http://bugzilla.mozilla.org/show_bug.cgi?id=206643 # and look at the older versions of this file that are easier to read, but # do basically the same thing # prog=$1 shift if test -z "$prog"; then exit 0 fi # If $CYGDRIVE_MOUNT was not set in configure, give $mountpoint the results of mount -p mountpoint=$CYGDRIVE_MOUNT if test -z "$mountpoint"; then mountpoint=`mount -p` if test -z "$mountpoint"; then print "Cannot determine cygwin mount points. Exiting" exit 1 fi fi # Delete everything but "/cygdrive" (or other mountpoint) from mount=`mount -p` mountpoint=${mountpoint#*/} mountpoint=/${mountpoint%%[!A-Za-z0-9_]*} mountpoint=${mountpoint%/} args="" up="" if test "${prog}" = "-up"; then up=1 prog=${1} shift fi process=1 # Convert the mountpoint in parameters to Win32 filenames # For instance: /cygdrive/c/foo -> c:/foo for i in "${@}" do if test "${i}" = "-wrap"; then process=1 else if test "${i}" = "-nowrap"; then process= else if test -n "${process}"; then if test -n "${up}"; then pathname=${i#-I[a-zA-Z]:/} if ! test "${pathname}" = "${i}"; then no_i=${i#-I} driveletter=${no_i%%:*} i=-I${mountpoint}/${driveletter}/${pathname} fi else eval 'leader=${i%%'${mountpoint}'/[a-zA-Z]/*}' if ! test "${leader}" = "${i}"; then eval 'pathname=${i#'${leader}${mountpoint}'/[a-zA-Z]/}' eval 'no_mountpoint=${i#'${leader}${mountpoint}'/}' driveletter=${no_mountpoint%%/*} i=${leader}${driveletter}:/${pathname} fi fi fi args="${args} ${i}" fi fi done exec $prog $args nspr-4.11/nspr/build/win32/pgomerge.py0000644000000000000000000000345012623070344015754 0ustar 00000000000000#!/usr/bin/python # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Usage: pgomerge.py # Gathers .pgc files from dist/bin and merges them into # $PWD/$basename.pgd using pgomgr, then deletes them. # No errors if any of these files don't exist. import sys, os, os.path, subprocess if not sys.platform == "win32": raise Exception("This script was only meant for Windows.") def MergePGOFiles(basename, pgddir, pgcdir): """Merge pgc files produced from an instrumented binary into the pgd file for the second pass of profile-guided optimization with MSVC. |basename| is the name of the DLL or EXE without the extension. |pgddir| is the path that contains .pgd (should be the objdir it was built in). |pgcdir| is the path containing basename!N.pgc files, which is probably dist/bin. Calls pgomgr to merge each pgc file into the pgd, then deletes the pgc files.""" if not os.path.isdir(pgddir) or not os.path.isdir(pgcdir): return pgdfile = os.path.abspath(os.path.join(pgddir, basename + ".pgd")) if not os.path.isfile(pgdfile): return for file in os.listdir(pgcdir): if file.startswith(basename+"!") and file.endswith(".pgc"): try: pgcfile = os.path.normpath(os.path.join(pgcdir, file)) subprocess.call(['pgomgr', '-merge', pgcfile, pgdfile]) os.remove(pgcfile) except OSError: pass if __name__ == '__main__': if len(sys.argv) != 3: print >>sys.stderr, "Usage: pgomerge.py " sys.exit(1) MergePGOFiles(sys.argv[1], os.getcwd(), sys.argv[2]) nspr-4.11/nspr/config/.cvsignore0000644000000000000000000000016412623070344015000 0ustar 00000000000000nfspwd revdepth my_config.mk my_overrides.mk autoconf.mk nsprincl.mk nsprincl.sh now Makefile nsinstall nspr-config nspr-4.11/nspr/config/Makefile.in0000644000000000000000000000603012623070344015043 0ustar 00000000000000#! gmake # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOD_DEPTH = .. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk # Indicate that this directory builds build tools. INTERNAL_TOOLS = 1 # For sanity's sake, we compile nsinstall without the wrapped system # headers, so that we can use it to set up the wrapped system headers. VISIBILITY_FLAGS = # autoconf.mk must be deleted last (from the top-level directory) # because it is included by every makefile. DIST_GARBAGE = nsprincl.mk nsprincl.sh nspr-config nspr.pc RELEASE_BINS = nspr-config include $(topsrcdir)/config/config.mk CSRCS = now.c # This version hasn't been ported for us; the one in mozilla/config has ifneq ($(OS_ARCH),OS2) CSRCS += nsinstall.c PLSRCS = nfspwd.pl endif ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2,$(OS_ARCH))) PROG_SUFFIX = .exe else PROG_SUFFIX = endif # Temporary workaround to disable the generation of # library build time because now.c uses the 'long long' # data type that's not available on some platforms. ifeq (,$(filter-out QNX SCOOS UNIXWARE,$(OS_ARCH))) DEFINES += -DOMIT_LIB_BUILD_TIME endif ifeq ($(OS_ARCH), IRIX) ifeq ($(basename $(OS_RELEASE)),6) ifndef NS_USE_GCC ifeq ($(USE_N32),1) XLDOPTS += -n32 -Wl,-woff,85 else ifeq ($(USE_64),1) XLDOPTS += -64 else XLDOPTS += -32 endif endif endif endif endif ifeq ($(OS_ARCH), HP-UX) ifeq ($(USE_64),1) XLDOPTS += +DD64 endif endif ifeq ($(OS_ARCH), OS2) XCFLAGS = $(OS_CFLAGS) endif include $(topsrcdir)/config/rules.mk PROGS = $(OBJDIR)/now$(PROG_SUFFIX) ifeq (,$(CROSS_COMPILE)$(filter-out OS2 WINNT,$(OS_ARCH))) TARGETS = $(PROGS) else ifeq (,$(filter-out SYMBIAN WINCE,$(OS_ARCH))) TARGETS = $(PROGS) else PROGS += $(OBJDIR)/nsinstall$(PROG_SUFFIX) TARGETS = $(PROGS) $(PLSRCS:.pl=) endif endif OUTOPTION = -o # end of the line ifeq (,$(filter-out WINNT WIN95 WINCE,$(OS_TARGET))) ifndef NS_USE_GCC OUTOPTION = -Fe endif endif # Redefine MAKE_OBJDIR for just this directory define MAKE_OBJDIR if test ! -d $(@D); then rm -rf $(@D); mkdir $(@D); else true; fi endef export:: $(TARGETS) rm -f $(dist_bindir)/nspr-config ifdef WRAP_SYSTEM_INCLUDES export:: if test ! -d system_wrappers; then mkdir system_wrappers; fi $(PERL) $(srcdir)/make-system-wrappers.pl system_wrappers < $(srcdir)/system-headers $(INSTALL) system_wrappers $(dist_includedir) endif $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) $(CC) $(XCFLAGS) $< $(LDFLAGS) $(XLDOPTS) $(OUTOPTION)$@ install:: nspr.m4 $(NSINSTALL) -D $(DESTDIR)$(datadir)/aclocal $(NSINSTALL) -t -m 0644 $< $(DESTDIR)$(datadir)/aclocal install:: nspr.pc $(NSINSTALL) -D $(DESTDIR)$(libdir)/pkgconfig $(NSINSTALL) -t -m 0644 $< $(DESTDIR)$(libdir)/pkgconfig nspr-4.11/nspr/config/autoconf.mk.in0000644000000000000000000000662312623070344015562 0ustar 00000000000000# -*- Mode: Makefile -*- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. INCLUDED_AUTOCONF_MK = 1 USE_AUTOCONF = 1 @SHELL_OVERRIDE@ MOZILLA_CLIENT = @MOZILLA_CLIENT@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ includedir = @includedir@ libdir = @libdir@ datarootdir = @datarootdir@ datadir = @datadir@ dist_prefix = @dist_prefix@ dist_bindir = @dist_bindir@ dist_includedir = @dist_includedir@ dist_libdir = @dist_libdir@ DIST = $(dist_prefix) RELEASE_OBJDIR_NAME = @RELEASE_OBJDIR_NAME@ OBJDIR_NAME = @OBJDIR_NAME@ OBJDIR = @OBJDIR@ # We do magic with OBJ_SUFFIX in config.mk, the following ensures we don't # manually use it before config.mk inclusion OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX) _OBJ_SUFFIX = @OBJ_SUFFIX@ LIB_SUFFIX = @LIB_SUFFIX@ DLL_SUFFIX = @DLL_SUFFIX@ ASM_SUFFIX = @ASM_SUFFIX@ MOD_NAME = @NSPR_MODNAME@ MOD_MAJOR_VERSION = @MOD_MAJOR_VERSION@ MOD_MINOR_VERSION = @MOD_MINOR_VERSION@ MOD_PATCH_VERSION = @MOD_PATCH_VERSION@ LIBNSPR = @LIBNSPR@ LIBPLC = @LIBPLC@ CROSS_COMPILE = @CROSS_COMPILE@ MOZ_OPTIMIZE = @MOZ_OPTIMIZE@ MOZ_DEBUG = @MOZ_DEBUG@ MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@ USE_CPLUS = @USE_CPLUS@ USE_IPV6 = @USE_IPV6@ USE_N32 = @USE_N32@ USE_X32 = @USE_X32@ USE_64 = @USE_64@ ENABLE_STRIP = @ENABLE_STRIP@ USE_PTHREADS = @USE_PTHREADS@ USE_BTHREADS = @USE_BTHREADS@ PTHREADS_USER = @USE_USER_PTHREADS@ CLASSIC_NSPR = @USE_NSPR_THREADS@ AS = @AS@ ASFLAGS = @ASFLAGS@ CC = @CC@ CCC = @CXX@ NS_USE_GCC = @GNU_CC@ GCC_USE_GNU_LD = @GCC_USE_GNU_LD@ MSC_VER = @MSC_VER@ AR = @AR@ AR_FLAGS = @AR_FLAGS@ LD = @LD@ RANLIB = @RANLIB@ PERL = @PERL@ RC = @RC@ RCFLAGS = @RCFLAGS@ STRIP = @STRIP@ NSINSTALL = @NSINSTALL@ FILTER = @FILTER@ IMPLIB = @IMPLIB@ CYGWIN_WRAPPER = @CYGWIN_WRAPPER@ MT = @MT@ OS_CPPFLAGS = @CPPFLAGS@ OS_CFLAGS = $(OS_CPPFLAGS) @CFLAGS@ $(DSO_CFLAGS) OS_CXXFLAGS = $(OS_CPPFLAGS) @CXXFLAGS@ $(DSO_CFLAGS) OS_LIBS = @OS_LIBS@ OS_LDFLAGS = @LDFLAGS@ OS_DLLFLAGS = @OS_DLLFLAGS@ DLLFLAGS = @DLLFLAGS@ EXEFLAGS = @EXEFLAGS@ OPTIMIZER = @OPTIMIZER@ PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@ PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@ PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@ PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@ MKSHLIB = @MKSHLIB@ WRAP_LDFLAGS = @WRAP_LDFLAGS@ DSO_CFLAGS = @DSO_CFLAGS@ DSO_LDOPTS = @DSO_LDOPTS@ RESOLVE_LINK_SYMBOLS = @RESOLVE_LINK_SYMBOLS@ HOST_CC = @HOST_CC@ HOST_CFLAGS = @HOST_CFLAGS@ HOST_LDFLAGS = @HOST_LDFLAGS@ DEFINES = @DEFINES@ @DEFS@ MDCPUCFG_H = @MDCPUCFG_H@ PR_MD_CSRCS = @PR_MD_CSRCS@ PR_MD_ASFILES = @PR_MD_ASFILES@ PR_MD_ARCH_DIR = @PR_MD_ARCH_DIR@ CPU_ARCH = @CPU_ARCH@ OS_TARGET = @OS_TARGET@ OS_ARCH = @OS_ARCH@ OS_RELEASE = @OS_RELEASE@ OS_TEST = @OS_TEST@ NOSUCHFILE = @NOSUCHFILE@ AIX_LINK_OPTS = @AIX_LINK_OPTS@ MOZ_OBJFORMAT = @MOZ_OBJFORMAT@ ULTRASPARC_LIBRARY = @ULTRASPARC_LIBRARY@ OBJECT_MODE = @OBJECT_MODE@ ifdef OBJECT_MODE export OBJECT_MODE endif VISIBILITY_FLAGS = @VISIBILITY_FLAGS@ WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@ MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@ ifdef MACOSX_DEPLOYMENT_TARGET export MACOSX_DEPLOYMENT_TARGET endif MACOS_SDK_DIR = @MACOS_SDK_DIR@ SYMBIAN_SDK_DIR = @SYMBIAN_SDK_DIR@ NEXT_ROOT = @NEXT_ROOT@ ifdef NEXT_ROOT export NEXT_ROOT endif nspr-4.11/nspr/config/config.mk0000644000000000000000000001026012623070344014574 0ustar 00000000000000#! gmake # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Configuration information for building in the NSPR source module # Define an include-at-most-once-flag NSPR_CONFIG_MK = 1 # # The variable definitions in this file are inputs to NSPR's # build system. This file, if present, is included at the # beginning of config.mk. # # For example: # # MOZ_OPTIMIZE=1 # USE_PTHREADS=1 # NS_USE_GCC= # ifndef topsrcdir topsrcdir=$(MOD_DEPTH) endif ifndef srcdir srcdir=. endif NFSPWD = $(MOD_DEPTH)/config/nfspwd CFLAGS = $(VISIBILITY_FLAGS) $(CC_ONLY_FLAGS) $(OPTIMIZER)\ $(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS) CCCFLAGS = $(VISIBILITY_FLAGS) $(CCC_ONLY_FLAGS) $(OPTIMIZER)\ $(OS_CFLAGS) $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS) # For purify NOMD_CFLAGS = $(CC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS) NOMD_CCFLAGS = $(CCC_ONLY_FLAGS) $(OPTIMIZER) $(NOMD_OS_CFLAGS)\ $(XP_DEFINE) $(DEFINES) $(INCLUDES) $(XCFLAGS) LDFLAGS = $(OS_LDFLAGS) # Enable profile-guided optimization ifndef NO_PROFILE_GUIDED_OPTIMIZE ifdef MOZ_PROFILE_GENERATE CFLAGS += $(PROFILE_GEN_CFLAGS) LDFLAGS += $(PROFILE_GEN_LDFLAGS) DLLFLAGS += $(PROFILE_GEN_LDFLAGS) ifeq (WINNT,$(OS_ARCH)) AR_FLAGS += -LTCG endif endif # MOZ_PROFILE_GENERATE ifdef MOZ_PROFILE_USE CFLAGS += $(PROFILE_USE_CFLAGS) LDFLAGS += $(PROFILE_USE_LDFLAGS) DLLFLAGS += $(PROFILE_USE_LDFLAGS) ifeq (WINNT,$(OS_ARCH)) AR_FLAGS += -LTCG endif endif # MOZ_PROFILE_USE endif # NO_PROFILE_GUIDED_OPTIMIZE define MAKE_OBJDIR if test ! -d $(@D); then rm -rf $(@D); $(NSINSTALL) -D $(@D); fi endef LINK_DLL = $(LD) $(OS_DLLFLAGS) $(DLLFLAGS) ifeq ($(OS_ARCH),Darwin) PWD := $(shell pwd) endif ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2, $(OS_ARCH))) INSTALL = $(NSINSTALL) else ifeq ($(NSDISTMODE),copy) # copy files, but preserve source mtime INSTALL = $(NSINSTALL) -t else ifeq ($(NSDISTMODE),absolute_symlink) # install using absolute symbolic links ifeq ($(OS_ARCH),Darwin) INSTALL = $(NSINSTALL) -L $(PWD) else INSTALL = $(NSINSTALL) -L `$(NFSPWD)` endif else # install using relative symbolic links INSTALL = $(NSINSTALL) -R endif endif endif # (WINNT || OS2) && !CROSS_COMPILE DEPENDENCIES = $(OBJDIR)/.md ifdef BUILD_DEBUG_GC DEFINES += -DDEBUG_GC endif GARBAGE += $(DEPENDENCIES) core $(wildcard core.[0-9]*) DIST_GARBAGE += Makefile #################################################################### # # The NSPR-specific configuration # #################################################################### DEFINES += -DFORCE_PR_LOG ifeq ($(_PR_NO_CLOCK_TIMER),1) DEFINES += -D_PR_NO_CLOCK_TIMER endif ifeq ($(USE_PTHREADS), 1) DEFINES += -D_PR_PTHREADS -UHAVE_CVAR_BUILT_ON_SEM endif ifeq ($(PTHREADS_USER), 1) DEFINES += -DPTHREADS_USER -UHAVE_CVAR_BUILT_ON_SEM endif ifeq ($(USE_IPV6),1) DEFINES += -D_PR_INET6 endif ifeq ($(MOZ_UNICODE),1) DEFINES += -DMOZ_UNICODE endif #################################################################### # # Configuration for the release process # #################################################################### MDIST = /m/dist ifeq ($(OS_ARCH),WINNT) MDIST = //helium/dist MDIST_DOS = $(subst /,\\,$(MDIST)) endif # RELEASE_DIR is ns/dist/ RELEASE_DIR = $(MOD_DEPTH)/dist/release/$(MOD_NAME) RELEASE_INCLUDE_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/include RELEASE_BIN_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/bin RELEASE_LIB_DIR = $(RELEASE_DIR)/$(BUILD_NUMBER)/$(OBJDIR_NAME)/lib # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including # this file OBJ_SUFFIX := $(_OBJ_SUFFIX) # PGO builds with GCC build objects with instrumentation in a first pass, # then objects optimized, without instrumentation, in a second pass. If # we overwrite the ojects from the first pass with those from the second, # we end up not getting instrumentation data for better optimization on # incremental builds. As a consequence, we use a different object suffix # for the first pass. ifdef MOZ_PROFILE_GENERATE ifdef NS_USE_GCC OBJ_SUFFIX := i_o endif endif nspr-4.11/nspr/config/gcc_hidden.h0000644000000000000000000000043512623070344015221 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Begin all files as hidden visibility */ #pragma GCC visibility push(hidden) nspr-4.11/nspr/config/libc_r.h0000644000000000000000000000755312623070344014414 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* libc_r.h -- macros, defines, etc. to make using reentrant libc calls */ /* a bit easier. This was initially done for AIX pthreads, */ /* but should be usable for anyone... */ /* Most of these use locally defined space instead of static library space. */ /* Because of this, we use the _INIT_R to declare/allocate space (stack), */ /* and the plain routines to actually do it..._WARNING_: avoid allocating */ /* memory wherever possible. Memory allocation is fairly expensive, at */ /* least on AIX...use arrays instead (which allocate from the stack.) */ /* I know the names are a bit strange, but I wanted to be fairly certain */ /* that we didn't have any namespace corruption...in general, the inits are */ /* R__INIT_R(), and the actual calls are R__R(). */ #ifndef _LIBC_R_H #define _LIBC_R_H /************/ /* strtok */ /************/ #define R_STRTOK_INIT_R() \ char *r_strtok_r=NULL #define R_STRTOK_R(return,source,delim) \ return=strtok_r(source,delim,&r_strtok_r) #define R_STRTOK_NORET_R(source,delim) \ strtok_r(source,delim,&r_strtok_r) /**************/ /* strerror */ /**************/ #define R_MAX_STRERROR_LEN_R 8192 /* Straight from limits.h */ #define R_STRERROR_INIT_R() \ char r_strerror_r[R_MAX_STRERROR_LEN_R] #define R_STRERROR_R(val) \ strerror_r(val,r_strerror_r,R_MAX_STRERROR_LEN_R) /*****************/ /* time things */ /*****************/ #define R_ASCTIME_INIT_R() \ char r_asctime_r[26] #define R_ASCTIME_R(val) \ asctime_r(val,r_asctime_r) #define R_CTIME_INIT_R() \ char r_ctime_r[26] #define R_CTIME_R(val) \ ctime_r(val,r_ctime_r) #define R_GMTIME_INIT_R() \ struct tm r_gmtime_r #define R_GMTIME_R(time) \ gmtime_r(time,&r_gmtime_r) #define R_LOCALTIME_INIT_R() \ struct tm r_localtime_r #define R_LOCALTIME_R(val) \ localtime_r(val,&r_localtime_r) /***********/ /* crypt */ /***********/ #include #define R_CRYPT_INIT_R() \ CRYPTD r_cryptd_r; \ bzero(&r_cryptd_r,sizeof(CRYPTD)) #define R_CRYPT_R(pass,salt) \ crypt_r(pass,salt,&r_cryptd_r) /**************/ /* pw stuff */ /**************/ #define R_MAX_PW_LEN_R 1024 /* The following must be after the last declaration, but */ /* before the first bit of code... */ #define R_GETPWNAM_INIT_R(pw_ptr) \ struct passwd r_getpwnam_pw_r; \ char r_getpwnam_line_r[R_MAX_PW_LEN_R]; \ pw_ptr = &r_getpwnam_pw_r #define R_GETPWNAM_R(name) \ getpwnam_r(name,&r_getpwnam_pw_r,r_getpwnam_line_r,R_MAX_PW_LEN_R) /*******************/ /* gethost stuff */ /*******************/ #define R_GETHOSTBYADDR_INIT_R() \ struct hostent r_gethostbyaddr_r; \ struct hostent_data r_gethostbyaddr_data_r #define R_GETHOSTBYADDR_R(addr,len,type,xptr_ent) \ bzero(&r_gethostbyaddr_r,sizeof(struct hostent)); \ bzero(&r_gethostbyaddr_data_r,sizeof(struct hostent_data)); \ xptr_ent = &r_gethostbyaddr_r; \ if (gethostbyaddr_r(addr,len,type, \ &r_gethostbyaddr_r,&r_gethostbyaddr_data_r) == -1) { \ xptr_ent = NULL; \ } #define R_GETHOSTBYNAME_INIT_R() \ struct hostent r_gethostbyname_r; \ struct hostent_data r_gethostbyname_data_r #define R_GETHOSTBYNAME_R(name,xptr_ent) \ bzero(&r_gethostbyname_r,sizeof(struct hostent)); \ bzero(&r_gethostbyname_data_r,sizeof(struct hostent_data)); \ xptr_ent = &r_gethostbyname_r; \ if (gethostbyname_r(name, \ &r_gethostbyname_r,&r_gethostbyname_data_r) == -1) { \ xptr_ent = NULL; \ } #endif /* _LIBC_R_H */ nspr-4.11/nspr/config/make-system-wrappers.pl0000644000000000000000000000120312623070344017430 0ustar 00000000000000#!/usr/bin/perl # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. $output_dir = shift; while () { chomp; if (-e "$output_dir/$_") { next; } if (/(.*)\/[^\/*]/) { mkdir "$output_dir/$1"; } open OUT, ">$output_dir/$_"; print OUT "#pragma GCC system_header\n"; # suppress include_next warning print OUT "#pragma GCC visibility push(default)\n"; print OUT "#include_next \<$_\>\n"; print OUT "#pragma GCC visibility pop\n"; close OUT; } nspr-4.11/nspr/config/nfspwd.pl0000644000000000000000000000100612623070344014632 0ustar 00000000000000#! perl # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. require "fastcwd.pl"; $_ = &fastcwd; if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) { print("$_\n"); } elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o) && readlink("/u/$user") eq "/usr/people/$user") { print("/u/$user/$rest\n"); } else { chop($host = `hostname`); print("/h/$host$_\n"); } nspr-4.11/nspr/config/now.c0000644000000000000000000000220712623070344013747 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include int main(int argc, char **argv) { #if defined(OMIT_LIB_BUILD_TIME) /* * Some platforms don't have any 64-bit integer type * such as 'long long'. Because we can't use NSPR's * PR_snprintf in this program, it is difficult to * print a static initializer for PRInt64 (a struct). * So we print nothing. The makefiles that build the * shared libraries will detect the empty output string * of this program and omit the library build time * in PRVersionDescription. */ #elif defined(_MSC_VER) __int64 now; time_t sec; sec = time(NULL); now = (1000000i64) * sec; fprintf(stdout, "%I64d", now); #else long long now; time_t sec; sec = time(NULL); now = (1000000LL) * sec; fprintf(stdout, "%lld", now); #endif return 0; } /* main */ /* now.c */ nspr-4.11/nspr/config/nsinstall.c0000644000000000000000000002603512623070344015160 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Netscape portable install command. ** ** Brendan Eich, 7/20/95 */ #include /* OSF/1 requires this before grp.h, so put it first */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_REENTRANT_LIBC #include "libc_r.h" #endif /* USE_REENTRANT_LIBC */ #include "pathsub.h" #define HAVE_FCHMOD #if defined(BEOS) #undef HAVE_FCHMOD #endif /* * Does getcwd() take NULL as the first argument and malloc * the result buffer? */ #if !defined(DARWIN) #define GETCWD_CAN_MALLOC #endif #if defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) #include #endif #if defined(SCO) || defined(UNIXWARE) #if !defined(S_ISLNK) && defined(S_IFLNK) #define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK) #endif #endif #ifdef QNX #define d_ino d_stat.st_ino #endif static void usage(void) { fprintf(stderr, "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n" " %*s [-DdltR] file [file ...] directory\n", program, (int)strlen(program), ""); exit(2); } static int mkdirs(char *path, mode_t mode) { char *cp; struct stat sb; int res; while (*path == '/' && path[1] == '/') path++; for (cp = strrchr(path, '/'); cp && cp != path && cp[-1] == '/'; cp--) ; if (cp && cp != path) { *cp = '\0'; if ((stat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) && mkdirs(path, mode) < 0) { return -1; } *cp = '/'; } res = mkdir(path, mode); if ((res != 0) && (errno == EEXIST)) return 0; else return res; } static uid_t touid(char *owner) { struct passwd *pw; uid_t uid; char *cp; pw = getpwnam(owner); if (pw) return pw->pw_uid; uid = strtol(owner, &cp, 0); if (uid == 0 && cp == owner) fail("cannot find uid for %s", owner); return uid; } static gid_t togid(char *group) { struct group *gr; gid_t gid; char *cp; gr = getgrnam(group); if (gr) return gr->gr_gid; gid = strtol(group, &cp, 0); if (gid == 0 && cp == group) fail("cannot find gid for %s", group); return gid; } int main(int argc, char **argv) { int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc; mode_t mode = 0755; char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ]; uid_t uid; gid_t gid; struct stat sb, tosb; struct utimbuf utb; program = argv[0]; cwd = linkname = linkprefix = owner = group = 0; onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0; while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) { switch (opt) { case 'C': cwd = optarg; break; case 'D': onlydir = 1; break; case 'd': dodir = 1; break; case 'l': dolink = 1; break; case 'L': linkprefix = optarg; lplen = strlen(linkprefix); dolink = 1; break; case 'R': dolink = dorelsymlink = 1; break; case 'm': mode = strtoul(optarg, &cp, 8); if (mode == 0 && cp == optarg) usage(); break; case 'o': owner = optarg; break; case 'g': group = optarg; break; case 't': dotimes = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc < 2 - onlydir) usage(); todir = argv[argc-1]; if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) && mkdirs(todir, 0777) < 0) { fail("cannot make directory %s", todir); } if (onlydir) return 0; if (!cwd) { #ifdef GETCWD_CAN_MALLOC cwd = getcwd(0, PATH_MAX); #else cwd = malloc(PATH_MAX + 1); cwd = getcwd(cwd, PATH_MAX); #endif } xchdir(todir); #ifdef GETCWD_CAN_MALLOC todir = getcwd(0, PATH_MAX); #else todir = malloc(PATH_MAX + 1); todir = getcwd(todir, PATH_MAX); #endif xchdir(cwd); tdlen = strlen(todir); uid = owner ? touid(owner) : -1; gid = group ? togid(group) : -1; while (--argc > 0) { name = *argv++; len = strlen(name); base = xbasename(name); bnlen = strlen(base); toname = (char*)xmalloc(tdlen + 1 + bnlen + 1); sprintf(toname, "%s/%s", todir, base); exists = (lstat(toname, &tosb) == 0); if (dodir) { /* -d means create a directory, always */ if (exists && !S_ISDIR(tosb.st_mode)) { (void) unlink(toname); exists = 0; } if (!exists && mkdir(toname, mode) < 0) fail("cannot make directory %s", toname); if ((owner || group) && chown(toname, uid, gid) < 0) fail("cannot change owner of %s", toname); } else if (dolink) { if (*name == '/') { /* source is absolute pathname, link to it directly */ linkname = 0; } else { if (linkprefix) { /* -L implies -l and prefixes names with a $cwd arg. */ len += lplen + 1; linkname = (char*)xmalloc(len + 1); sprintf(linkname, "%s/%s", linkprefix, name); } else if (dorelsymlink) { /* Symlink the relative path from todir to source name. */ linkname = (char*)xmalloc(PATH_MAX); if (*todir == '/') { /* todir is absolute: skip over common prefix. */ lplen = relatepaths(todir, cwd, linkname); strcpy(linkname + lplen, name); } else { /* todir is named by a relative path: reverse it. */ reversepath(todir, name, len, linkname); xchdir(cwd); } len = strlen(linkname); } name = linkname; } /* Check for a pre-existing symlink with identical content. */ if (exists && (!S_ISLNK(tosb.st_mode) || readlink(toname, buf, sizeof buf) != len || strncmp(buf, name, len) != 0)) { (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname); exists = 0; } if (!exists && symlink(name, toname) < 0) fail("cannot make symbolic link %s", toname); #ifdef HAVE_LCHOWN if ((owner || group) && lchown(toname, uid, gid) < 0) fail("cannot change owner of %s", toname); #endif if (linkname) { free(linkname); linkname = 0; } } else { /* Copy from name to toname, which might be the same file. */ fromfd = open(name, O_RDONLY); if (fromfd < 0 || fstat(fromfd, &sb) < 0) fail("cannot access %s", name); if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0)) (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname); tofd = open(toname, O_CREAT | O_WRONLY, 0666); if (tofd < 0) fail("cannot create %s", toname); bp = buf; while ((cc = read(fromfd, bp, sizeof buf)) > 0) { while ((wc = write(tofd, bp, cc)) > 0) { if ((cc -= wc) == 0) break; bp += wc; } if (wc < 0) fail("cannot write to %s", toname); } if (cc < 0) fail("cannot read from %s", name); if (ftruncate(tofd, sb.st_size) < 0) fail("cannot truncate %s", toname); if (dotimes) { utb.actime = sb.st_atime; utb.modtime = sb.st_mtime; if (utime(toname, &utb) < 0) fail("cannot set times of %s", toname); } #ifdef HAVE_FCHMOD if (fchmod(tofd, mode) < 0) #else if (chmod(toname, mode) < 0) #endif fail("cannot change mode of %s", toname); if ((owner || group) && fchown(tofd, uid, gid) < 0) fail("cannot change owner of %s", toname); /* Must check for delayed (NFS) write errors on close. */ if (close(tofd) < 0) fail("cannot write to %s", toname); close(fromfd); } free(toname); } free(cwd); free(todir); return 0; } /* ** Pathname subroutines. ** ** Brendan Eich, 8/29/95 */ char *program; void fail(char *format, ...) { int error; va_list ap; #ifdef USE_REENTRANT_LIBC R_STRERROR_INIT_R(); #endif error = errno; fprintf(stderr, "%s: ", program); va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); if (error) #ifdef USE_REENTRANT_LIBC R_STRERROR_R(errno); fprintf(stderr, ": %s", r_strerror_r); #else fprintf(stderr, ": %s", strerror(errno)); #endif putc('\n', stderr); exit(1); } char * getcomponent(char *path, char *name) { if (*path == '\0') return 0; if (*path == '/') { *name++ = '/'; } else { do { *name++ = *path++; } while (*path != '/' && *path != '\0'); } *name = '\0'; while (*path == '/') path++; return path; } #ifdef UNIXWARE_READDIR_BUFFER_TOO_SMALL /* Sigh. The static buffer in Unixware's readdir is too small. */ struct dirent * readdir(DIR *d) { static struct dirent *buf = NULL; #define MAX_PATH_LEN 1024 if(buf == NULL) buf = (struct dirent *) malloc(sizeof(struct dirent) + MAX_PATH_LEN) ; return(readdir_r(d, buf)); } #endif char * ino2name(ino_t ino, char *dir) { DIR *dp; struct dirent *ep; char *name; dp = opendir(".."); if (!dp) fail("cannot read parent directory"); for (;;) { if (!(ep = readdir(dp))) fail("cannot find current directory"); if (ep->d_ino == ino) break; } name = xstrdup(ep->d_name); closedir(dp); return name; } void * xmalloc(size_t size) { void *p = malloc(size); if (!p) fail("cannot allocate %u bytes", size); return p; } char * xstrdup(char *s) { return strcpy((char*)xmalloc(strlen(s) + 1), s); } char * xbasename(char *path) { char *cp; while ((cp = strrchr(path, '/')) && cp[1] == '\0') *cp = '\0'; if (!cp) return path; return cp + 1; } void xchdir(char *dir) { if (chdir(dir) < 0) fail("cannot change directory to %s", dir); } int relatepaths(char *from, char *to, char *outpath) { char *cp, *cp2; int len; char buf[NAME_MAX]; assert(*from == '/' && *to == '/'); for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++) if (*cp == '\0') break; while (cp[-1] != '/') cp--, cp2--; if (cp - 1 == to) { /* closest common ancestor is /, so use full pathname */ len = strlen(strcpy(outpath, to)); if (outpath[len] != '/') { outpath[len++] = '/'; outpath[len] = '\0'; } } else { len = 0; while ((cp2 = getcomponent(cp2, buf)) != 0) { strcpy(outpath + len, "../"); len += 3; } while ((cp = getcomponent(cp, buf)) != 0) { sprintf(outpath + len, "%s/", buf); len += strlen(outpath + len); } } return len; } void reversepath(char *inpath, char *name, int len, char *outpath) { char *cp, *cp2; char buf[NAME_MAX]; struct stat sb; cp = strcpy(outpath + PATH_MAX - (len + 1), name); cp2 = inpath; while ((cp2 = getcomponent(cp2, buf)) != 0) { if (strcmp(buf, ".") == 0) continue; if (strcmp(buf, "..") == 0) { if (stat(".", &sb) < 0) fail("cannot stat current directory"); name = ino2name(sb.st_ino, ".."); len = strlen(name); cp -= len + 1; strcpy(cp, name); cp[len] = '/'; free(name); xchdir(".."); } else { cp -= 3; strncpy(cp, "../", 3); xchdir(buf); } } strcpy(outpath, cp); } nspr-4.11/nspr/config/nspr-config.in0000755000000000000000000000501612623070344015561 0ustar 00000000000000#!/bin/sh # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. prefix=@prefix@ major_version=@MOD_MAJOR_VERSION@ minor_version=@MOD_MINOR_VERSION@ patch_version=@MOD_PATCH_VERSION@ usage() { cat <&2 fi lib_nspr=yes lib_plc=yes lib_plds=yes while test $# -gt 0; do case "$1" in -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac case $1 in --prefix=*) prefix=$optarg ;; --prefix) echo_prefix=yes ;; --exec-prefix=*) exec_prefix=$optarg ;; --exec-prefix) echo_exec_prefix=yes ;; --includedir=*) includedir=$optarg ;; --includedir) echo_includedir=yes ;; --libdir=*) libdir=$optarg ;; --libdir) echo_libdir=yes ;; --version) echo ${major_version}.${minor_version}.${patch_version} ;; --cflags) echo_cflags=yes ;; --libs) echo_libs=yes ;; nspr) lib_nspr=yes ;; plc) lib_plc=yes ;; plds) lib_plds=yes ;; *) usage 1 1>&2 ;; esac shift done # Set variables that may be dependent upon other variables if test -z "$exec_prefix"; then exec_prefix=@exec_prefix@ fi if test -z "$includedir"; then includedir=@includedir@ fi if test -z "$libdir"; then libdir=@libdir@ fi if test "$echo_prefix" = "yes"; then echo $prefix fi if test "$echo_exec_prefix" = "yes"; then echo $exec_prefix fi if test "$echo_includedir" = "yes"; then echo $includedir fi if test "$echo_libdir" = "yes"; then echo $libdir fi if test "$echo_cflags" = "yes"; then echo -I$includedir fi if test "$echo_libs" = "yes"; then libdirs=-L$libdir if test -n "$lib_plds"; then libdirs="$libdirs -lplds${major_version}" fi if test -n "$lib_plc"; then libdirs="$libdirs -lplc${major_version}" fi if test -n "$lib_nspr"; then libdirs="$libdirs -lnspr${major_version}" fi os_ldflags="@LDFLAGS@" for i in $os_ldflags ; do if echo $i | grep \^-L >/dev/null; then libdirs="$libdirs $i" fi done echo $libdirs @OS_LIBS@ fi nspr-4.11/nspr/config/nspr.m40000644000000000000000000000541012623070344014223 0ustar 00000000000000# -*- tab-width: 4; -*- # Configure paths for NSPR # Public domain - Chris Seawood 2001-04-05 # Based upon gtk.m4 (also PD) by Owen Taylor dnl AM_PATH_NSPR([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for NSPR, and define NSPR_CFLAGS and NSPR_LIBS AC_DEFUN([AM_PATH_NSPR], [dnl AC_ARG_WITH(nspr-prefix, [ --with-nspr-prefix=PFX Prefix where NSPR is installed], nspr_config_prefix="$withval", nspr_config_prefix="") AC_ARG_WITH(nspr-exec-prefix, [ --with-nspr-exec-prefix=PFX Exec prefix where NSPR is installed], nspr_config_exec_prefix="$withval", nspr_config_exec_prefix="") if test -n "$nspr_config_exec_prefix"; then nspr_config_args="$nspr_config_args --exec-prefix=$nspr_config_exec_prefix" if test -z "$NSPR_CONFIG"; then NSPR_CONFIG=$nspr_config_exec_prefix/bin/nspr-config fi fi if test -n "$nspr_config_prefix"; then nspr_config_args="$nspr_config_args --prefix=$nspr_config_prefix" if test -z "$NSPR_CONFIG"; then NSPR_CONFIG=$nspr_config_prefix/bin/nspr-config fi fi unset ac_cv_path_NSPR_CONFIG AC_PATH_PROG(NSPR_CONFIG, nspr-config, no) min_nspr_version=ifelse([$1], ,4.0.0,$1) AC_MSG_CHECKING(for NSPR - version >= $min_nspr_version) no_nspr="" if test "$NSPR_CONFIG" = "no"; then no_nspr="yes" else NSPR_CFLAGS=`$NSPR_CONFIG $nspr_config_args --cflags` NSPR_LIBS=`$NSPR_CONFIG $nspr_config_args --libs` nspr_config_major_version=`$NSPR_CONFIG $nspr_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` nspr_config_minor_version=`$NSPR_CONFIG $nspr_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` nspr_config_micro_version=`$NSPR_CONFIG $nspr_config_args --version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` min_nspr_major_version=`echo $min_nspr_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` min_nspr_minor_version=`echo $min_nspr_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` min_nspr_micro_version=`echo $min_nspr_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` if test "$nspr_config_major_version" -ne "$min_nspr_major_version"; then no_nspr="yes" elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" && test "$nspr_config_minor_version" -lt "$min_nspr_minor_version"; then no_nspr="yes" elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" && test "$nspr_config_minor_version" -eq "$min_nspr_minor_version" && test "$nspr_config_micro_version" -lt "$min_nspr_micro_version"; then no_nspr="yes" fi fi if test -z "$no_nspr"; then AC_MSG_RESULT(yes) ifelse([$2], , :, [$2]) else AC_MSG_RESULT(no) fi AC_SUBST(NSPR_CFLAGS) AC_SUBST(NSPR_LIBS) ]) nspr-4.11/nspr/config/nspr.pc.in0000644000000000000000000000050312623070344014710 0ustar 00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: NSPR Description: The Netscape Portable Runtime Version: @MOD_MAJOR_VERSION@.@MOD_MINOR_VERSION@.@MOD_PATCH_VERSION@ Libs: -L@libdir@ -lplds@MOD_MAJOR_VERSION@ -lplc@MOD_MAJOR_VERSION@ -lnspr@MOD_MAJOR_VERSION@ Cflags: -I@includedir@ nspr-4.11/nspr/config/nsprincl.mk.in0000644000000000000000000000054012623070344015564 0ustar 00000000000000# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Include in Makefiles to define NSPR variables NSPR_VERSION = @NSPR_VERSION@ NSPR_LIB = -lnspr@NSPR_VERSION@ NSPR_EXTRA_LIBS = @EXTRA_LIBS@ nspr-4.11/nspr/config/nsprincl.sh.in0000644000000000000000000000052512623070344015572 0ustar 00000000000000# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Include in shell scripts to define NSPR variables NSPR_VERSION=@NSPR_VERSION@ NSPR_LIB=-lnspr$NSPR_VERSION NSPR_EXTRA_LIBS="@EXTRA_LIBS@" nspr-4.11/nspr/config/pathsub.h0000644000000000000000000000216512623070344014622 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef pathsub_h___ #define pathsub_h___ /* ** Pathname subroutines. ** ** Brendan Eich, 8/29/95 */ #include #include #ifndef PATH_MAX #define PATH_MAX 1024 #endif /* * Just prevent stupidity */ #undef NAME_MAX #define NAME_MAX 256 extern char *program; extern void fail(char *format, ...); extern char *getcomponent(char *path, char *name); extern char *ino2name(ino_t ino, char *dir); extern void *xmalloc(size_t size); extern char *xstrdup(char *s); extern char *xbasename(char *path); extern void xchdir(char *dir); /* Relate absolute pathnames from and to returning the result in outpath. */ extern int relatepaths(char *from, char *to, char *outpath); /* XXX changes current working directory -- caveat emptor */ extern void reversepath(char *inpath, char *name, int len, char *outpath); #endif /* pathsub_h___ */ nspr-4.11/nspr/config/prdepend.h0000644000000000000000000000101112623070344014742 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A dummy header file that is a dependency for all the object files. * Used to force a full recompilation of NSPR in Mozilla's Tinderbox * depend builds. See comments in rules.mk. */ #error "Do not include this header file." nspr-4.11/nspr/config/rules.mk0000644000000000000000000003450312623070344014467 0ustar 00000000000000#! gmake # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ################################################################################ # We used to have a 4 pass build process. Now we do everything in one pass. # # export - Create generated headers and stubs. Publish public headers to # dist//include. # Create libraries. Publish libraries to dist//lib. # Create programs. # # libs - obsolete. Now a synonym of "export". # # all - the default makefile target. Now a synonym of "export". # # install - Install headers, libraries, and programs on the system. # # Parameters to this makefile (set these before including): # # a) # TARGETS -- the target to create # (defaults to $LIBRARY $PROGRAM) # b) # DIRS -- subdirectories for make to recurse on # (the 'all' rule builds $TARGETS $DIRS) # c) # CSRCS -- .c files to compile # (used to define $OBJS) # d) # PROGRAM -- the target program name to create from $OBJS # ($OBJDIR automatically prepended to it) # e) # LIBRARY -- the target library name to create from $OBJS # ($OBJDIR automatically prepended to it) # ################################################################################ ifndef topsrcdir topsrcdir=$(MOD_DEPTH) endif ifndef srcdir srcdir=. endif ifndef NSPR_CONFIG_MK include $(topsrcdir)/config/config.mk endif ifdef USE_AUTOCONF ifdef CROSS_COMPILE ifdef INTERNAL_TOOLS CC=$(HOST_CC) CCC=$(HOST_CXX) CFLAGS=$(HOST_CFLAGS) CXXFLAGS=$(HOST_CXXFLAGS) LDFLAGS=$(HOST_LDFLAGS) endif endif endif # # This makefile contains rules for building the following kinds of # libraries: # - LIBRARY: a static (archival) library # - SHARED_LIBRARY: a shared (dynamic link) library # - IMPORT_LIBRARY: an import library, used only on Windows and OS/2 # # The names of these libraries can be generated by simply specifying # LIBRARY_NAME and LIBRARY_VERSION. # ifdef LIBRARY_NAME ifeq (,$(filter-out WINNT WINCE OS2,$(OS_ARCH))) # # Win95 and OS/2 require library names conforming to the 8.3 rule. # other platforms do not. # ifeq (,$(filter-out WIN95 WINCE WINMO OS2,$(OS_TARGET))) SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX) SHARED_LIB_PDB = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).pdb ifdef MSC_VER LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX) IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX) else LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX) IMPORT_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX) endif else SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX) SHARED_LIB_PDB = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).pdb LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_s.$(LIB_SUFFIX) IMPORT_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX) endif else LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(LIB_SUFFIX) ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1) SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION)_shr.a else ifdef MKSHLIB SHARED_LIBRARY = $(OBJDIR)/lib$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX) endif endif endif endif ifndef TARGETS ifeq (,$(filter-out WINNT WINCE OS2,$(OS_ARCH))) TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) ifdef MOZ_DEBUG_SYMBOLS ifdef MSC_VER ifneq (,$(filter-out 1100 1200,$(MSC_VER))) TARGETS += $(SHARED_LIB_PDB) endif endif endif else TARGETS = $(LIBRARY) $(SHARED_LIBRARY) endif endif # # OBJS is the list of object files. It can be constructed by # specifying CSRCS (list of C source files) and ASFILES (list # of assembly language source files). # ifndef OBJS OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \ $(addprefix $(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))) endif ALL_TRASH = $(TARGETS) $(OBJS) $(RES) $(filter-out . .., $(OBJDIR)) LOGS TAGS $(GARBAGE) \ $(NOSUCHFILE) \ $(OBJS:.$(OBJ_SUFFIX)=.i_o) \ so_locations ifndef RELEASE_LIBS_DEST RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR) endif define MAKE_IN_DIR $(MAKE) -C $(dir) $@ endef # do not remove the blank line! ifdef DIRS LOOP_OVER_DIRS = $(foreach dir,$(DIRS),$(MAKE_IN_DIR)) endif ################################################################################ all:: export export:: +$(LOOP_OVER_DIRS) libs:: export clean:: rm -rf $(OBJS) $(RES) so_locations $(NOSUCHFILE) $(GARBAGE) +$(LOOP_OVER_DIRS) clobber:: rm -rf $(OBJS) $(RES) $(TARGETS) $(filter-out . ..,$(OBJDIR)) $(GARBAGE) so_locations $(NOSUCHFILE) +$(LOOP_OVER_DIRS) realclean clobber_all:: rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH) +$(LOOP_OVER_DIRS) distclean:: rm -rf $(wildcard *.OBJ *.OBJD) dist $(ALL_TRASH) $(DIST_GARBAGE) +$(LOOP_OVER_DIRS) install:: $(RELEASE_BINS) $(RELEASE_HEADERS) $(RELEASE_LIBS) ifdef RELEASE_BINS $(NSINSTALL) -t -m 0755 $(RELEASE_BINS) $(DESTDIR)$(bindir) endif ifdef RELEASE_HEADERS $(NSINSTALL) -t -m 0644 $(RELEASE_HEADERS) $(DESTDIR)$(includedir)/$(include_subdir) endif ifdef RELEASE_LIBS $(NSINSTALL) -t -m 0755 $(RELEASE_LIBS) $(DESTDIR)$(libdir)/$(lib_subdir) endif +$(LOOP_OVER_DIRS) release:: export ifdef RELEASE_BINS @echo "Copying executable programs and scripts to release directory" @if test -z "$(BUILD_NUMBER)"; then \ echo "BUILD_NUMBER must be defined"; \ false; \ else \ true; \ fi @if test ! -d $(RELEASE_BIN_DIR); then \ rm -rf $(RELEASE_BIN_DIR); \ $(NSINSTALL) -D $(RELEASE_BIN_DIR);\ else \ true; \ fi cp $(RELEASE_BINS) $(RELEASE_BIN_DIR) endif ifdef RELEASE_LIBS @echo "Copying libraries to release directory" @if test -z "$(BUILD_NUMBER)"; then \ echo "BUILD_NUMBER must be defined"; \ false; \ else \ true; \ fi @if test ! -d $(RELEASE_LIBS_DEST); then \ rm -rf $(RELEASE_LIBS_DEST); \ $(NSINSTALL) -D $(RELEASE_LIBS_DEST);\ else \ true; \ fi cp $(RELEASE_LIBS) $(RELEASE_LIBS_DEST) endif ifdef RELEASE_HEADERS @echo "Copying header files to release directory" @if test -z "$(BUILD_NUMBER)"; then \ echo "BUILD_NUMBER must be defined"; \ false; \ else \ true; \ fi @if test ! -d $(RELEASE_HEADERS_DEST); then \ rm -rf $(RELEASE_HEADERS_DEST); \ $(NSINSTALL) -D $(RELEASE_HEADERS_DEST);\ else \ true; \ fi cp $(RELEASE_HEADERS) $(RELEASE_HEADERS_DEST) endif +$(LOOP_OVER_DIRS) alltags: rm -f TAGS tags find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs etags -a find . -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' \) -print | xargs ctags -a $(NFSPWD): cd $(@D); $(MAKE) $(@F) $(PROGRAM): $(OBJS) @$(MAKE_OBJDIR) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) ifdef MOZ_PROFILE_USE # In the second pass, we need to merge the pgc files into the pgd file. # The compiler would do this for us automatically if they were in the right # place, but they're in dist/bin. python $(topsrcdir)/build/win32/pgomerge.py \ $(notdir $(PROGRAM:.exe=)) $(DIST)/bin endif # MOZ_PROFILE_USE $(CC) $(OBJS) -Fe$@ -link $(LDFLAGS) $(OS_LIBS) $(EXTRA_LIBS) ifdef MT @if test -f $@.manifest; then \ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ rm -f $@.manifest; \ fi endif # MSVC with manifest tool ifdef MOZ_PROFILE_GENERATE # touch it a few seconds into the future to work around FAT's # 2-second granularity touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink endif # MOZ_PROFILE_GENERATE else # WINNT && !GCC $(CC) -o $@ $(CFLAGS) $(OBJS) $(LDFLAGS) $(WRAP_LDFLAGS) endif # WINNT && !GCC ifdef ENABLE_STRIP $(STRIP) $@ endif $(LIBRARY): $(OBJS) @$(MAKE_OBJDIR) rm -f $@ $(AR) $(AR_FLAGS) $(OBJS) $(AR_EXTRA_ARGS) $(RANLIB) $@ ifeq ($(OS_TARGET), OS2) $(IMPORT_LIBRARY): $(MAPFILE) rm -f $@ $(IMPLIB) $@ $(MAPFILE) else ifeq (,$(filter-out WIN95 WINCE WINMO,$(OS_TARGET))) # PDBs and import libraries need to depend on the shared library to # order dependencies properly. $(IMPORT_LIBRARY): $(SHARED_LIBRARY) $(SHARED_LIB_PDB): $(SHARED_LIBRARY) endif endif $(SHARED_LIBRARY): $(OBJS) $(RES) $(MAPFILE) @$(MAKE_OBJDIR) rm -f $@ ifeq ($(OS_ARCH)$(OS_RELEASE), AIX4.1) echo "#!" > $(OBJDIR)/lib$(LIBRARY_NAME)_syms nm -B -C -g $(OBJS) \ | awk '/ [T,D] / {print $$3}' \ | sed -e 's/^\.//' \ | sort -u >> $(OBJDIR)/lib$(LIBRARY_NAME)_syms $(LD) $(XCFLAGS) -o $@ $(OBJS) -bE:$(OBJDIR)/lib$(LIBRARY_NAME)_syms \ -bM:SRE -bnoentry $(OS_LIBS) $(EXTRA_LIBS) else # AIX 4.1 ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) ifdef MOZ_PROFILE_USE python $(topsrcdir)/build/win32/pgomerge.py \ $(notdir $(SHARED_LIBRARY:.$(DLL_SUFFIX)=)) $(DIST)/bin endif # MOZ_PROFILE_USE $(LINK_DLL) -MAP $(DLLBASE) $(DLL_LIBS) $(EXTRA_LIBS) $(OBJS) $(RES) ifdef MT @if test -f $@.manifest; then \ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;2; \ rm -f $@.manifest; \ fi endif # MSVC with manifest tool ifdef MOZ_PROFILE_GENERATE touch -t `date +%Y%m%d%H%M.%S -d "now+5seconds"` pgo.relink endif # MOZ_PROFILE_GENERATE else # WINNT && !GCC $(MKSHLIB) $(OBJS) $(RES) $(LDFLAGS) $(WRAP_LDFLAGS) $(EXTRA_LIBS) endif # WINNT && !GCC endif # AIX 4.1 ifdef ENABLE_STRIP $(STRIP) $@ endif ################################################################################ ifdef MOZ_PROFILE_USE ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) # When building with PGO, we have to make sure to re-link # in the MOZ_PROFILE_USE phase if we linked in the # MOZ_PROFILE_GENERATE phase. We'll touch this pgo.relink # file in the link rule in the GENERATE phase to indicate # that we need a relink. $(SHARED_LIBRARY): pgo.relink $(PROGRAM): pgo.relink endif # WINNT && !GCC endif # MOZ_PROFILE_USE ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE)) ifdef NS_USE_GCC # Force rebuilding libraries and programs in both passes because each # pass uses different object files. $(PROGRAM) $(SHARED_LIBRARY) $(LIBRARY): FORCE .PHONY: FORCE endif endif ################################################################################ ifdef MOZ_PROFILE_GENERATE # Clean up profiling data during PROFILE_GENERATE phase export:: ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(foreach pgd,$(wildcard *.pgd),pgomgr -clear $(pgd);) else ifdef NS_USE_GCC -$(RM) *.gcda endif endif endif ################################################################################ ifeq ($(OS_ARCH),WINNT) $(RES): $(RESNAME) @$(MAKE_OBJDIR) # The resource compiler does not understand the -U option. ifdef NS_USE_GCC $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) -o $@ $< else $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES) -Fo$@ $< endif # GCC @echo $(RES) finished endif $(MAPFILE): $(LIBRARY_NAME).def @$(MAKE_OBJDIR) ifeq ($(OS_ARCH),SunOS) grep -v ';-' $< | \ sed -e 's,;+,,' -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,;,' > $@ endif ifeq ($(OS_ARCH),OS2) echo LIBRARY $(LIBRARY_NAME)$(LIBRARY_VERSION) INITINSTANCE TERMINSTANCE > $@ echo PROTMODE >> $@ echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@ echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@ echo EXPORTS >> $@ grep -v ';+' $< | grep -v ';-' | \ sed -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,,' -e 's,\([\t ]*\),\1_,' | \ awk 'BEGIN {ord=1;} { print($$0 " @" ord " RESIDENTNAME"); ord++;}' >> $@ $(ADD_TO_DEF_FILE) endif # # Translate source filenames to absolute paths. This is required for # debuggers under Windows and OS/2 to find source files automatically. # ifeq (,$(filter-out AIX OS2,$(OS_ARCH))) NEED_ABSOLUTE_PATH = 1 endif ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) NEED_ABSOLUTE_PATH = 1 endif ifdef NEED_ABSOLUTE_PATH # The quotes allow absolute paths to contain spaces. pr_abspath = "$(if $(findstring :,$(1)),$(1),$(if $(filter /%,$(1)),$(1),$(CURDIR)/$(1)))" endif $(OBJDIR)/%.$(OBJ_SUFFIX): %.cpp @$(MAKE_OBJDIR) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(CCC) -Fo$@ -c $(CCCFLAGS) $(call pr_abspath,$<) else ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINCE) $(CCC) -Fo$@ -c $(CCCFLAGS) $< else ifdef NEED_ABSOLUTE_PATH $(CCC) -o $@ -c $(CCCFLAGS) $(call pr_abspath,$<) else $(CCC) -o $@ -c $(CCCFLAGS) $< endif endif endif WCCFLAGS1 = $(subst /,\\,$(CFLAGS)) WCCFLAGS2 = $(subst -I,-i=,$(WCCFLAGS1)) WCCFLAGS3 = $(subst -D,-d,$(WCCFLAGS2)) $(OBJDIR)/%.$(OBJ_SUFFIX): %.c @$(MAKE_OBJDIR) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(CC) -Fo$@ -c $(CFLAGS) $(call pr_abspath,$<) else ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINCE) $(CC) -Fo$@ -c $(CFLAGS) $< else ifdef NEED_ABSOLUTE_PATH $(CC) -o $@ -c $(CFLAGS) $(call pr_abspath,$<) else $(CC) -o $@ -c $(CFLAGS) $< endif endif endif $(OBJDIR)/%.$(OBJ_SUFFIX): %.s @$(MAKE_OBJDIR) $(AS) -o $@ $(ASFLAGS) -c $< %.i: %.c $(CC) -C -E $(CFLAGS) $< > $*.i %: %.pl rm -f $@; cp $< $@; chmod +x $@ # # HACK ALERT # # The only purpose of this rule is to pass Mozilla's Tinderbox depend # builds (http://tinderbox.mozilla.org/showbuilds.cgi). Mozilla's # Tinderbox builds NSPR continuously as part of the Mozilla client. # Because NSPR's make depend is not implemented, whenever we change # an NSPR header file, the depend build does not recompile the NSPR # files that depend on the header. # # This rule makes all the objects depend on a dummy header file. # Touch this dummy header file to force the depend build to recompile # everything. # # This rule should be removed when make depend is implemented. # DUMMY_DEPEND_H = $(topsrcdir)/config/prdepend.h $(filter $(OBJDIR)/%.$(OBJ_SUFFIX),$(OBJS)): $(OBJDIR)/%.$(OBJ_SUFFIX): $(DUMMY_DEPEND_H) # END OF HACK ################################################################################ # Special gmake rules. ################################################################################ # # Disallow parallel builds with MSVC < 8 since it can't open the PDB file in # parallel. # ifeq (,$(filter-out 1200 1300 1310,$(MSC_VER))) .NOTPARALLEL: endif # # Re-define the list of default suffixes, so gmake won't have to churn through # hundreds of built-in suffix rules for stuff we don't need. # .SUFFIXES: .SUFFIXES: .a .$(OBJ_SUFFIX) .c .cpp .s .h .i .pl # # Fake targets. Always run these rules, even if a file/directory with that # name already exists. # .PHONY: all alltags clean export install libs realclean release # # List the target pattern of an implicit rule as a dependency of the # special target .PRECIOUS to preserve intermediate files made by # implicit rules whose target patterns match that file's name. # (See GNU Make documentation, Edition 0.51, May 1996, Sec. 10.4, # p. 107.) # .PRECIOUS: $(OBJDIR)/%.$(OBJ_SUFFIX) nspr-4.11/nspr/config/system-headers0000644000000000000000000000352512623070344015664 0ustar 00000000000000Aliases.h arpa/inet.h assert.h bsd/libc.h bsd/syscall.h bstring.h builtin.h c_asm.h cf.h CFBundle.h CFData.h CFDictionary.h CFString.h CFURL.h CodeFragments.h commdlg.h crt_externs.h crypt.h ctype.h descrip.h Devices.h direct.h dirent.h dlfcn.h dl.h DriverServices.h dvidef.h errno.h Errors.h Events.h fcntl.h fibdef.h files.h Files.h float.h Folders.h Gestalt.h getopt.h grp.h ia64/sys/inline.h ifaddrs.h image.h ints.h iodef.h io.h iostream.h kernel/OS.h lib$routines.h limits.h loader.h locale.h LowMem.h MacErrors.h machine/builtins.h machine/clock.h machine/endian.h machine/inline.h mach/mach_init.h mach/mach_host.h mach-o/dyld.h MacTypes.h Math64.h math.h mbstring.h memory.h MixedMode.h model.h mswsock.h Multiprocessing.h mutex.h netdb.h net/if.h netinet/in.h netinet/in_systm.h netinet/tcp.h OpenTptInternet.h OpenTransport.h os2.h OS.h osreldate.h OSUtils.h poll.h PPCToolbox.h Processes.h process.h pthread.h pwd.h QDOffscreen.h Resources.h rld_interface.h rpc/types.h semaphore.h setjmp.h share.h signal.h ssdef.h starlet.h stat.h stdarg.h stddef.h stdio.h stdlib.h string.h stropts.h stsdef.h support/SupportDefs.h support/TLS.h synch.h sys/atomic_op.h syscall.h sys/cfgodm.h sys/file.h sys/filio.h sys/immu.h sys/ioctl.h sys/ipc.h sys/ldr.h sys/locking.h sys/lwp.h sys/mman.h sys/mpctl.h sys/param.h sys/pda.h sys/poll.h sys/prctl.h sys/priv.h sys/procfs.h sys/pstat.h sys/regset.h sys/resource.h sys/sched.h sys/select.h sys/sem.h sys/sendfile.h sys/shm.h sys/socket.h sys/stack.h sys/stat.h sys/statvfs.h sys/syscall.h sys/sysctl.h sys/sysmp.h sys/syssgi.h sys/systeminfo.h sys/timeb.h sys/time.h sys/times.h sys/types.h sys/ucontext.h sys/uio.h sys/utsname.h sys/wait.h task.h TextUtils.h thread.h time.h Timer.h types.h Types.h ucontext.h ucx$inetdef.h ulocks.h unistd.h unix.h unixlib.h utime.h wchar.h winbase.h win/compobj.h windef.h windows.h winsock.h nspr-4.11/nspr/configure0000755000000000000000000102613012623070344013444 0ustar 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="pr/include/nspr.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS MT NEXT_ROOT SYMBIAN_SDK_DIR MACOS_SDK_DIR WRAP_SYSTEM_INCLUDES VISIBILITY_FLAGS CYGWIN_WRAPPER OS_DLLFLAGS EXEFLAGS DLLFLAGS RCFLAGS RC OPTIMIZER NSINSTALL RELEASE_OBJDIR_NAME OBJDIR_NAME OBJDIR ULTRASPARC_LIBRARY MOZ_OBJFORMAT NOSUCHFILE AIX_LINK_OPTS RESOLVE_LINK_SYMBOLS OS_LIBS PROFILE_USE_LDFLAGS PROFILE_USE_CFLAGS PROFILE_GEN_LDFLAGS PROFILE_GEN_CFLAGS IMPLIB FILTER ASFLAGS AR_FLAGS DEFINES MACOSX_DEPLOYMENT_TARGET OS_TEST OS_RELEASE OS_ARCH OS_TARGET DSO_LDOPTS DSO_CFLAGS MKSHLIB WRAP_LDFLAGS ASM_SUFFIX DLL_SUFFIX LIB_SUFFIX OBJ_SUFFIX CPU_ARCH PR_MD_ARCH_DIR PR_MD_ASFILES PR_MD_CSRCS MDCPUCFG_H NSPR_MODNAME MOD_PATCH_VERSION MOD_MINOR_VERSION MOD_MAJOR_VERSION LIBPLC LIBNSPR USE_NSPR_THREADS USE_USER_PTHREADS USE_BTHREADS USE_PTHREADS ENABLE_STRIP OBJECT_MODE USE_64 USE_X32 USE_N32 USE_IPV6 USE_CPLUS MOZ_DEBUG_SYMBOLS MOZ_DEBUG MOZ_OPTIMIZE CROSS_COMPILE MSC_VER GCC_USE_GNU_LD GNU_CC HOST_LDFLAGS HOST_CFLAGS MOZILLA_CLIENT SHELL_OVERRIDE CCACHE EGREP GREP PERL CPP HOST_CC WINDRES STRIP LD AS AR RANLIB ac_ct_CXX CXXFLAGS CXX OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS WHOAMI dist_libdir dist_includedir dist_bindir dist_prefix CC target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_android_ndk with_android_toolchain with_android_version with_android_platform with_gonk with_dist_prefix with_dist_bindir with_dist_includedir with_dist_libdir with_mozilla enable_optimize enable_debug enable_debug_symbols enable_win32_target enable_symbian_target enable_debug_rtl enable_static_rtl enable_n32 enable_x32 enable_64bit enable_mdupdate enable_cplus with_arm_kuser with_macos_sdk enable_macos_target enable_os2_high_mem enable_thumb2 with_thumb with_thumb_interwork with_arch with_fpu with_float_abi with_soft_float with_symbian_sdk with_ccache enable_strip with_pthreads enable_user_pthreads enable_nspr_threads with_bthreads enable_ipv6 enable_wrap_malloc with_wrap_malloc ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-optimize=OPT Enable code optimizations (ie. -O2) --enable-debug=DBG Enable debugging (using compiler flags DBG) --enable-debug-symbols=DBG Enable debugging symbols (using compiler flags DBG) --enable-win32-target=\$t Specify win32 flavor. (WIN95 or WINNT) --enable-symbian-target=\$t Specify symbian flavor. (WINSCW or GCCE) --enable-debug-rtl Use the MSVC debug runtime library --enable-static-rtl Use the MSVC static runtime library --enable-n32 Enable n32 ABI support (IRIX only) --enable-x32 Enable x32 ABI support (x86_64 only) --enable-64bit Enable 64-bit support (on certain platforms) --enable-mdupdate Enable use of certain compilers' mdupdate feature --enable-cplus Enable some c++ api routines --enable-macos-target=VER Set the minimum MacOS version needed at runtime 10.2 for ppc, 10.4 for x86 --disable-os2-high-mem Disable high-memory support on OS/2 --enable-strip Enable stripping of shared libs and programs --enable-user-pthreads Build using userland pthreads --enable-nspr-threads Build using classic nspr threads --enable-ipv6 Compile ipv6 support --enable-wrap-malloc Wrap malloc calls (gnu linker only) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-android-ndk=DIR location where the Android NDK can be found --with-android-toolchain=DIR location of the Android toolchain --with-android-version=VER Android platform version, default 5 for arm, 9 for x86/mips --with-android-platform=DIR location of platform dir --with-gonk=DIR location of gonk dir --with-dist-prefix=DIST_PREFIX place build files in DIST_PREFIX dist --with-dist-bindir=DIR build execuatables in DIR DIST_PREFIX/bin --with-dist-includedir=DIR build include files in DIR DIST_PREFIX/include/nspr --with-dist-libdir=DIR build library files in DIR DIST_PREFIX/lib --with-mozilla Compile NSPR with Mozilla support --with-arm-kuser Use kuser helpers (Linux/ARM only) (Requires kernel 2.6.13 or later) --with-macos-sdk=dir Location of platform SDK to use (Mac OS X only) --with-thumb[=yes|no|toolchain-default] Use Thumb instruction set (-mthumb) --with-thumb-interwork[=yes|no|toolchain-default] Use Thumb/ARM instuctions interwork (-mthumb-interwork) --with-arch=[type|toolchain-default] Use specific CPU features (-march=type) --with-fpu=[type|toolchain-default] Use specific FPU type (-mfpu=type) --with-float-abi=[type|toolchain-default] Use specific arm float ABI (-mfloat-abi=type) --with-soft-float[=yes|no|toolchain-default] Use soft float library (-msoft-float) --with-symbian-sdk=SYMBIAN_SDK_DIR The path to the Symbian SDK --with-ccache=path/to/ccache Enable compiling with ccache --with-pthreads Use system pthreads library as thread subsystem --with-bthreads Use system bthreads library as thread subsystem (BeOS only) --with-wrap-malloc=SHAREDLIB Location of malloc wrapper library Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in ${srcdir}/build/autoconf "$srcdir"/${srcdir}/build/autoconf; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in ${srcdir}/build/autoconf \"$srcdir\"/${srcdir}/build/autoconf" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- MOD_MAJOR_VERSION=4 MOD_MINOR_VERSION=11 MOD_PATCH_VERSION=0 NSPR_MODNAME=nspr20 _HAVE_PTHREADS= USE_PTHREADS= USE_USER_PTHREADS= USE_NSPR_THREADS= USE_N32= USE_X32= USE_64= USE_CPLUS= USE_IPV6= USE_MDUPDATE= _MACOSX_DEPLOYMENT_TARGET= _OPTIMIZE_FLAGS=-O _DEBUG_FLAGS=-g MOZ_DEBUG=1 MOZ_OPTIMIZE= OBJDIR='$(OBJDIR_NAME)' OBJDIR_NAME=. OBJDIR_SUFFIX=OBJ NSINSTALL='$(MOD_DEPTH)/config/$(OBJDIR_NAME)/nsinstall' NOSUCHFILE=/no-such-file LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)' LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)' CYGWIN_WRAPPER= MACOS_SDK_DIR= NEXT_ROOT= MT= MOZ_OS2_HIGH_MEMORY=1 PROFILE_GEN_CFLAGS= PROFILE_GEN_LDFLAGS= PROFILE_USE_CFLAGS= PROFILE_USE_LDFLAGS= RESOLVE_LINK_SYMBOLS= CFLAGS="${CFLAGS=}" CXXFLAGS="${CXXFLAGS=}" LDFLAGS="${LDFLAGS=}" DLLFLAGS="${DLLFLAGS=}" HOST_CFLAGS="${HOST_CFLAGS=}" HOST_LDFLAGS="${HOST_LDFLAGS=}" case "$target" in *-cygwin*|*-mingw*|*-msys*) # Check to see if we are really running in a msvc environemnt _WIN32_MSVC= for ac_prog in cl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done cat > conftest.c </dev/null | grep COMPILER) EOF if test -n "$dummy"; then _WIN32_MSVC=1 CXX=$CC fi rm -f conftest.c ;; *-mks*) _WIN32_MSVC=1 ;; esac if test -n "$_WIN32_MSVC"; then SKIP_PATH_CHECKS=1 SKIP_COMPILER_CHECKS=1 SKIP_LIBRARY_CHECKS=1 fi # Check whether --with-android-ndk was given. if test "${with_android_ndk+set}" = set; then : withval=$with_android_ndk; android_ndk=$withval fi # Check whether --with-android-toolchain was given. if test "${with_android_toolchain+set}" = set; then : withval=$with_android_toolchain; android_toolchain=$withval fi case "$target_cpu" in arm) android_version=5 ;; i?86|mipsel) android_version=9 ;; esac # Check whether --with-android-version was given. if test "${with_android_version+set}" = set; then : withval=$with_android_version; android_version=$withval fi # Check whether --with-android-platform was given. if test "${with_android_platform+set}" = set; then : withval=$with_android_platform; android_platform=$withval fi case "$target" in arm-linux*-android*|*-linuxandroid*) android_tool_prefix="arm-linux-androideabi" ;; i?86-*android*) android_tool_prefix="i686-linux-android" ;; mipsel-*android*) android_tool_prefix="mipsel-linux-android" ;; *) android_tool_prefix="$target_os" ;; esac # Check whether --with-gonk was given. if test "${with_gonk+set}" = set; then : withval=$with_gonk; gonkdir=$withval fi if test -n "$gonkdir" ; then $as_echo "#define ANDROID 1" >>confdefs.h else case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then as_fn_error $? "You must specify --with-android-ndk=/path/to/ndk when targeting Android." "$LINENO" 5 fi if test -z "$android_toolchain" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for android toolchain directory" >&5 $as_echo_n "checking for android toolchain directory... " >&6; } kernel_name=`uname -s | tr "[:upper:]" "[:lower:]"` case "$target_cpu" in arm) target_name=arm-linux-androideabi-4.4.3 ;; i?86) target_name=x86-4.4.3 ;; mipsel) target_name=mipsel-linux-android-4.4.3 ;; esac android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86 if test -d "$android_toolchain" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $android_toolchain" >&5 $as_echo "$android_toolchain" >&6; } else as_fn_error $? "not found. You have to specify --with-android-toolchain=/path/to/ndk/toolchain." "$LINENO" 5 fi fi if test -z "$android_platform" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for android platform directory" >&5 $as_echo_n "checking for android platform directory... " >&6; } case "$target_cpu" in arm) target_name=arm ;; i?86) target_name=x86 ;; mipsel) target_name=mips ;; esac android_platform="$android_ndk"/platforms/android-"$android_version"/arch-"$target_name" if test -d "$android_platform" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $android_platform" >&5 $as_echo "$android_platform" >&6; } else as_fn_error $? "not found. You have to specify --with-android-platform=/path/to/ndk/platform." "$LINENO" 5 fi fi case "$target_cpu" in i?86) if ! test -e "$android_toolchain"/bin/"$android_tool_prefix"-gcc; then android_tool_prefix="i686-android-linux" fi ;; esac AS="$android_toolchain"/bin/"$android_tool_prefix"-as CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp LD="$android_toolchain"/bin/"$android_tool_prefix"-ld AR="$android_toolchain"/bin/"$android_tool_prefix"-ar RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -I$android_platform/usr/include -fpic -fno-short-enums -fno-exceptions $CXXFLAGS" LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform $LDFLAGS" $as_echo "#define ANDROID 1" >>confdefs.h ;; esac fi dist_prefix='${MOD_DEPTH}/dist' dist_bindir='${dist_prefix}/bin' dist_includedir='${dist_prefix}/include/nspr' dist_libdir='${dist_prefix}/lib' if test "${includedir}" = '${prefix}/include'; then includedir='${prefix}/include/nspr' fi # Check whether --with-dist-prefix was given. if test "${with_dist_prefix+set}" = set; then : withval=$with_dist_prefix; dist_prefix=$withval fi # Check whether --with-dist-bindir was given. if test "${with_dist_bindir+set}" = set; then : withval=$with_dist_bindir; dist_bindir=$withval fi # Check whether --with-dist-includedir was given. if test "${with_dist_includedir+set}" = set; then : withval=$with_dist_includedir; dist_includedir=$withval fi # Check whether --with-dist-libdir was given. if test "${with_dist_libdir+set}" = set; then : withval=$with_dist_libdir; dist_libdir=$withval fi # Check whether --with-mozilla was given. if test "${with_mozilla+set}" = set; then : withval=$with_mozilla; if test "$withval" = "yes"; then $as_echo "#define MOZILLA_CLIENT 1" >>confdefs.h MOZILLA_CLIENT=1 else MOZILLA_CLIENT= fi else if test -n "$MOZILLA_CLIENT"; then $as_echo "#define MOZILLA_CLIENT 1" >>confdefs.h fi fi # Check whether --enable-optimize was given. if test "${enable_optimize+set}" = set; then : enableval=$enable_optimize; if test "$enableval" != "no"; then MOZ_OPTIMIZE=1 if test -n "$enableval" -a "$enableval" != "yes"; then _OPTIMIZE_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _SAVE_OPTIMIZE_FLAGS=$_OPTIMIZE_FLAGS fi else MOZ_OPTIMIZE= fi fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; if test "$enableval" != "no"; then MOZ_DEBUG=1 MOZ_DEBUG_SYMBOLS=1 if test -n "$enableval" -a "$enableval" != "yes"; then _DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _SAVE_DEBUG_FLAGS=$_DEBUG_FLAGS fi else MOZ_DEBUG= fi else MOZ_DEBUG_SYMBOLS=1 fi # Check whether --enable-debug-symbols was given. if test "${enable_debug_symbols+set}" = set; then : enableval=$enable_debug_symbols; if test "$enableval" != "no"; then MOZ_DEBUG_SYMBOLS=1 if test -n "$enableval" -a "$enableval" != "yes"; then if test -z "$_SAVE_DEBUG_FLAGS"; then _DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _SAVE_DEBUG_FLAGS=$_DEBUG_FLAGS else as_fn_error $? "--enable-debug-symbols flags cannot be used with --enable-debug flags" "$LINENO" 5 fi fi else MOZ_DEBUG_SYMBOLS= fi fi # Check whether --enable-win32-target was given. if test "${enable_win32_target+set}" = set; then : enableval=$enable_win32_target; OS_TARGET=`echo $enableval | tr a-z A-Z` fi # Check whether --enable-symbian-target was given. if test "${enable_symbian_target+set}" = set; then : enableval=$enable_symbian_target; OS_TARGET=`echo $enableval | tr a-z A-Z` fi # Check whether --enable-debug-rtl was given. if test "${enable_debug_rtl+set}" = set; then : enableval=$enable_debug_rtl; if test "$enableval" = "yes"; then USE_DEBUG_RTL=1 else USE_DEBUG_RTL=0 fi fi # Check whether --enable-static-rtl was given. if test "${enable_static_rtl+set}" = set; then : enableval=$enable_static_rtl; if test "$enableval" = "yes"; then USE_STATIC_RTL=1 fi fi # Check whether --enable-n32 was given. if test "${enable_n32+set}" = set; then : enableval=$enable_n32; if test "$enableval" = "yes"; then USE_N32=1 else if test "$enableval" = "no"; then USE_N32= fi fi fi # Check whether --enable-x32 was given. if test "${enable_x32+set}" = set; then : enableval=$enable_x32; if test "$enableval" = "yes"; then USE_X32=1 else if test "$enableval" = "no"; then USE_X32= fi fi fi # Check whether --enable-64bit was given. if test "${enable_64bit+set}" = set; then : enableval=$enable_64bit; if test "$enableval" = "yes"; then USE_64=1 fi fi # Check whether --enable-mdupdate was given. if test "${enable_mdupdate+set}" = set; then : enableval=$enable_mdupdate; if test "$enableval" = "yes"; then USE_MDUPDATE=1 fi fi # Check whether --enable-cplus was given. if test "${enable_cplus+set}" = set; then : enableval=$enable_cplus; if test "$enableval" = "yes"; then USE_CPLUS=1 fi fi # Check whether --with-arm-kuser was given. if test "${with_arm_kuser+set}" = set; then : withval=$with_arm_kuser; if test "$withval" = "yes"; then $as_echo "#define _PR_ARM_KUSER 1" >>confdefs.h fi fi # Check whether --with-macos-sdk was given. if test "${with_macos_sdk+set}" = set; then : withval=$with_macos_sdk; MACOS_SDK_DIR=$withval fi # Check whether --enable-macos-target was given. if test "${enable_macos_target+set}" = set; then : enableval=$enable_macos_target; _MACOSX_DEPLOYMENT_TARGET=$enableval fi case "$target" in *-aix*) case "${target_os}" in aix3.2*) USE_NSPR_THREADS=1 ;; *) USE_PTHREADS=1 ;; esac ;; esac if test -z "$CC"; then case "$target" in *-aix*) if test -z "$USE_NSPR_THREADS"; then CC=xlc_r else CC=xlc fi ;; *-hpux*) CC=cc ;; *-irix*) CC=cc ;; *-osf*) CC=cc ;; *-solaris*) CC=cc ;; esac fi if test -z "$CXX"; then case "$target" in *-aix*) if test -z "$USE_NSPR_THREADS"; then CXX=xlC_r else CXX=xlC fi ;; *-hpux*) case "${target_os}" in hpux10.30) CXX=aCC ;; hpux11.*) CXX=aCC ;; *) CXX=CC ;; esac ;; *-irix*) CXX=CC ;; *-osf*) CXX=cxx ;; *-solaris*) CXX=CC ;; esac fi if test -z "$SKIP_PATH_CHECKS"; then # Extract the first word of "$WHOAMI whoami", so it can be a program name with args. set dummy $WHOAMI whoami; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_WHOAMI+:} false; then : $as_echo_n "(cached) " >&6 else case $WHOAMI in [\\/]* | ?:[\\/]*) ac_cv_path_WHOAMI="$WHOAMI" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_WHOAMI="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_WHOAMI" && ac_cv_path_WHOAMI="echo not_whoami" ;; esac fi WHOAMI=$ac_cv_path_WHOAMI if test -n "$WHOAMI"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WHOAMI" >&5 $as_echo "$WHOAMI" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -n "$MOZ_DEBUG"; then $as_echo "#define DEBUG 1" >>confdefs.h DEFINES="$DEFINES -UNDEBUG" case "${target_os}" in beos*) DEFINES="$DEFINES -DDEBUG_${USER}" ;; mks*|cygwin*|mingw*|msys*|os2*) DEFINES="$DEFINES -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`" ;; *) DEFINES="$DEFINES -DDEBUG_`$WHOAMI`" ;; esac else $as_echo "#define NDEBUG 1" >>confdefs.h DEFINES="$DEFINES -UDEBUG" fi if test -z "$SKIP_COMPILER_CHECKS"; then if test "$target" != "$host"; then echo "cross compiling from $host to $target" cross_compiling=yes case "$build:$target" in powerpc-apple-darwin8*:i?86-apple-darwin*) _SAVE_CFLAGS=$CFLAGS _SAVE_CXXFLAGS=$CXXFLAGS CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CFLAGS" CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS" ;; esac for ac_prog in $CC "${target_alias}-gcc" "${target}-gcc" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done test -n "$CC" || CC="echo" unset ac_cv_prog_CC fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$target" != "$host"; then if test -n "$USE_CPLUS"; then for ac_prog in $CXX "${target_alias}-g++" "${target}-g++" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done test -n "$CXX" || CXX="echo" unset ac_cv_prog_CXX ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi case "$build:$target" in powerpc-apple-darwin8*:i?86-apple-darwin*|*:arm*-apple-darwin*) CFLAGS=$_SAVE_CFLAGS CXXFLAGS=$_SAVE_CXXFLAGS ;; esac for ac_prog in $RANLIB "${target_alias}-ranlib" "${target}-ranlib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$RANLIB" && break done test -n "$RANLIB" || RANLIB="echo" for ac_prog in $AR "${target_alias}-ar" "${target}-ar" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done test -n "$AR" || AR="echo" for ac_prog in $AS "${target_alias}-as" "${target}-as" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AS+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AS"; then ac_cv_prog_AS="$AS" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AS="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AS=$ac_cv_prog_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AS" && break done test -n "$AS" || AS="echo" for ac_prog in $LD "${target_alias}-ld" "${target}-ld" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LD"; then ac_cv_prog_LD="$LD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LD="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LD=$ac_cv_prog_LD if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LD" && break done test -n "$LD" || LD="echo" for ac_prog in $STRIP "${target_alias}-strip" "${target}-strip" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$STRIP" && break done test -n "$STRIP" || STRIP="echo" for ac_prog in $WINDRES "${target_alias}-windres" "${target}-windres" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_WINDRES+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$WINDRES"; then ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_WINDRES="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi WINDRES=$ac_cv_prog_WINDRES if test -n "$WINDRES"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 $as_echo "$WINDRES" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$WINDRES" && break done test -n "$WINDRES" || WINDRES="echo" _SAVE_CC="$CC" _SAVE_CFLAGS="$CFLAGS" _SAVE_LDFLAGS="$LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $host compiler" >&5 $as_echo_n "checking for $host compiler... " >&6; } for ac_prog in $HOST_CC gcc cc /usr/ucb/cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_HOST_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$HOST_CC"; then ac_cv_prog_HOST_CC="$HOST_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_HOST_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi HOST_CC=$ac_cv_prog_HOST_CC if test -n "$HOST_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HOST_CC" >&5 $as_echo "$HOST_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$HOST_CC" && break done test -n "$HOST_CC" || HOST_CC="""" if test -z "$HOST_CC"; then as_fn_error $? "no acceptable cc found in \$PATH" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HOST_CC" >&5 $as_echo "$HOST_CC" >&6; } CC="$HOST_CC" CFLAGS="$HOST_CFLAGS" LDFLAGS="$HOST_LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works" >&5 $as_echo_n "checking whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else as_fn_error $? "installation or configuration problem: $host compiler $HOST_CC cannot create executables." "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CC=$_SAVE_CC CFLAGS=$_SAVE_CFLAGS LDFLAGS=$_SAVE_LDFLAGS else if test -n "$USE_CPLUS"; then if test "$CC" = "cl" -a -z "$CXX"; then CXX=$CC else ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi for ac_prog in as do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_AS+:} false; then : $as_echo_n "(cached) " >&6 else case $AS in [\\/]* | ?:[\\/]*) ac_cv_path_AS="$AS" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_AS="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AS=$ac_cv_path_AS if test -n "$AS"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 $as_echo "$AS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AS" && break done test -n "$AS" || AS="$CC" for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_AR+:} false; then : $as_echo_n "(cached) " >&6 else case $AR in [\\/]* | ?:[\\/]*) ac_cv_path_AR="$AR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AR=$ac_cv_path_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done test -n "$AR" || AR="echo not_ar" for ac_prog in ld link do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else case $LD in [\\/]* | ?:[\\/]*) ac_cv_path_LD="$LD" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_LD="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi LD=$ac_cv_path_LD if test -n "$LD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LD" && break done test -n "$LD" || LD="echo not_ld" for ac_prog in strip do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else case $STRIP in [\\/]* | ?:[\\/]*) ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi STRIP=$ac_cv_path_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$STRIP" && break done test -n "$STRIP" || STRIP="echo not_strip" for ac_prog in windres do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_WINDRES+:} false; then : $as_echo_n "(cached) " >&6 else case $WINDRES in [\\/]* | ?:[\\/]*) ac_cv_path_WINDRES="$WINDRES" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_WINDRES="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi WINDRES=$ac_cv_path_WINDRES if test -n "$WINDRES"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 $as_echo "$WINDRES" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$WINDRES" && break done test -n "$WINDRES" || WINDRES="echo not_windres" if test -z "$HOST_CC"; then HOST_CC="$CC" fi if test -z "$HOST_CFLAGS"; then HOST_CFLAGS="$CFLAGS" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$GCC" = "yes"; then GNU_CC=1 fi if test "$GXX" = "yes"; then GNU_CXX=1 fi if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then GNU_AS=1 fi rm -f a.out case "$build:$target" in i?86-apple-darwin*:powerpc-apple-darwin*) cross_compiling=yes ;; esac if test "$cross_compiling" = "yes"; then CROSS_COMPILE=1 else CROSS_COMPILE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc -pipe support" >&5 $as_echo_n "checking for gcc -pipe support... " >&6; } if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then echo '#include ' > dummy-hello.c echo 'int main() { printf("Hello World\n"); return 0; }' >> dummy-hello.c ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5 cat dummy-hello.s | ${AS} -o dummy-hello.S - 2>&5 if test $? = 0; then _res_as_stdin="yes" else _res_as_stdin="no" fi if test "$_res_as_stdin" = "yes"; then _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { printf("Hello World\n"); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : _res_gcc_pipe="yes" else _res_gcc_pipe="no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS=$_SAVE_CFLAGS fi if test "$_res_as_stdin" = "yes" && test "$_res_gcc_pipe" = "yes"; then _res="yes"; CFLAGS="$CFLAGS -pipe" CXXFLAGS="$CXXFLAGS -pipe" else _res="no" fi rm -f dummy-hello.c dummy-hello.s dummy-hello.S dummy-hello a.out { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_res" >&5 $as_echo "$_res" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fprofile-generate -fprofile-correction" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler supports -fprofile-generate" >&5 $as_echo_n "checking whether C compiler supports -fprofile-generate... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : PROFILE_GEN_CFLAGS="-fprofile-generate" result="yes" else result="no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $result" >&5 $as_echo "$result" >&6; } if test $result = "yes"; then PROFILE_GEN_LDFLAGS="-fprofile-generate" PROFILE_USE_CFLAGS="-fprofile-use -fprofile-correction -Wcoverage-mismatch" PROFILE_USE_LDFLAGS="-fprofile-use" fi CFLAGS="$_SAVE_CFLAGS" if test "$GNU_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for visibility(hidden) attribute" >&5 $as_echo_n "checking for visibility(hidden) attribute... " >&6; } if ${ac_cv_visibility_hidden+:} false; then : $as_echo_n "(cached) " >&6 else cat > conftest.c </dev/null 2>&1; then if grep '\.hidden.*foo' conftest.s >/dev/null; then ac_cv_visibility_hidden=yes fi fi rm -f conftest.cs fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_visibility_hidden" >&5 $as_echo "$ac_cv_visibility_hidden" >&6; } if test "$ac_cv_visibility_hidden" = "yes"; then $as_echo "#define HAVE_VISIBILITY_HIDDEN_ATTRIBUTE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for visibility pragma support" >&5 $as_echo_n "checking for visibility pragma support... " >&6; } if ${ac_cv_visibility_pragma+:} false; then : $as_echo_n "(cached) " >&6 else cat > conftest.c </dev/null 2>&1; then if grep '\.hidden.*foo_hidden' conftest.s >/dev/null; then if ! grep '\.hidden.*foo_default' conftest.s > /dev/null; then ac_cv_visibility_pragma=yes fi fi fi rm -f conftest.cs fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_visibility_pragma" >&5 $as_echo "$ac_cv_visibility_pragma" >&6; } if test "$ac_cv_visibility_pragma" = "yes"; then $as_echo "#define HAVE_VISIBILITY_PRAGMA 1" >>confdefs.h # To work around a build problem on Linux x86-64 (Bugzilla bug # 293438), we use the -fvisibility=hidden flag. This flag is less # optimal than #pragma GCC visibility push(hidden) because the flag # assumes that symbols defined outside the current source file have # the default visibility. This has the advantage that we don't need # to wrap system header files, but has the disadvantage that calls # to hidden symbols defined in other source files cannot be # optimized by the compiler. The -fvisibility=hidden flag does # hide and export symbols correctly. #VISIBILITY_FLAGS='-I$(dist_includedir)/system_wrappers -include $(topsrcdir)/config/gcc_hidden.h' #WRAP_SYSTEM_INCLUDES=1 VISIBILITY_FLAGS="-fvisibility=hidden" WRAP_SYSTEM_INCLUDES= fi fi fi # GNU_CC fi # SKIP_COMPILER_CHECKS if test -z "$SKIP_PATH_CHECKS"; then for ac_prog in perl5 perl do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PERL+:} false; then : $as_echo_n "(cached) " >&6 else case $PERL in [\\/]* | ?:[\\/]*) ac_cv_path_PERL="$PERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PERL=$ac_cv_path_PERL if test -n "$PERL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 $as_echo "$PERL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$PERL" && break done test -n "$PERL" || PERL="echo not_perl" elif test -z "$PERL"; then PERL=perl fi OBJ_SUFFIX=o LIB_SUFFIX=a DLL_SUFFIX=so ASM_SUFFIX=s MKSHLIB='$(LD) $(DSO_LDOPTS) -o $@' PR_MD_ASFILES= PR_MD_CSRCS= PR_MD_ARCH_DIR=unix AR_FLAGS='cr $@' AS='$(CC)' ASFLAGS='$(CFLAGS)' if test -n "$CROSS_COMPILE"; then OS_ARCH=`echo $target_os | sed -e 's|/|_|g'` OS_RELEASE= OS_TEST="${target_cpu}" case "${target_os}" in linux*) OS_ARCH=Linux ;; solaris*) OS_ARCH=SunOS OS_RELEASE=5 ;; mingw*) OS_ARCH=WINNT CPU_ARCH=x86 ;; darwin*) OS_ARCH=Darwin ;; riscos*) OS_ARCH=RISCOS ;; esac else OS_ARCH=`uname -s | sed -e 's|/|_|g'` OS_RELEASE=`uname -r` OS_TEST=`uname -m` fi if test "$OS_ARCH" = "IRIX64"; then OS_ARCH=IRIX fi if test "$OS_ARCH" = "AIX"; then OS_RELEASE=`uname -v`.`uname -r` fi if test "$OS_ARCH" = "FreeBSD"; then OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'` fi if test "$OS_ARCH" = "Linux"; then OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'` OS_RELEASE=`echo $OS_RELEASE | awk -F\. '{ print $1 "." $2 }'` fi ####################################################################### # Master "Core Components" macros for getting the OS target # ####################################################################### # # Note: OS_TARGET should be specified on the command line for gmake. # When OS_TARGET=WIN95 is specified, then a Windows 95 target is built. # The difference between the Win95 target and the WinNT target is that # the WinNT target uses Windows NT specific features not available # in Windows 95. The Win95 target will run on Windows NT, but (supposedly) # at lesser performance (the Win95 target uses threads; the WinNT target # uses fibers). # # If OS_TARGET is not specified, it defaults to $(OS_ARCH), i.e., no # cross-compilation. # # # The following hack allows one to build on a WIN95 machine (as if # s/he were cross-compiling on a WINNT host for a WIN95 target). # It also accomodates for MKS's uname.exe. If you never intend # to do development on a WIN95 machine, you don't need this hack. # case "$OS_ARCH" in Windows_95) OS_ARCH=Windows_NT OS_TARGET=WIN95 ;; Windows_98) OS_ARCH=Windows_NT OS_TARGET=WIN95 ;; CYGWIN_9*|CYGWIN_ME*) OS_ARCH='CYGWIN_NT-4.0' OS_TARGET=WIN95 ;; OS_2) OS_ARCH=OS2 OS_TARGET=OS2 ;; esac # # On WIN32, we also define the variable CPU_ARCH. # case "$OS_ARCH" in Windows_NT) # # If uname -s returns "Windows_NT", we assume that we are using # the uname.exe in MKS toolkit. # # The -r option of MKS uname only returns the major version number. # So we need to use its -v option to get the minor version number. # Moreover, it doesn't have the -p option, so we need to use uname -m. # OS_ARCH=WINNT OS_MINOR_RELEASE=`uname -v` if test "$OS_MINOR_RELEASE" = "00"; then OS_MINOR_RELEASE=0 fi OS_RELEASE="${OS_RELEASE}.${OS_MINOR_RELEASE}" CPU_ARCH=`uname -m` # # MKS's uname -m returns "586" on a Pentium machine. # if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then CPU_ARCH=x86 fi ;; CYGWIN_NT*|MINGW*_NT*|MSYS_NT*) # # If uname -s returns "CYGWIN_NT-4.0", we assume that we are using # the uname.exe in the Cygwin tools. # If uname -s returns "MINGW32_NT-5.1", we assume that we are using # the uname.exe in the MSYS tools. # If uname -s returns "MSYS_NT-6.3", we assume that we are using # the uname.exe in the MSYS2 tools. # OS_RELEASE=`expr $OS_ARCH : '.*NT-\(.*\)'` OS_ARCH=WINNT CPU_ARCH=`uname -m` # # Cygwin's uname -m returns "i686" on a Pentium Pro machine. # if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then CPU_ARCH=x86 fi ;; esac if test -n "$MOZILLA_CLIENT" && test "$OS_ARCH" = "WINNT"; then OS_TARGET=WIN95 if test -n "$MOZ_DEBUG" -a -z "$USE_DEBUG_RTL"; then USE_DEBUG_RTL=1 fi fi if test -z "$OS_TARGET"; then OS_TARGET=$OS_ARCH fi if test "$OS_TARGET" = "WIN95"; then OS_RELEASE="4.0" fi OS_CONFIG="${OS_TARGET}${OS_RELEASE}" # Check whether --enable-os2-high-mem was given. if test "${enable_os2_high_mem+set}" = set; then : enableval=$enable_os2_high_mem; if test "$enableval" = "no"; then MOZ_OS2_HIGH_MEMORY= else MOZ_OS2_HIGH_MEMORY=1 fi fi MOZ_ALIGN=toolchain-default case "$target" in arm*-android*|arm*-linuxandroid*) MOZ_THUMB=yes MOZ_ARCH=armv7-a MOZ_FPU=vfp MOZ_FLOAT_ABI=softfp MOZ_SOFT_FLOAT=yes MOZ_ALIGN=no ;; arm*-*) if test -n "$MOZ_PLATFORM_MAEMO"; then MOZ_THUMB=no MOZ_ARCH=armv7-a MOZ_FLOAT_ABI=softfp fi if test "$MOZ_PLATFORM_MAEMO" = 6; then MOZ_THUMB=yes fi ;; esac # Check whether --enable-thumb2 was given. if test "${enable_thumb2+set}" = set; then : enableval=$enable_thumb2; MOZ_THUMB=$enableval fi # Check whether --with-thumb was given. if test "${with_thumb+set}" = set; then : withval=$with_thumb; if test -z "$GNU_CC"; then as_fn_error $? "--with-thumb is not supported on non-GNU toolchain-defaults" "$LINENO" 5 fi MOZ_THUMB=$withval fi # Check whether --with-thumb-interwork was given. if test "${with_thumb_interwork+set}" = set; then : withval=$with_thumb_interwork; if test -z "$GNU_CC"; then as_fn_error $? "--with-thumb-interwork is not supported on non-GNU toolchain-defaults" "$LINENO" 5 fi MOZ_THUMB_INTERWORK=$withval fi # Check whether --with-arch was given. if test "${with_arch+set}" = set; then : withval=$with_arch; if test -z "$GNU_CC"; then as_fn_error $? "--with-arch is not supported on non-GNU toolchain-defaults" "$LINENO" 5 fi MOZ_ARCH=$withval fi # Check whether --with-fpu was given. if test "${with_fpu+set}" = set; then : withval=$with_fpu; if test -z "$GNU_CC"; then as_fn_error $? "--with-fpu is not supported on non-GNU toolchain-defaults" "$LINENO" 5 fi MOZ_FPU=$withval fi # Check whether --with-float-abi was given. if test "${with_float_abi+set}" = set; then : withval=$with_float_abi; if test -z "$GNU_CC"; then as_fn_error $? "--with-float-abi is not supported on non-GNU toolchain-defaults" "$LINENO" 5 fi MOZ_FLOAT_ABI=$withval fi # Check whether --with-soft-float was given. if test "${with_soft_float+set}" = set; then : withval=$with_soft_float; if test -z "$GNU_CC"; then as_fn_error $? "--with-soft-float is not supported on non-GNU toolchain-defaults" "$LINENO" 5 fi MOZ_SOFT_FLOAT=$withval fi case "$MOZ_ARCH" in toolchain-default|"") arch_flag="" ;; *) arch_flag="-march=$MOZ_ARCH" ;; esac case "$MOZ_THUMB" in yes) MOZ_THUMB2=1 thumb_flag="-mthumb" ;; no) MOZ_THUMB2= thumb_flag="-marm" ;; *) _SAVE_CFLAGS="$CFLAGS" CFLAGS="$arch_flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return sizeof(__thumb2__); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : MOZ_THUMB2=1 else MOZ_THUMB2= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$_SAVE_CFLAGS" thumb_flag="" ;; esac case "$MOZ_THUMB_INTERWORK" in yes) thumb_interwork_flag="-mthumb-interwork" ;; no) thumb_interwork_flag="-mno-thumb-interwork" ;; *) # toolchain-default thumb_interwork_flag="" ;; esac case "$MOZ_FPU" in toolchain-default|"") fpu_flag="" ;; *) fpu_flag="-mfpu=$MOZ_FPU" ;; esac case "$MOZ_FLOAT_ABI" in toolchain-default|"") float_abi_flag="" ;; *) float_abi_flag="-mfloat-abi=$MOZ_FLOAT_ABI" ;; esac case "$MOZ_SOFT_FLOAT" in yes) soft_float_flag="-msoft-float" ;; no) soft_float_flag="-mno-soft-float" ;; *) # toolchain-default soft_float_flag="" ;; esac case "$MOZ_ALIGN" in toolchain-default|"") align_flag="" ;; no) align_flag="-mno-unaligned-access" ;; yes) align_flag="-munaligned-access" ;; *) align_flag="" ;; esac if test -n "$align_flag"; then _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $align_flag" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether alignment flag ($align_flag) is supported" >&5 $as_echo_n "checking whether alignment flag ($align_flag) is supported... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else align_flag="" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$_SAVE_CFLAGS" fi all_flags=`echo $arch_flag $thumb_flag $thumb_interwork_flag $fpu_flag $float_abi_flag $soft_float_flag $align_flag` if test -n "$all_flags"; then _SAVE_CFLAGS="$CFLAGS" CFLAGS="$all_flags" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the chosen combination of compiler flags ($all_flags) works" >&5 $as_echo_n "checking whether the chosen combination of compiler flags ($all_flags) works... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else as_fn_error $? "no" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$_SAVE_CFLAGS $all_flags" CXXFLAGS="$CXXFLAGS $all_flags" ASFLAGS="$ASFLAGS $all_flags" if test -n "$thumb_flag"; then LDFLAGS="$LDFLAGS $thumb_flag" fi fi case "$host" in *-mingw*|*-msys*) NSINSTALL=nsinstall ;; *-cygwin*|*-mks*) NSINSTALL='$(CYGWIN_WRAPPER) nsinstall' if test `echo "${PATH}" | grep -c \;` = 0; then CYGWIN_WRAPPER='sh $(topsrcdir)/build/cygwin-wrapper' fi ;; *-beos*) HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE" ;; *os2*) ;; *) HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX" ;; esac case "$target" in *-aix*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define AIX 1" >>confdefs.h $as_echo "#define SYSV 1" >>confdefs.h DSO_LDOPTS='-brtl -bnortllib -bM:SRE -bnoentry -bexpall -blibpath:/usr/lib:/lib' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "sys/atomic_op.h" "ac_cv_header_sys_atomic_op_h" "$ac_includes_default" if test "x$ac_cv_header_sys_atomic_op_h" = xyes; then : $as_echo "#define AIX_HAVE_ATOMIC_OP_H 1" >>confdefs.h fi case "${target_os}" in aix3.2*) $as_echo "#define AIX_RENAME_SELECT 1" >>confdefs.h $as_echo "#define _PR_NO_LARGE_FILES 1" >>confdefs.h AIX_LINK_OPTS='-bnso -berok' PR_MD_ASFILES=os_AIX.s ;; aix4.1*) $as_echo "#define AIX_TIMERS 1" >>confdefs.h $as_echo "#define _PR_NO_LARGE_FILES 1" >>confdefs.h $as_echo "#define AIX4_1 1" >>confdefs.h MKSHLIB= DSO_LDOPTS= AIX_LINK_OPTS='-bnso -berok' LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)_shr' LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)_shr' ;; aix4.2*) $as_echo "#define AIX_TIMERS 1" >>confdefs.h $as_echo "#define _PR_HAVE_OFF64_T 1" >>confdefs.h AIX_LINK_OPTS='-brtl -bnso -berok' ;; aix4.3*) $as_echo "#define AIX_TIMERS 1" >>confdefs.h $as_echo "#define _PR_HAVE_OFF64_T 1" >>confdefs.h $as_echo "#define AIX4_3_PLUS 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h USE_IPV6=1 AIX_LINK_OPTS='-brtl -bnso -berok' ;; *) $as_echo "#define AIX_TIMERS 1" >>confdefs.h $as_echo "#define _PR_HAVE_OFF64_T 1" >>confdefs.h $as_echo "#define AIX4_3_PLUS 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h USE_IPV6=1 AIX_LINK_OPTS='-brtl -bnso -berok' ;; esac CFLAGS="$CFLAGS -qro -qroconst" AIX_WRAP='$(DIST)/lib/aixwrap.o' AIX_TMP='./_aix_tmp.o' if test -n "$USE_64"; then MDCPUCFG_H=_aix64.cfg OBJECT_MODE=64 else MDCPUCFG_H=_aix32.cfg fi PR_MD_CSRCS=aix.c RESOLVE_LINK_SYMBOLS=1 ;; *-beos*) $as_echo "#define XP_BEOS 1" >>confdefs.h $as_echo "#define BeOS 1" >>confdefs.h $as_echo "#define BEOS 1" >>confdefs.h $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h DSO_LDOPTS=-nostart MDCPUCFG_H=_beos.cfg USE_BTHREADS=1 PR_MD_ARCH_DIR=beos RESOLVE_LINK_SYMBOLS=1 case "${target_cpu}" in i*86) _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS='-gdwarf-2 -O0' MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr in -lbind" >&5 $as_echo_n "checking for gethostbyaddr in -lbind... " >&6; } if ${ac_cv_lib_bind_gethostbyaddr+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyaddr (); int main () { return gethostbyaddr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bind_gethostbyaddr=yes else ac_cv_lib_bind_gethostbyaddr=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_gethostbyaddr" >&5 $as_echo "$ac_cv_lib_bind_gethostbyaddr" >&6; } if test "x$ac_cv_lib_bind_gethostbyaddr" = xyes; then : OS_LIBS="$OS_LIBS -lbind -lsocket" fi ;; powerpc) CC=mwcc CCC=mwcc LD=mwld DSO_LDOPTS='-xms -export pragma -init _init_routine_ -term _term_routine_ -lroot -lnet /boot/develop/lib/ppc/glue-noinit.a /boot/develop/lib/ppc/init_term_dyn.o /boot/develop/lib/ppc/start_dyn.o' _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS='-g -O0' ;; esac ;; *-bsdi*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define BSDI 1" >>confdefs.h $as_echo "#define NEED_BSDREGEX 1" >>confdefs.h CFLAGS="$CFLAGS -Wall -Wno-format" CXXFLAGS="$CXXFLAGS -Wall -Wno-format" if echo "$OS_TEST" | grep -c 86 >/dev/null; then CPU_ARCH=x86 elif echo "$OS_TEST" | grep -c sparc >/dev/null; then CPU_ARCH=sparc fi MDCPUCFG_H=_bsdi.cfg PR_MD_CSRCS=bsdi.c DSO_LDOPTS=-r case "$target_os" in bsdi1.1*) $as_echo "#define _PR_BSDI_JMPBUF_IS_ARRAY 1" >>confdefs.h $as_echo "#define _PR_STAT_HAS_ONLY_ST_ATIME 1" >>confdefs.h $as_echo "#define _PR_NEED_H_ERRNO 1" >>confdefs.h MKSHLIB= DSO_CFLAGS= DSO_LDOPTS= ;; bsdi2.1*) $as_echo "#define _PR_TIMESPEC_HAS_TS_SEC 1" >>confdefs.h $as_echo "#define _PR_BSDI_JMPBUF_IS_ARRAY 1" >>confdefs.h $as_echo "#define HAVE_DLL 1" >>confdefs.h $as_echo "#define USE_DLFCN 1" >>confdefs.h $as_echo "#define _PR_STAT_HAS_ST_ATIMESPEC 1" >>confdefs.h PR_MD_ASFILES=os_BSD_OS_386_2.s ;; bsdi4.* | bsdi5.*) $as_echo "#define _PR_SELECT_CONST_TIMEVAL 1" >>confdefs.h $as_echo "#define _PR_BSDI_JMPBUF_IS_STRUCT 1" >>confdefs.h $as_echo "#define HAVE_DLL 1" >>confdefs.h $as_echo "#define USE_DLFCN 1" >>confdefs.h $as_echo "#define _PR_STAT_HAS_ST_ATIMESPEC 1" >>confdefs.h MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)' DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname,$(@:$(OBJDIR)/%.so=%.so)' STRIP="$STRIP -d" case "$target_os" in bsdi4.2* | bsdi4.3* | bsdi5.*) $as_echo "#define _PR_HAVE_GETPROTO_R 1" >>confdefs.h $as_echo "#define _PR_HAVE_GETPROTO_R_POINTER 1" >>confdefs.h ;; esac ;; *) $as_echo "#define _PR_SELECT_CONST_TIMEVAL 1" >>confdefs.h $as_echo "#define _PR_BSDI_JMPBUF_IS_STRUCT 1" >>confdefs.h $as_echo "#define HAVE_DLL 1" >>confdefs.h $as_echo "#define USE_DLFCN 1" >>confdefs.h $as_echo "#define _PR_STAT_HAS_ST_ATIMESPEC 1" >>confdefs.h ;; esac ;; *-darwin*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define DARWIN 1" >>confdefs.h $as_echo "#define HAVE_BSD_FLOCK 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h AS='$(CC) -x assembler-with-cpp' CFLAGS="$CFLAGS -Wall -fno-common" case "${target_cpu}" in arm*) CPU_ARCH=arm ;; i*86*|x86_64) if test -n "$USE_64"; then CPU_ARCH=x86_64 else CPU_ARCH=i386 fi ;; *) CPU_ARCH=ppc ;; esac if test "`echo $CC | grep -c '\-arch '`" = "0"; then CC="$CC -arch $CPU_ARCH" fi ac_fn_c_check_header_mongrel "$LINENO" "crt_externs.h" "ac_cv_header_crt_externs_h" "$ac_includes_default" if test "x$ac_cv_header_crt_externs_h" = xyes; then : $as_echo "#define HAVE_CRT_EXTERNS_H 1" >>confdefs.h fi DSO_CFLAGS=-fPIC DSO_LDOPTS='-dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name @executable_path/$@ -headerpad_max_install_names' _OPTIMIZE_FLAGS=-O2 MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' STRIP="$STRIP -x -S" DLL_SUFFIX=dylib USE_PTHREADS=1 MDCPUCFG_H=_darwin.cfg PR_MD_CSRCS=darwin.c PR_MD_ASFILES=os_Darwin.s # Add Mac OS X support for loading CFM & CFBundle plugins if test -f "${MACOS_SDK_DIR}/System/Library/Frameworks/Carbon.framework/Carbon"; then $as_echo "#define XP_MACOSX 1" >>confdefs.h OS_TARGET=MacOSX if test -n "$_MACOSX_DEPLOYMENT_TARGET" ; then export MACOSX_DEPLOYMENT_TARGET=$_MACOSX_DEPLOYMENT_TARGET elif test -z "$MACOSX_DEPLOYMENT_TARGET" ; then case "${target_cpu}" in powerpc*) export MACOSX_DEPLOYMENT_TARGET=10.2 ;; i*86*) export MACOSX_DEPLOYMENT_TARGET=10.4 ;; esac fi if test "$MACOS_SDK_DIR"; then if test ! -d "$MACOS_SDK_DIR"; then as_fn_error $? "SDK not found. When using --with-macos-sdk, you must specify a valid SDK. SDKs are installed when the optional cross-development tools are selected during the Xcode/Developer Tools installation." "$LINENO" 5 fi CC_VERSION=`$CC -v 2>&1 | grep 'gcc version'` GCC_VERSION_FULL=`echo $CC_VERSION | $PERL -pe 's/^.*gcc version ([^ ]*).*/$1/'` GCC_VERSION=`echo $GCC_VERSION_FULL | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/$1/;'` GCC_VERSION_MAJOR=`echo $GCC_VERSION_FULL | $PERL -pe 's/(^\d*).*/$1/;'` if test "$GCC_VERSION_MAJOR" -lt "4" ; then SDK_C_FRAMEWORK="-F${MACOS_SDK_DIR}/System/Library/Frameworks" if test -d "${MACOS_SDK_DIR}/Library/Frameworks" ; then SDK_C_FRAMEWORK="$SDK_C_FRAMEWORK -F${MACOS_SDK_DIR}/Library/Frameworks" fi SDK_C_INCLUDE="-isystem ${MACOS_SDK_DIR}/usr/include/gcc/darwin/${GCC_VERSION} -isystem ${MACOS_SDK_DIR}/usr/include ${SDK_C_FRAMEWORK}" CFLAGS="$CFLAGS -nostdinc ${SDK_C_INCLUDE}" CPP="$CPP -nostdinc ${SDK_C_INCLUDE}" HOST_DARWIN_MAJOR=`echo "$build_os" | sed -E -e 's/^darwin([0-9]+).*$/\1/'` if test "$HOST_DARWIN_MAJOR" -lt 9 ; then MACOS_SDK_LIBS="-L${MACOS_SDK_DIR}/usr/lib/gcc/darwin -L${MACOS_SDK_DIR}/usr/lib/gcc/darwin/${GCC_VERSION_FULL} -L${MACOS_SDK_DIR}/usr/lib ${SDK_C_FRAMEWORK}" else MACOS_SDK_LIBS="-Wl,-syslibroot,${MACOS_SDK_DIR}" fi LDFLAGS="${MACOS_SDK_LIBS} $LDFLAGS" export NEXT_ROOT=$MACOS_SDK_DIR if test -n "$CROSS_COMPILE" ; then HOST_CC="NEXT_ROOT= $HOST_CC" HOST_CXX="NEXT_ROOT= $HOST_CXX" fi else CFLAGS="$CFLAGS -isysroot ${MACOS_SDK_DIR}" CPP="$CPP -isysroot ${MACOS_SDK_DIR}" if test "$GCC_VERSION_FULL" != "4.0.0" ; then LDFLAGS="$LDFLAGS -isysroot ${MACOS_SDK_DIR}" else LDFLAGS="$LDFLAGS -Wl,-syslibroot,${MACOS_SDK_DIR}" fi fi fi fi ;; *-dgux*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h $as_echo "#define SVR4 1" >>confdefs.h $as_echo "#define SYSV 1" >>confdefs.h $as_echo "#define DGUX 1" >>confdefs.h $as_echo "#define _DGUX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX4A_DRAFT6_SOURCE 1" >>confdefs.h DSO_LDOPTS=-G _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS= MDCPUCFG_H=_dgux.cfg PR_MD_CSRCS=dgux.c ;; *-freebsd*) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define FREEBSD 1" >>confdefs.h $as_echo "#define HAVE_BSD_FLOCK 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h CFLAGS="$CFLAGS $(DSO_CFLAGS) -ansi -Wall" MOZ_OBJFORMAT=`test -x /usr/bin/objformat && /usr/bin/objformat || echo elf` if test "$MOZ_OBJFORMAT" = "elf"; then DLL_SUFFIX=so else DLL_SUFFIX=so.1.0 fi MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' MDCPUCFG_H=_freebsd.cfg PR_MD_CSRCS=freebsd.c ;; *-hpux*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define HPUX 1" >>confdefs.h $as_echo "#define _HPUX_SOURCE 1" >>confdefs.h # OSF1 and HPUX report the POLLHUP event for a socket when the # shutdown(SHUT_WR) operation is called for the remote end, even though # the socket is still writeable. Use select(), instead of poll(), to # workaround this problem. $as_echo "#define _PR_POLL_WITH_SELECT 1" >>confdefs.h $as_echo "#define _USE_BIG_FDS 1" >>confdefs.h DSO_LDOPTS='-b +h $(notdir $@)' PR_MD_CSRCS=hpux.c if test "$OS_TEST" = "ia64"; then DLL_SUFFIX=so DSO_LDOPTS="$DSO_LDOPTS +b '\$\$ORIGIN'" CPU_ARCH_TAG=_$OS_TEST if test -z "$USE_64"; then COMPILER_TAG=_32 fi PR_MD_ASFILES=os_HPUX_ia64.s else $as_echo "#define hppa 1" >>confdefs.h DLL_SUFFIX=sl PR_MD_ASFILES=os_HPUX.s fi if test -n "$USE_64"; then MDCPUCFG_H=_hpux64.cfg else MDCPUCFG_H=_hpux32.cfg fi if test -z "$GNU_CC"; then CC="$CC -Ae" CXX="$CXX -ext" DSO_CFLAGS=+Z else DSO_CFLAGS=-fPIC ASFLAGS="$ASFLAGS -x assembler-with-cpp" fi if test -n "$MOZILLA_CLIENT"; then DEFAULT_IMPL_STRATEGY=_EMU fi if echo "$OS_RELEASE" | grep ^A.09 >/dev/null; then $as_echo "#define _PR_NEED_H_ERRNO 1" >>confdefs.h $as_echo "#define HPUX9 1" >>confdefs.h DEFAULT_IMPL_STRATEGY=_EMU USE_NSPR_THREADS=1 fi if echo "$OS_RELEASE" | egrep '^(A.09|B.10)' >/dev/null; then $as_echo "#define _PR_NO_LARGE_FILES 1" >>confdefs.h fi if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then $as_echo "#define _PR_NEED_H_ERRNO 1" >>confdefs.h fi if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then $as_echo "#define HAVE_INT_LOCALTIME_R 1" >>confdefs.h fi if echo "$OS_RELEASE" | egrep '^(B.10.30|B.11)' >/dev/null; then $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h fi # HP-UX 11i v2 (B.11.23) or higher case "$OS_RELEASE" in [C-Z]*|B.[2-9]*|B.1[2-9]*|B.11.[3-9]*|B.11.2[3-9]*) USE_IPV6=1 ;; esac if test "$OS_RELEASE" = "B.10.01"; then $as_echo "#define HPUX10 1" >>confdefs.h DEFAULT_IMPL_STRATEGY=_EMU fi if test "$OS_RELEASE" = "B.10.10"; then $as_echo "#define HPUX10 1" >>confdefs.h $as_echo "#define HPUX10_10 1" >>confdefs.h DEFAULT_IMPL_STRATEGY=_PTH fi if test "$OS_RELEASE" = "B.10.20"; then $as_echo "#define HPUX10 1" >>confdefs.h $as_echo "#define HPUX10_20 1" >>confdefs.h if test -z "$GNU_CC"; then CFLAGS="$CFLAGS +DAportable +DS1.1" CXXFLAGS="$CXXFLAGS +DAportable +DS1.1" fi DEFAULT_IMPL_STRATEGY=_PTH fi if test "$OS_RELEASE" = "B.10.30"; then $as_echo "#define HPUX10 1" >>confdefs.h $as_echo "#define HPUX10_30 1" >>confdefs.h if test -z "$GNU_CC"; then CFLAGS="$CFLAGS +DAportable +DS1.1" CXXFLAGS="$CXXFLAGS +DAportable +DS1.1" fi DEFAULT_IMPL_STRATEGY=_PTH fi if echo "$OS_RELEASE" | grep ^B.11 >/dev/null; then $as_echo "#define HPUX10 1" >>confdefs.h $as_echo "#define HPUX11 1" >>confdefs.h $as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h $as_echo "#define _PR_HAVE_OFF64_T 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h if test -z "$GNU_CC"; then if test -z "$USE_64"; then if test "$OS_TEST" = "ia64"; then CFLAGS="$CFLAGS +DD32" CXXFLAGS="$CXXFLAGS +DD32" else CFLAGS="$CFLAGS +DAportable +DS2.0" CXXFLAGS="$CXXFLAGS +DAportable +DS2.0" fi else if test "$OS_TEST" = "ia64"; then CFLAGS="$CFLAGS +DD64" CXXFLAGS="$CXXFLAGS +DD64" else CFLAGS="$CFLAGS +DA2.0W +DS2.0" CXXFLAGS="$CXXFLAGS +DA2.0W +DS2.0" fi fi fi DEFAULT_IMPL_STRATEGY=_PTH fi if test "$DEFAULT_IMPL_STRATEGY" = "_EMU"; then USE_NSPR_THREADS=1 USE_PTHREADS= USE_USER_PTHREADS= elif test "$DEFAULT_IMPL_STRATEGY" = "_PTH"; then USE_PTHREADS=1 if test "$USE_NSPR_THREADS"; then USE_PTHREADS= fi if test "$USE_USER_PTHREADS"; then USE_PTHREADS= fi fi ;; *-irix*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define IRIX 1" >>confdefs.h $as_echo "#define SVR4 1" >>confdefs.h $as_echo "#define _SGI_MP_SOURCE 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h PR_MD_CSRCS=irix.c PR_MD_ASFILES=os_Irix.s MKSHLIB='$(LD) $(DSO_LDOPTS) -rdata_shared -shared -soname $(notdir $@) -o $@' STRIP="$STRIP -f" RESOLVE_LINK_SYMBOLS=1 if test -n "$USE_64"; then MDCPUCFG_H=_irix64.cfg else MDCPUCFG_H=_irix32.cfg fi case "${target_os}" in irix6*) $as_echo "#define IRIX6 1" >>confdefs.h USE_PTHREADS=1 USE_N32=1 COMPILER_TAG=_n32 IMPL_STRATEGY=_PTH ;; irix5*) $as_echo "#define IRIX5 1" >>confdefs.h USE_NSPR_THREADS=1 ;; *) USE_PTHREADS=1 USE_N32=1 ;; esac if test "$GNU_CC"; then AS='$(CC) -Wp,-P -x assembler-with-cpp -D_ASM -mips2 $(INCLUDES)' CFLAGS="$CFLAGS -Wall -Wno-format" _OPTIMIZE_FLAGS="-O6" else if test -n "$USE_N32"; then AS='as -D_ASM $(INCLUDES) -n32' else AS='as -D_ASM $(INCLUDES)' fi CFLAGS="$CFLAGS -fullwarn -xansi" if test "$USE_N32"; then _OPTIMIZE_FLAGS="-O -OPT:Olimit=4000" else _OPTIMIZE_FLAGS="-O -Olimit 4000" fi if test "$USE_MDUPDATE"; then CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)" fi case "${target}" in *-irix6.*) CFLAGS="$CFLAGS -multigot" DSO_LDOPTS="-no_unresolved" if test "$USE_N32"; then CFLAGS="$CFLAGS -n32 -woff 1209" DSO_LDOPTS="$DSO_LDOPTS -n32" else if test "$USE_64"; then CFLAGS="$CFLAGS -64" else CFLAGS="$CFLAGS -32" fi fi ;; *) CFLAGS="$CFLAGS -xgot" ;; esac fi if test "${target_os}" = "irix5.3"; then $as_echo "#define IRIX5_3 1" >>confdefs.h fi case "${target_os}" in irix6.5) if test -z "$GNU_CC"; then CFLAGS="$CFLAGS -mips3" fi $as_echo "#define _PR_HAVE_GETPROTO_R 1" >>confdefs.h $as_echo "#define _PR_HAVE_GETPROTO_R_POINTER 1" >>confdefs.h $as_echo "#define _PR_HAVE_SGI_PRDA_PROCMASK 1" >>confdefs.h ;; irix5*) ;; *) $as_echo "#define _PR_HAVE_SGI_PRDA_PROCMASK 1" >>confdefs.h ;; esac ;; *-linux*|*-gnu*|*-k*bsd*-gnu|*-android*|*-linuxandroid*) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 IMPL_STRATEGY=_PTH fi $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h case "${target}" in *-android*|*-linuxandroid*) OS_TARGET=Android $as_echo "#define LINUX 1" >>confdefs.h ;; *-linux*) $as_echo "#define LINUX 1" >>confdefs.h ;; esac CFLAGS="$CFLAGS -Wall" CXXFLAGS="$CXXFLAGS -Wall" MDCPUCFG_H=_linux.cfg PR_MD_CSRCS=linux.c MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that # combo is not yet good at debugging inlined # functions (even when using DWARF2 as the # debugging format) COMPILER_TAG=_glibc if echo "$OS_TEST" | grep -c 86 >/dev/null; then CPU_ARCH=x86 else CPU_ARCH=$OS_TEST fi CPU_ARCH_TAG=_${CPU_ARCH} case "${target_cpu}" in alpha) $as_echo "#define _ALPHA_ 1" >>confdefs.h $as_echo "#define __alpha 1" >>confdefs.h CFLAGS="$CFLAGS -mieee" CXXFLAGS="$CXXFLAGS -mieee" ;; i*86) $as_echo "#define i386 1" >>confdefs.h PR_MD_ASFILES=os_Linux_x86.s ;; ia64) PR_MD_ASFILES=os_Linux_ia64.s ;; x86_64) if test -n "$USE_64"; then PR_MD_ASFILES=os_Linux_x86_64.s elif test -n "$USE_X32"; then PR_MD_ASFILES=os_Linux_x86_64.s CC="$CC -mx32" CXX="$CXX -mx32" else $as_echo "#define i386 1" >>confdefs.h PR_MD_ASFILES=os_Linux_x86.s CC="$CC -m32" CXX="$CXX -m32" fi ;; ppc|powerpc) PR_MD_ASFILES=os_Linux_ppc.s ;; powerpc64) if test -n "$USE_64"; then CC="$CC -m64" CXX="$CXX -m64" else PR_MD_ASFILES=os_Linux_ppc.s fi ;; m68k) CFLAGS="$CFLAGS -m68020-60" CXXFLAGS="$CXXFLAGS -m68020-60" ;; esac ;; *-mingw*|*-msys*|*-cygwin*|*-mks*) $as_echo "#define XP_PC 1" >>confdefs.h $as_echo "#define WIN32 1" >>confdefs.h PR_MD_ARCH_DIR=windows RESOLVE_LINK_SYMBOLS=1 if test -n "$GNU_CC"; then CC="$CC -mwindows" CXX="$CXX -mwindows" DLL_SUFFIX=dll MKSHLIB='$(CC) -shared -Wl,--export-all-symbols -Wl,--out-implib -Wl,$(IMPORT_LIBRARY) $(DLLBASE) -o $(subst $(OBJDIR)/,,$(SHARED_LIBRARY))' RC=$WINDRES # Use temp file for windres (bug 213281) RCFLAGS='-O coff --use-temp-file' else LD=link AR='lib -NOLOGO -OUT:"$@"' AR_FLAGS= RANLIB='echo not_ranlib' STRIP='echo not_strip' RC=rc.exe GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb' OBJ_SUFFIX=obj LIB_SUFFIX=lib DLL_SUFFIX=dll # Determine compiler version _MSVC_VER_FILTER='s|.* \([0-9]\+\.[0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?\).*|\1|p' CC_VERSION=`${CC} -v 2>&1 | sed -ne "$_MSVC_VER_FILTER"` if test -z "$CC_VERSION"; then as_fn_error $? "Could not determine MSC version." "$LINENO" 5 fi _CC_MAJOR_VERSION=`echo ${CC_VERSION} | awk -F\. '{ print $1 }'` _CC_MINOR_VERSION=`echo ${CC_VERSION} | awk -F\. '{ print $2 }'` _CC_RELEASE=`echo ${CC_VERSION} | awk -F\. '{ print $3 }'` _CC_BUILD=`echo ${CC_VERSION} | awk -F\. '{ print $4 }'` MSC_VER=${_CC_MAJOR_VERSION}${_CC_MINOR_VERSION} if test "$_CC_MAJOR_VERSION" -eq "14"; then if test $_CC_RELEASE -gt 50727; then _USE_DYNAMICBASE=1 elif test $_CC_BUILD -ge 762; then _USE_DYNAMICBASE=1 fi $as_echo "#define _CRT_SECURE_NO_DEPRECATE 1" >>confdefs.h $as_echo "#define _CRT_NONSTDC_NO_DEPRECATE 1" >>confdefs.h elif test $_CC_MAJOR_VERSION -ge 15; then _USE_DYNAMICBASE=1 $as_echo "#define _CRT_SECURE_NO_WARNINGS 1" >>confdefs.h $as_echo "#define _CRT_NONSTDC_NO_WARNINGS 1" >>confdefs.h fi if test -n "$_USE_DYNAMICBASE"; then DLLFLAGS="$DLLFLAGS -DYNAMICBASE" fi # Ensure that mt is Microsoft (R) Manifest Tool and not magnetic # tape manipulation utility (or something else) if test "$MSC_VER" -ge "1400"; then _MSMT_VER_FILTER='s|.* \([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*|\1|p' MSMT_TOOL=`mt 2>&1|grep 'Microsoft (R) Manifest Tool'` if test -n "$MSMT_TOOL"; then MSMANIFEST_TOOL_VERSION=`echo ${MSMT_TOOL}|sed -ne "$_MSMT_VER_FILTER"` if test -z "$MSMANIFEST_TOOL_VERSION"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unknown version of the Microsoft (R) Manifest Tool." >&5 $as_echo "$as_me: WARNING: Unknown version of the Microsoft (R) Manifest Tool." >&2;} fi MT=mt unset MSMT_TOOL else as_fn_error $? "Microsoft (R) Manifest Tool must be in your \$PATH." "$LINENO" 5 fi fi CFLAGS="$CFLAGS -W3 -nologo -GF -Gy" DLLFLAGS="$DLLFLAGS -OUT:\"\$@\"" _DEBUG_FLAGS=-Zi _OPTIMIZE_FLAGS=-O2 PROFILE_GEN_CFLAGS="-GL" PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT" PROFILE_USE_CFLAGS="-GL -wd4624 -wd4952" PROFILE_USE_LDFLAGS="-LTCG:PGUPDATE" if test "$MSC_VER" -ge "1800"; then CFLAGS="$CFLAGS -FS" PROFILE_GEN_CFLAGS="$PROFILE_GEN_CFLAGS -Gw" PROFILE_USE_CFLAGS="$PROFILE_USE_CFLAGS -Gw" fi if test -z "$MOZ_OPTIMIZE"; then CFLAGS="$CFLAGS -Od" fi if test "$USE_DEBUG_RTL" = 1; then if test -n "$USE_STATIC_RTL"; then CFLAGS="$CFLAGS -MTd" else CFLAGS="$CFLAGS -MDd" fi else if test -n "$USE_STATIC_RTL"; then CFLAGS="$CFLAGS -MT" else CFLAGS="$CFLAGS -MD" fi fi if test -n "$MOZ_DEBUG"; then $as_echo "#define _DEBUG 1" >>confdefs.h else DEFINES="$DEFINES -U_DEBUG" fi if test -n "$MOZ_DEBUG_SYMBOLS"; then if test -n "$MOZ_OPTIMIZE"; then DLLFLAGS="$DLLFLAGS -DEBUG -OPT:REF" LDFLAGS="$LDFLAGS -DEBUG -OPT:REF" else DLLFLAGS="$DLLFLAGS -DEBUG" LDFLAGS="$LDFLAGS -DEBUG" fi fi OS_DLLFLAGS="-nologo -DLL -SUBSYSTEM:WINDOWS" if test "$MSC_VER" -le "1200" -a -z "$MOZ_DEBUG_SYMBOLS"; then OS_DLLFLAGS="$OS_DLLFLAGS -PDB:NONE" fi if test "$OS_TARGET" = "WINNT"; then CFLAGS="$CFLAGS -GT" LIBNSPR='$(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' LIBPLC='$(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' else LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' fi fi # GNU_CC if test -n "$USE_STATIC_TLS"; then $as_echo "#define _PR_USE_STATIC_TLS 1" >>confdefs.h fi if test "$OS_TARGET" = "WINNT"; then $as_echo "#define WINNT 1" >>confdefs.h else $as_echo "#define WIN95 1" >>confdefs.h # undefine WINNT as some versions of mingw gcc define it by default DEFINES="$DEFINES -UWINNT" $as_echo "#define _PR_GLOBAL_THREADS_ONLY 1" >>confdefs.h fi if test "$CPU_ARCH" = "x86"; then CPU_ARCH_TAG= else CPU_ARCH_TAG=$CPU_ARCH fi if test "$USE_DEBUG_RTL" = 1; then OBJDIR_SUFFIX=OBJD fi case "$OS_TARGET" in WINNT) MDCPUCFG_H=_winnt.cfg ;; WIN95) MDCPUCFG_H=_win95.cfg ;; *) as_fn_error $? "Missing OS_TARGET for ${target}. Use --enable-win32-target to set." "$LINENO" 5 ;; esac case "$target_cpu" in i*86) if test -n "$USE_64"; then $as_echo "#define _AMD64_ 1" >>confdefs.h else $as_echo "#define _X86_ 1" >>confdefs.h if test -z "$GNU_CC" -a "$MSC_VER" -ge "1700"; then CFLAGS="$CFLAGS -arch:IA32" fi fi ;; x86_64) $as_echo "#define _AMD64_ 1" >>confdefs.h USE_64=1 ;; ia64) $as_echo "#define _IA64_ 1" >>confdefs.h USE_64=1 ;; *) $as_echo "#define _CPU_ARCH_NOT_DEFINED 1" >>confdefs.h ;; esac ;; *-netbsd*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define NETBSD 1" >>confdefs.h $as_echo "#define HAVE_BSD_FLOCK 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi MDCPUCFG_H=_netbsd.cfg PR_MD_CSRCS=netbsd.c DSO_CFLAGS='-fPIC -DPIC' CFLAGS="$CFLAGS -ansi -Wall" CXXFLAGS="$CXXFLAGS -ansi -Wall" MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)' if test -z "$OBJECT_FMT"; then if echo __ELF__ | ${CC-cc} -E - | grep -q __ELF__ 2>/dev/null; then OBJECT_FMT=a.out DLL_SUFFIX=so.1.0 DSO_LDOPTS='-shared' else OBJECT_FMT=ELF DLL_SUFFIX=so DSO_LDOPTS='-shared -Wl,-soname,$(notdir $@)' fi fi if test "$LIBRUNPATH"; then DSO_LDOPTS="$DSO_LDOPTS -Wl,-R$LIBRUNPATH" fi ;; *-nto*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define NTO 1" >>confdefs.h $as_echo "#define _QNX_SOURCE 1" >>confdefs.h $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h MDCPUCFG_H=_nto.cfg PR_MD_CSRCS=nto.c MKSHLIB='$(CC) $(DSO_LDOPTS) -Wl,-soname -Wl,$(notdir $@) -o $@' DSO_CFLAGS=-fPIC DSO_LDOPTS=-shared OS_LIBS="$OS_LIBS -lsocket" _OPTIMIZE_FLAGS="-O1" _DEBUG_FLAGS="-gstabs" ;; *-openbsd*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define OPENBSD 1" >>confdefs.h $as_echo "#define HAVE_BSD_FLOCK 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h CFLAGS="$CFLAGS -ansi -Wall" CXXFLAGS="$CXXFLAGS -ansi -Wall" DLL_SUFFIX=so.1.0 DSO_CFLAGS=-fPIC MDCPUCFG_H=_openbsd.cfg PR_MD_CSRCS=openbsd.c OS_LIBS="-lc" if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi DSO_LDOPTS='-shared -fPIC -Wl,-soname,$(notdir $@)' MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' ;; *-osf*) SHELL_OVERRIDE="SHELL = /usr/bin/ksh" $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define OSF1 1" >>confdefs.h $as_echo "#define _REENTRANT 1" >>confdefs.h # OSF1 and HPUX report the POLLHUP event for a socket when the # shutdown(SHUT_WR) operation is called for the remote end, even though # the socket is still writeable. Use select(), instead of poll(), to # workaround this problem. $as_echo "#define _PR_POLL_WITH_SELECT 1" >>confdefs.h if echo "$OS_RELEASE" | egrep -c '(V2.0|V3.2)' 2>/dev/null ; then USE_NSPR_THREADS=1 fi if test -z "$GNU_CC"; then CC="$CC -std1 -ieee_with_inexact" if test "$OS_RELEASE" != "V2.0"; then CC="$CC -readonly_strings" fi _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Olimit 4000" ac_fn_c_check_header_mongrel "$LINENO" "machine/builtins.h" "ac_cv_header_machine_builtins_h" "$ac_includes_default" if test "x$ac_cv_header_machine_builtins_h" = xyes; then : $as_echo "#define OSF1_HAVE_MACHINE_BUILTINS_H 1" >>confdefs.h fi else CFLAGS="$CFLAGS -mieee" CXXFLAGS="$CXXFLAGS -mieee" fi if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then $as_echo "#define HAVE_INT_LOCALTIME_R 1" >>confdefs.h else $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h fi if echo $OS_RELEASE | grep -c V4.0 >/dev/null; then $as_echo "#define OSF1V4_MAP_PRIVATE_BUG 1" >>confdefs.h fi DSO_LDOPTS='-shared -all -expect_unresolved "*" -soname $(notdir $@)' MDCPUCFG_H=_osf1.cfg PR_MD_CSRCS=osf1.c ;; *-qnx*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define QNX 1" >>confdefs.h $as_echo "#define _PR_NEED_H_ERRNO 1" >>confdefs.h USE_NSPR_THREADS=1 MDCPUCFG_H=_qnx.cfg PR_MD_CSRCS=qnx.c ;; *-riscos*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define RISCOS 1" >>confdefs.h $as_echo "#define _PR_NEED_H_ERRNO 1" >>confdefs.h USE_PTHREADS=1 MDCPUCFG_H=_riscos.cfg PR_MD_CSRCS=riscos.c DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' ;; *-*-sco*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define SCO 1" >>confdefs.h $as_echo "#define sco 1" >>confdefs.h $as_echo "#define SYSV 1" >>confdefs.h $as_echo "#define _SVID3 1" >>confdefs.h $as_echo "#define _PR_NEED_H_ERRNO 1" >>confdefs.h CC='cc -b elf -KPIC' CXX='$(NSDEPTH)/build/hcpp CC +.cpp +w' USE_NSPR_THREADS=1 CPU_ARCH=x86 DSO_LDOPTS='-b elf -G' MDCPUCFG_H=_scoos.cfg PR_MD_SRCS=scoos.c ;; *-solaris*) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define SVR4 1" >>confdefs.h $as_echo "#define SYSV 1" >>confdefs.h $as_echo "#define __svr4 1" >>confdefs.h $as_echo "#define __svr4__ 1" >>confdefs.h $as_echo "#define SOLARIS 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h CPU_ARCH=`uname -p` MDCPUCFG_H=_solaris.cfg PR_MD_CSRCS=solaris.c LD=/usr/ccs/bin/ld MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' RESOLVE_LINK_SYMBOLS=1 case "${OS_RELEASE}" in 5.8|5.9) ;; *) # It is safe to use the -Bdirect linker flag on Solaris 10 or later. USE_B_DIRECT=1 ;; esac if test -n "$GNU_CC"; then DSO_CFLAGS=-fPIC if `$CC -print-prog-name=ld` -v 2>&1 | grep -c GNU >/dev/null; then GCC_USE_GNU_LD=1 fi DSO_LDOPTS='-shared -Wl,-h,$(notdir $@),-z,combreloc,-z,defs,-z,ignore' if test -n "$USE_B_DIRECT"; then DSO_LDOPTS="$DSO_LDOPTS,-Bdirect" fi else DSO_CFLAGS=-KPIC DSO_LDOPTS='-G -h $(notdir $@) -z combreloc -z defs -z ignore' if test -n "$USE_B_DIRECT"; then DSO_LDOPTS="$DSO_LDOPTS -Bdirect" fi fi if test -n "$GNU_CC"; then CFLAGS="$CFLAGS -Wall" CXXFLAGS="$CXXFLAGS -Wall" if test -n "$USE_MDUPDATE"; then CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)" CXXFLAGS="$CXXFLAGS -MDupdate \$(DEPENDENCIES)" fi GCC_AS=`$CC -print-prog-name=as` if test "`echo | $GCC_AS -v 2>&1 | grep -c GNU`" != "0"; then GNU_AS=1 fi else CFLAGS="$CFLAGS -xstrconst" CXXFLAGS="$CXXFLAGS -Qoption cg -xstrconst -features=tmplife" if test -z "$MOZ_OPTIMIZE"; then CFLAGS="$CFLAGS -xs" CXXFLAGS="$CXXFLAGS -xs" fi _OPTIMIZE_FLAGS=-xO4 fi if test -z "$GNU_AS"; then ASFLAGS="$ASFLAGS -Wa,-P" fi if test -n "$USE_64"; then if test -n "$GNU_CC"; then CC="$CC -m64" CXX="$CXX -m64" else if test "$OS_TEST" = "i86pc"; then CC="$CC -xarch=amd64" CXX="$CXX -xarch=amd64" else CC="$CC -xarch=v9" CXX="$CXX -xarch=v9" fi fi fi if test "$OS_TEST" = "i86pc"; then if test -z "$USE_64"; then $as_echo "#define i386 1" >>confdefs.h fi CPU_ARCH_TAG=_$OS_TEST # The default debug format, DWARF (-g), is not supported by gcc # on i386-ANY-sysv4/solaris, but the stabs format is. It is # assumed that the Solaris assembler /usr/ccs/bin/as is used. # If your gcc uses GNU as, you do not need the -Wa,-s option. if test -n "$MOZ_DEBUG" && test -n "$GNU_CC"; then _DEBUG_FLAGS=-gstabs if test -z "$GNU_AS"; then _DEBUG_FLAGS="$_DEBUG_FLAGS -Wa,-s" fi fi fi case "${target_os}" in solaris2.3*) $as_echo "#define _PR_NO_LARGE_FILES 1" >>confdefs.h ;; solaris2.4*) $as_echo "#define _PR_NO_LARGE_FILES 1" >>confdefs.h ;; solaris2.5*) $as_echo "#define SOLARIS2_5 1" >>confdefs.h ;; *) $as_echo "#define _PR_HAVE_OFF64_T 1" >>confdefs.h # The lfcompile64(5) man page on Solaris 2.6 says: # For applications that do not wish to conform to the POSIX or # X/Open specifications, the 64-bit transitional interfaces # are available by default. No compile-time flags need to be # set. # But gcc 2.7.2.x fails to define _LARGEFILE64_SOURCE by default. # The native compiler, gcc 2.8.x, and egcs don't have this problem. if test -n "$GNU_CC"; then $as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h fi ;; esac case "${target_os}" in solaris2.3*) ;; solaris2.4*) ;; solaris2.5*) ;; solaris2.6*) ;; solaris2.7*) ;; *) # Solaris 8 or higher has IPv6. $as_echo "#define _PR_INET6 1" >>confdefs.h ;; esac if test "$CPU_ARCH" = "sparc"; then # 64-bit Solaris SPARC requires V9 architecture, so the following # is not needed. if test -z "$USE_64"; then ULTRASPARC_LIBRARY=nspr_flt fi fi # Purify requires that binaries linked against nspr also # be linked against -lrt (or -lposix4) so add it to OS_LIBS _rev=`uname -r` _librt=`echo $_rev 5.6 | awk '{ if ($1 > $2) print "-lrt"; else print "-lposix4" }'` OS_LIBS="$OS_LIBS $_librt" ;; *-sco-sysv5*) $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define UNIXWARE 1" >>confdefs.h $as_echo "#define SVR4 1" >>confdefs.h $as_echo "#define SYSV 1" >>confdefs.h USE_NSPR_THREADS=1 if echo $OS_RELEASE | grep -c 2.1 2>/dev/null; then $as_echo "#define _PR_NO_LARGE_FILES 1" >>confdefs.h CC='$(NSDEPTH)/build/hcc cc' CXX='$(NSDEPTH)/build/hcpp CC' MDCPUCFG_H=_unixware.cfg else $as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h $as_echo "#define _PR_HAVE_OFF64_T 1" >>confdefs.h $as_echo "#define _PR_HAVE_SOCKADDR_LEN 1" >>confdefs.h MDCPUCFG_H=_unixware7.cfg fi PR_MD_CSRCS=unixware.c DSO_LDOPTS=-G CPU_ARCH=x86 ;; *-symbian*) # Check whether --with-symbian-sdk was given. if test "${with_symbian_sdk+set}" = set; then : withval=$with_symbian_sdk; SYMBIAN_SDK_DIR=$withval fi echo ----------------------------------------------------------------------------- echo Building with Symbian SDK in: $SYMBIAN_SDK_DIR echo ----------------------------------------------------------------------------- $as_echo "#define XP_UNIX 1" >>confdefs.h $as_echo "#define SYMBIAN 1" >>confdefs.h $as_echo "#define __arm__ 1" >>confdefs.h $as_echo "#define __SYMBIAN32__ 1" >>confdefs.h $as_echo "#define _UNICODE 1" >>confdefs.h $as_echo "#define NDEBUG 1" >>confdefs.h $as_echo "#define __SUPPORT_CPP_EXCEPTIONS__ 1" >>confdefs.h $as_echo "#define MOZ_STDERR_TO_STDOUT 1" >>confdefs.h $as_echo "#define HAVE_FCNTL_FILE_LOCKING 1" >>confdefs.h $as_echo "#define HAVE_SOCKLEN_T 1" >>confdefs.h USE_PTHREADS=1 LIB_SUFFIX=lib DLL_SUFFIX=dll MKSHLIB= DSO_LDOPTS= DSO_CFLAGS= VISIBILITY_FLAGS= MDCPUCFG_H=_symbian.cfg PR_MD_CSRCS=symbian.c NSINSTALL=nsinstall RANLIB='echo no ranlib ' CPU_ARCH=ARM OS_ARCH=SYMBIAN OS_EXE_CFLAGS="$OS_EXE_CFLAGS -D__EXE__" CFLAGS="$CFLAGS -MD -nostdinc" SYMBIAN_SYS_INCLUDE="-I$SYMBIAN_SDK_DIR/Epoc32/include/variant -I$SYMBIAN_SDK_DIR/Epoc32/include -I$SYMBIAN_SDK_DIR/Epoc32/include/stdapis" echo ------------------------------------------------------- echo SYMBIAN_SYS_INCLUDE is: $SYMBIAN_SYS_INCLUDE echo ------------------------------------------------------- case "$OS_TARGET" in WINSCW) CC=mwccsym2.exe CXX=mwccsym2.exe LD=mwldsym2.exe AR=mwldsym2.exe WINSCW_LD_DIR="\$(SYMBIAN_SDK_DIR)/EPOC32/RELEASE/WINSCW/UDEB" CFLAGS="$CFLAGS -O0 -inline off -wchar_t off -align 4 -warnings on -w nohidevirtual,nounusedexpr -msgstyle gcc -enum int -str pool -exc ms -trigraphs on -nostderr -gccdep -cwd source -i- -I\$(VPATH)" SYMBIAN_SYS_INCLUDE="$SYMBIAN_SYS_INCLUDE -include Symbian_OS_v9.2.hrh" AR_FLAGS="-library -msgstyle gcc -stdlib -subsystem windows -noimplib -o \$@" $as_echo "#define _DEBUG 1" >>confdefs.h $as_echo "#define __CW32__ 1" >>confdefs.h $as_echo "#define __WINS__ 1" >>confdefs.h $as_echo "#define __WINSCW__ 1" >>confdefs.h DEFINES="$DEFINES -U_WIN32" ;; GCCE) CFLAGS="$CFLAGS -Wall -Wno-unknown-pragmas -fexceptions -march=armv5t -mapcs -pipe -x c -msoft-float" CXXFLAGS="$CXXFLAGS $CFLAGS -Wno-ctor-dtor-privacy" SYMBIAN_SYS_INCLUDE="$SYMBIAN_SYS_INCLUDE -include $SYMBIAN_SDK_DIR/EPOC32/INCLUDE/GCCE/GCCE.h" $as_echo "#define __GCCE__ 1" >>confdefs.h $as_echo "#define __EABI__ 1" >>confdefs.h DEFINES="$DEFINES -D__PRODUCT_INCLUDE__=$SYMBIAN_SDK_DIR/Epoc32/include/variant/Symbian_OS_v9.2.hrh" ;; *) as_fn_error $? "Missing OS_TARGET for ${target}. Set --enable-symbian-target to with 'WINSCW' or 'GCCE'." "$LINENO" 5 ;; esac CFLAGS="$CFLAGS ${SYMBIAN_SYS_INCLUDE}" ;; *-os2*) $as_echo "#define XP_OS2 1" >>confdefs.h $as_echo "#define XP_PC 1" >>confdefs.h $as_echo "#define BSD_SELECT 1" >>confdefs.h $as_echo "#define TCPV40HDRS 1" >>confdefs.h LIB_SUFFIX=lib DLL_SUFFIX=dll RC=rc.exe PR_MD_ARCH_DIR=os2 PROG_SUFFIX=.exe NSINSTALL=nsinstall MDCPUCFG_H=_os2.cfg RESOLVE_LINK_SYMBOLS=1 $as_echo "#define OS2 1" >>confdefs.h AR=emxomfar AR_FLAGS='r $@' CFLAGS="$CFLAGS -Wall -Zomf" CXXFLAGS="$CFLAGS -Wall -Zomf" MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS= DSO_LDOPTS='-Zomf -Zdll' LDFLAGS='-Zmap' _OPTIMIZE_FLAGS="-O2 -s" _DEBUG_FLAGS="-g -fno-inline" if test -n "$MOZ_OPTIMIZE"; then DSO_LDOPTS="$DSO_LDOPTS -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA" fi IMPLIB='emximp -o' FILTER='emxexp -o' if test -n "$MOZ_OS2_HIGH_MEMORY"; then LDFLAGS="$LDFLAGS -Zhigh-mem" $as_echo "#define MOZ_OS2_HIGH_MEMORY 1" >>confdefs.h fi # GCC for OS/2 currently predefines these, but we don't want them DEFINES="$DEFINES -Uunix -U__unix -U__unix__" ;; *) $as_echo "#define XP_UNIX 1" >>confdefs.h ;; esac if test -z "$SKIP_LIBRARY_CHECKS"; then case $target in *-darwin*|*-beos*|*-os2*) ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes; then : OS_LIBS="-ldl $OS_LIBS" fi fi ;; esac if test $ac_cv_c_compiler_gnu = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 $as_echo_n "checking whether $CC needs -traditional... " >&6; } if ${ac_cv_prog_gcc_traditional+:} false; then : $as_echo_n "(cached) " >&6 else ac_pattern="Autoconf.*'x'" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TIOCGETP _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes else ac_cv_prog_gcc_traditional=no fi rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Autoconf TCGETA _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "$ac_pattern" >/dev/null 2>&1; then : ac_cv_prog_gcc_traditional=yes fi rm -f conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 $as_echo "$ac_cv_prog_gcc_traditional" >&6; } if test $ac_cv_prog_gcc_traditional = yes; then CC="$CC -traditional" fi fi _SAVE_LIBS="$LIBS" LIBS="$LIBS $OS_LIBS" for ac_func in dladdr gettid lchown setpriority strerror syscall do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done LIBS="$_SAVE_LIBS" # Check whether --with-ccache was given. if test "${with_ccache+set}" = set; then : withval=$with_ccache; CCACHE=$withval else CCACHE="no" fi if test "$CCACHE" != "no"; then if test -n "$CCACHE"; then if test "$CCACHE" = "yes"; then CCACHE= else if test ! -e "$CCACHE"; then as_fn_error $? "$CCACHE not found" "$LINENO" 5 fi fi fi for ac_prog in $CCACHE ccache do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_CCACHE+:} false; then : $as_echo_n "(cached) " >&6 else case $CCACHE in [\\/]* | ?:[\\/]*) ac_cv_path_CCACHE="$CCACHE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_CCACHE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi CCACHE=$ac_cv_path_CCACHE if test -n "$CCACHE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCACHE" >&5 $as_echo "$CCACHE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CCACHE" && break done if test -z "$CCACHE" -o "$CCACHE" = ":"; then as_fn_error $? "ccache not found" "$LINENO" 5 elif test -x "$CCACHE"; then CC="$CCACHE $CC" CXX="$CCACHE $CXX" else as_fn_error $? "$CCACHE is not executable" "$LINENO" 5 fi fi # Check whether --enable-strip was given. if test "${enable_strip+set}" = set; then : enableval=$enable_strip; if test "$enableval" = "yes"; then ENABLE_STRIP=1 fi fi case "${target_os}" in hpux*) if test -z "$GNU_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for +Olit support" >&5 $as_echo_n "checking for +Olit support... " >&6; } if ${ac_cv_hpux_usable_olit_option+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_hpux_usable_olit_option=no rm -f conftest* echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} ${CFLAGS} +Olit=all -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out`"; then ac_cv_hpux_usable_olit_option=yes fi fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_hpux_usable_olit_option" >&5 $as_echo "$ac_cv_hpux_usable_olit_option" >&6; } if test "$ac_cv_hpux_usable_olit_option" = "yes"; then CFLAGS="$CFLAGS +Olit=all" CXXFLAGS="$CXXFLAGS +Olit=all" else CFLAGS="$CFLAGS +ESlit" CXXFLAGS="$CXXFLAGS +ESlit" fi fi ;; esac case "$target_os" in darwin*) _HAVE_PTHREADS=1 ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthreads" >&5 $as_echo_n "checking for pthread_create in -lpthreads... " >&6; } if ${ac_cv_lib_pthreads_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthreads_pthread_create=yes else ac_cv_lib_pthreads_pthread_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_create" >&5 $as_echo "$ac_cv_lib_pthreads_pthread_create" >&6; } if test "x$ac_cv_lib_pthreads_pthread_create" = xyes; then : _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 $as_echo_n "checking for pthread_create in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_create=yes else ac_cv_lib_pthread_pthread_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc_r" >&5 $as_echo_n "checking for pthread_create in -lc_r... " >&6; } if ${ac_cv_lib_c_r_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_r_pthread_create=yes else ac_cv_lib_c_r_pthread_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_create" >&5 $as_echo "$ac_cv_lib_c_r_pthread_create" >&6; } if test "x$ac_cv_lib_c_r_pthread_create" = xyes; then : _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lc" >&5 $as_echo_n "checking for pthread_create in -lc... " >&6; } if ${ac_cv_lib_c_pthread_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_c_pthread_create=yes else ac_cv_lib_c_pthread_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_create" >&5 $as_echo "$ac_cv_lib_c_pthread_create" >&6; } if test "x$ac_cv_lib_c_pthread_create" = xyes; then : _HAVE_PTHREADS=1 fi fi fi fi ;; esac # Check whether --with-pthreads was given. if test "${with_pthreads+set}" = set; then : withval=$with_pthreads; if test "$withval" = "yes"; then if test -n "$_HAVE_PTHREADS"; then USE_PTHREADS=1 USE_USER_PTHREADS= USE_NSPR_THREADS= else as_fn_error $? " --with-pthreads specified for a system without pthread support " "$LINENO" 5; fi else USE_PTHREADS= _PTHREAD_LDFLAGS= fi else if test -n "$_HAVE_PTHREADS" && test -z "$USE_USER_PTHREADS" && test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 USE_USER_PTHREADS= USE_NSPR_THREADS= fi fi # Check whether --enable-user-pthreads was given. if test "${enable_user_pthreads+set}" = set; then : enableval=$enable_user_pthreads; if test "$enableval" = "yes"; then if test -n "$_HAVE_PTHREADS"; then USE_PTHREADS= USE_USER_PTHREADS=1 USE_NSPR_THREADS= else as_fn_error $? " --enable-user-pthreads specified for a system without pthread support " "$LINENO" 5; fi fi fi # Check whether --enable-nspr-threads was given. if test "${enable_nspr_threads+set}" = set; then : enableval=$enable_nspr_threads; if test "$enableval" = "yes"; then USE_PTHREADS= USE_USER_PTHREADS= USE_NSPR_THREADS=1 fi fi case "$target" in *-beos*) # Check whether --with-bthreads was given. if test "${with_bthreads+set}" = set; then : withval=$with_bthreads; if test "$withval" = "yes"; then USE_BTHREADS=1 USE_USER_PTHREADS= USE_PTHREADS= fi fi ;; esac fi # SKIP_LIBRARY_CHECKS # Check whether --enable-ipv6 was given. if test "${enable_ipv6+set}" = set; then : enableval=$enable_ipv6; if test "$enableval" = "yes"; then USE_IPV6=1 else USE_IPV6= fi fi if test -n "$USE_PTHREADS"; then rm -f conftest* ac_cv_have_dash_pthread=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -pthread" >&5 $as_echo_n "checking whether ${CC-cc} accepts -pthread... " >&6; } echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthread=yes case "$target_os" in freebsd*) # Freebsd doesn't use -pthread for compiles, it uses them for linking ;; *) CFLAGS="$CFLAGS -pthread" CXXFLAGS="$CXXFLAGS -pthread" ;; esac fi fi rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_dash_pthread" >&5 $as_echo "$ac_cv_have_dash_pthread" >&6; } ac_cv_have_dash_pthreads=no if test "$ac_cv_have_dash_pthread" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -pthreads" >&5 $as_echo_n "checking whether ${CC-cc} accepts -pthreads... " >&6; } echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthreads=yes CFLAGS="$CFLAGS -pthreads" CXXFLAGS="$CXXFLAGS -pthreads" fi fi rm -f conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_dash_pthreads" >&5 $as_echo "$ac_cv_have_dash_pthreads" >&6; } fi case "$target" in *-solaris*) if test "$ac_cv_have_dash_pthreads" = "yes"; then _PTHREAD_LDFLAGS= fi ;; *-freebsd*) $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _THREAD_SAFE 1" >>confdefs.h if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS="-pthread" else _PTHREAD_LDFLAGS="-lc_r" fi ;; *-netbsd*) if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS="-pthread" fi ;; *-bsdi*) $as_echo "#define _THREAD_SAFE 1" >>confdefs.h if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS= fi ;; *-openbsd*) if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS=-pthread fi ;; *-linux*|*-gnu*|*-k*bsd*-gnu) $as_echo "#define _REENTRANT 1" >>confdefs.h ;; esac else if test -n "$USE_USER_PTHREADS"; then USE_PTHREADS= USE_NSPR_THREADS= else _PTHREAD_LDFLAGS= fi fi case "$target" in *-aix*) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi case "$target_os" in aix4.1*) if test -z "$USE_PTHREADS"; then $as_echo "#define AIX_RENAME_SELECT 1" >>confdefs.h fi ;; aix4.2*) if test -z "$USE_NSPR_THREADS"; then $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h fi ;; aix4.3*) if test -z "$USE_NSPR_THREADS"; then $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h fi if test -n "$USE_PTHREADS"; then $as_echo "#define _PR_HAVE_THREADSAFE_GETHOST 1" >>confdefs.h fi ;; *) if test -z "$USE_NSPR_THREADS"; then $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h fi if test -n "$USE_PTHREADS"; then $as_echo "#define _PR_HAVE_THREADSAFE_GETHOST 1" >>confdefs.h fi ;; esac ;; *-bsdi*) if test -n "$USE_PTHREADS"; then $as_echo "#define _PR_NEED_PTHREAD_INIT 1" >>confdefs.h fi ;; *-freebsd*) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi ;; *-hpux*) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi if test "$USE_PTHREADS"; then if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define _PR_DCETHREADS 1" >>confdefs.h else cat >>confdefs.h <<_ACEOF #define _POSIX_C_SOURCE 199506L _ACEOF $as_echo "#define _PR_HAVE_THREADSAFE_GETHOST 1" >>confdefs.h fi fi if test "$USE_USER_PTHREADS"; then cat >>confdefs.h <<_ACEOF #define _POSIX_C_SOURCE 199506L _ACEOF fi ;; *-irix*) if test "${target_os}" = "irix6.5"; then if test -n "$USE_PTHREADS"; then $as_echo "#define _PR_HAVE_GETHOST_R 1" >>confdefs.h $as_echo "#define _PR_HAVE_GETHOST_R_POINTER 1" >>confdefs.h fi fi ;; *-linux*|*-gnu*|*-k*bsd*-gnu) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi ;; *-mingw*|*-msys*|*-cygwin*|*-mks*|*-os2*|*-beos*) USE_PTHREADS= _PTHREAD_LDFLAGS= USE_USER_PTHREADS= ;; *-netbsd*|*-openbsd*) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi ;; *-osf*) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi if test -n "$USE_PTHREADS"; then if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then : else $as_echo "#define _PR_HAVE_THREADSAFE_GETHOST 1" >>confdefs.h fi fi ;; *-solaris*) if test -n "$USE_NSPR_THREADS"; then $as_echo "#define _PR_LOCAL_THREADS_ONLY 1" >>confdefs.h fi if test -n "$USE_PTHREADS"; then $as_echo "#define _REENTRANT 1" >>confdefs.h $as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h if test "$OS_TEST" = "i86pc"; then if test -n "$USE_64"; then PR_MD_ASFILES=os_SunOS_x86_64.s else PR_MD_ASFILES=os_SunOS_x86.s fi else if test -n "$USE_64"; then PR_MD_ASFILES=os_SunOS_sparcv9.s fi fi fi ;; *-nto*) if test -n "$USE_PTHREADS"; then $as_echo "#define _PR_HAVE_GETHOST_R 1" >>confdefs.h $as_echo "#define _PR_HAVE_GETHOST_R_POINTER 1" >>confdefs.h fi ;; esac OS_LIBS="$_PTHREAD_LDFLAGS $OS_LIBS" if test -n "$_SAVE_OPTIMIZE_FLAGS"; then _OPTIMIZE_FLAGS="$_SAVE_OPTIMIZE_FLAGS" fi if test -n "$_SAVE_DEBUG_FLAGS"; then _DEBUG_FLAGS="$_SAVE_DEBUG_FLAGS" fi if test -n "$MOZ_OPTIMIZE"; then CFLAGS="$CFLAGS $_OPTIMIZE_FLAGS" CXXFLAGS="$CXXFLAGS $_OPTIMIZE_FLAGS" fi if test -n "$MOZ_DEBUG_SYMBOLS"; then CFLAGS="$CFLAGS $_DEBUG_FLAGS" CXXFLAGS="$CXXFLAGS $_DEBUG_FLAGS" fi if test -n "$MOZ_OPTIMIZE"; then OBJDIR_TAG=_OPT else OBJDIR_TAG=_DBG fi if test -n "$USE_64"; then COMPILER_TAG=_64 fi RELEASE_OBJDIR_NAME="${OS_CONFIG}${CPU_ARCH_TAG}${COMPILER_TAG}${IMPL_STRATEGY}${OBJDIR_TAG}.${OBJDIR_SUFFIX}" case "$target_os" in cygwin*|mks*) CC="\$(CYGWIN_WRAPPER) $CC" CXX="\$(CYGWIN_WRAPPER) $CXX" RC="\$(CYGWIN_WRAPPER) $RC" ;; esac # Check whether --enable-wrap-malloc was given. if test "${enable_wrap_malloc+set}" = set; then : enableval=$enable_wrap_malloc; if test "$enableval" = "yes"; then _WRAP_MALLOC=1 fi fi if test -n "$_WRAP_MALLOC"; then if test -n "$GNU_CC"; then WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign" WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete" WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup" WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size" else as_fn_error $? "--enable-wrap-malloc is not supported for non-GNU toolchains" "$LINENO" 5 fi fi # Check whether --with-wrap-malloc was given. if test "${with_wrap_malloc+set}" = set; then : withval=$with_wrap_malloc; WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval" fi MAKEFILES=" Makefile config/Makefile config/autoconf.mk config/nsprincl.mk config/nsprincl.sh config/nspr-config config/nspr.pc lib/Makefile lib/ds/Makefile lib/libc/Makefile lib/libc/include/Makefile lib/libc/src/Makefile lib/tests/Makefile pkg/Makefile pr/Makefile pr/include/Makefile pr/include/md/Makefile pr/include/obsolete/Makefile pr/include/private/Makefile pr/src/Makefile pr/src/io/Makefile pr/src/linking/Makefile pr/src/malloc/Makefile pr/src/md/Makefile pr/src/md/${PR_MD_ARCH_DIR}/Makefile pr/src/memory/Makefile pr/src/misc/Makefile pr/src/threads/Makefile pr/tests/Makefile pr/tests/dll/Makefile " if test "$OS_TARGET" = "Linux"; then MAKEFILES="$MAKEFILES pkg/linux/Makefile " elif test "$OS_TARGET" = "SunOS"; then MAKEFILES="$MAKEFILES pkg/solaris/Makefile pkg/solaris/SUNWpr/Makefile pkg/solaris/SUNWprd/Makefile " fi if test -z "$USE_PTHREADS" && test -z "$USE_BTHREADS"; then MAKEFILES="$MAKEFILES pr/src/threads/combined/Makefile " elif test -n "$USE_PTHREADS"; then MAKEFILES="$MAKEFILES pr/src/pthreads/Makefile " elif test -n "$USE_BTHREADS"; then MAKEFILES="$MAKEFILES pr/src/bthreads/Makefile " fi if test -n "$USE_CPLUS"; then MAKEFILES="$MAKEFILES pr/src/cplus/Makefile pr/src/cplus/tests/Makefile " fi echo $MAKEFILES > unallmakefiles ac_config_files="$ac_config_files $MAKEFILES" ac_config_commands="$ac_config_commands default" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "$MAKEFILES") CONFIG_FILES="$CONFIG_FILES $MAKEFILES" ;; "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "default":C) chmod +x config/nspr-config ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi nspr-4.11/nspr/configure.in0000644000000000000000000026355012623070344014056 0ustar 00000000000000dnl -*- Mode: Autoconf; tab-width: 4; indent-tabs-mode: nil; -*- dnl dnl This Source Code Form is subject to the terms of the Mozilla Public dnl License, v. 2.0. If a copy of the MPL was not distributed with this dnl file, You can obtain one at http://mozilla.org/MPL/2.0/. AC_PREREQ(2.61) AC_INIT AC_CONFIG_SRCDIR([pr/include/nspr.h]) AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf) AC_CANONICAL_TARGET dnl ======================================================== dnl = Defaults dnl ======================================================== MOD_MAJOR_VERSION=4 MOD_MINOR_VERSION=11 MOD_PATCH_VERSION=0 NSPR_MODNAME=nspr20 _HAVE_PTHREADS= USE_PTHREADS= USE_USER_PTHREADS= USE_NSPR_THREADS= USE_N32= USE_X32= USE_64= USE_CPLUS= USE_IPV6= USE_MDUPDATE= _MACOSX_DEPLOYMENT_TARGET= _OPTIMIZE_FLAGS=-O _DEBUG_FLAGS=-g MOZ_DEBUG=1 MOZ_OPTIMIZE= OBJDIR='$(OBJDIR_NAME)' OBJDIR_NAME=. OBJDIR_SUFFIX=OBJ NSINSTALL='$(MOD_DEPTH)/config/$(OBJDIR_NAME)/nsinstall' NOSUCHFILE=/no-such-file LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)' LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)' CYGWIN_WRAPPER= MACOS_SDK_DIR= NEXT_ROOT= MT= MOZ_OS2_HIGH_MEMORY=1 PROFILE_GEN_CFLAGS= PROFILE_GEN_LDFLAGS= PROFILE_USE_CFLAGS= PROFILE_USE_LDFLAGS= dnl Link in libraries necessary to resolve all symbols for shared libs RESOLVE_LINK_SYMBOLS= dnl ======================================================== dnl = dnl = Dont change the following lines. Doing so breaks: dnl = dnl = CFLAGS="-foo" ./configure dnl = dnl ======================================================== CFLAGS="${CFLAGS=}" CXXFLAGS="${CXXFLAGS=}" LDFLAGS="${LDFLAGS=}" DLLFLAGS="${DLLFLAGS=}" HOST_CFLAGS="${HOST_CFLAGS=}" HOST_LDFLAGS="${HOST_LDFLAGS=}" case "$target" in *-cygwin*|*-mingw*|*-msys*) # Check to see if we are really running in a msvc environemnt _WIN32_MSVC= AC_CHECK_PROGS(CC, cl) cat > conftest.c </dev/null | grep COMPILER) EOF if test -n "$dummy"; then _WIN32_MSVC=1 CXX=$CC fi rm -f conftest.c ;; *-mks*) _WIN32_MSVC=1 ;; esac if test -n "$_WIN32_MSVC"; then SKIP_PATH_CHECKS=1 SKIP_COMPILER_CHECKS=1 SKIP_LIBRARY_CHECKS=1 fi dnl ======================================================== dnl = Android uses a very custom (hacky) toolchain; we need to do this dnl = here, so that the compiler checks can succeed dnl ======================================================== AC_ARG_WITH(android-ndk, [ --with-android-ndk=DIR location where the Android NDK can be found], android_ndk=$withval) AC_ARG_WITH(android-toolchain, [ --with-android-toolchain=DIR location of the Android toolchain], android_toolchain=$withval) dnl The default android_version is different for each target cpu. case "$target_cpu" in arm) android_version=5 ;; i?86|mipsel) android_version=9 ;; esac AC_ARG_WITH(android-version, [ --with-android-version=VER Android platform version, default 5 for arm, 9 for x86/mips], android_version=$withval) AC_ARG_WITH(android-platform, [ --with-android-platform=DIR location of platform dir], android_platform=$withval) case "$target" in arm-linux*-android*|*-linuxandroid*) android_tool_prefix="arm-linux-androideabi" ;; i?86-*android*) android_tool_prefix="i686-linux-android" ;; mipsel-*android*) android_tool_prefix="mipsel-linux-android" ;; *) android_tool_prefix="$target_os" ;; esac dnl ======================================================== dnl = Gonk is a fork of Android used for Mozilla's B2G project. dnl = Configuration is done largely by the top level config dnl = and the specified gonk directory doesn't matter here. dnl ======================================================== AC_ARG_WITH(gonk, [ --with-gonk=DIR location of gonk dir], gonkdir=$withval) if test -n "$gonkdir" ; then dnl Most things are directly configured by env vars when building for gonk AC_DEFINE(ANDROID) else case "$target" in *-android*|*-linuxandroid*) if test -z "$android_ndk" ; then AC_MSG_ERROR([You must specify --with-android-ndk=/path/to/ndk when targeting Android.]) fi if test -z "$android_toolchain" ; then AC_MSG_CHECKING([for android toolchain directory]) kernel_name=`uname -s | tr "[[:upper:]]" "[[:lower:]]"` case "$target_cpu" in arm) target_name=arm-linux-androideabi-4.4.3 ;; i?86) target_name=x86-4.4.3 ;; mipsel) target_name=mipsel-linux-android-4.4.3 ;; esac android_toolchain="$android_ndk"/toolchains/$target_name/prebuilt/$kernel_name-x86 if test -d "$android_toolchain" ; then AC_MSG_RESULT([$android_toolchain]) else AC_MSG_ERROR([not found. You have to specify --with-android-toolchain=/path/to/ndk/toolchain.]) fi fi if test -z "$android_platform" ; then AC_MSG_CHECKING([for android platform directory]) case "$target_cpu" in arm) target_name=arm ;; i?86) target_name=x86 ;; mipsel) target_name=mips ;; esac android_platform="$android_ndk"/platforms/android-"$android_version"/arch-"$target_name" if test -d "$android_platform" ; then AC_MSG_RESULT([$android_platform]) else AC_MSG_ERROR([not found. You have to specify --with-android-platform=/path/to/ndk/platform.]) fi fi dnl Old NDK support. If minimum requirement is changed to NDK r8b, dnl please remove this. case "$target_cpu" in i?86) if ! test -e "$android_toolchain"/bin/"$android_tool_prefix"-gcc; then dnl Old NDK toolchain name android_tool_prefix="i686-android-linux" fi ;; esac dnl set up compilers AS="$android_toolchain"/bin/"$android_tool_prefix"-as CC="$android_toolchain"/bin/"$android_tool_prefix"-gcc CXX="$android_toolchain"/bin/"$android_tool_prefix"-g++ CPP="$android_toolchain"/bin/"$android_tool_prefix"-cpp LD="$android_toolchain"/bin/"$android_tool_prefix"-ld AR="$android_toolchain"/bin/"$android_tool_prefix"-ar RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip CPPFLAGS="-I$android_platform/usr/include $CPPFLAGS" CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -I$android_platform/usr/include -fpic -fno-short-enums -fno-exceptions $CXXFLAGS" LDFLAGS="-mandroid -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform $LDFLAGS" AC_DEFINE(ANDROID) ;; esac fi dnl ======================================================== dnl = dnl = Check options that may affect the compiler dnl = dnl ======================================================== dist_prefix='${MOD_DEPTH}/dist' dist_bindir='${dist_prefix}/bin' dist_includedir='${dist_prefix}/include/nspr' dist_libdir='${dist_prefix}/lib' dnl If the --includedir option was not specified, add '/nspr' to autoconf's dnl default value of includedir. if test "${includedir}" = '${prefix}/include'; then includedir='${prefix}/include/nspr' fi AC_ARG_WITH(dist-prefix, [ --with-dist-prefix=DIST_PREFIX place build files in DIST_PREFIX [dist]], dist_prefix=$withval) AC_ARG_WITH(dist-bindir, [ --with-dist-bindir=DIR build execuatables in DIR [DIST_PREFIX/bin]], dist_bindir=$withval) AC_ARG_WITH(dist-includedir, [ --with-dist-includedir=DIR build include files in DIR [DIST_PREFIX/include/nspr]], dist_includedir=$withval) AC_ARG_WITH(dist-libdir, [ --with-dist-libdir=DIR build library files in DIR [DIST_PREFIX/lib]], dist_libdir=$withval) AC_SUBST(dist_prefix) AC_SUBST(dist_bindir) AC_SUBST(dist_includedir) AC_SUBST(dist_libdir) dnl Check if NSPR is being compiled for Mozilla dnl Let --with-arg override environment setting dnl AC_ARG_WITH(mozilla, [ --with-mozilla Compile NSPR with Mozilla support], [ if test "$withval" = "yes"; then AC_DEFINE(MOZILLA_CLIENT) MOZILLA_CLIENT=1 else MOZILLA_CLIENT= fi], [ if test -n "$MOZILLA_CLIENT"; then AC_DEFINE(MOZILLA_CLIENT) fi]) AC_ARG_ENABLE(optimize, [ --enable-optimize[=OPT] Enable code optimizations (ie. -O2) ], [ if test "$enableval" != "no"; then MOZ_OPTIMIZE=1 if test -n "$enableval" -a "$enableval" != "yes"; then _OPTIMIZE_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _SAVE_OPTIMIZE_FLAGS=$_OPTIMIZE_FLAGS fi else MOZ_OPTIMIZE= fi ]) AC_ARG_ENABLE(debug, [ --enable-debug[=DBG] Enable debugging (using compiler flags DBG)], [ if test "$enableval" != "no"; then MOZ_DEBUG=1 MOZ_DEBUG_SYMBOLS=1 if test -n "$enableval" -a "$enableval" != "yes"; then _DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _SAVE_DEBUG_FLAGS=$_DEBUG_FLAGS fi else MOZ_DEBUG= fi ], MOZ_DEBUG_SYMBOLS=1) AC_ARG_ENABLE(debug-symbols, [ --enable-debug-symbols[=DBG] Enable debugging symbols (using compiler flags DBG)], [ if test "$enableval" != "no"; then MOZ_DEBUG_SYMBOLS=1 if test -n "$enableval" -a "$enableval" != "yes"; then if test -z "$_SAVE_DEBUG_FLAGS"; then _DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'` _SAVE_DEBUG_FLAGS=$_DEBUG_FLAGS else AC_MSG_ERROR([--enable-debug-symbols flags cannot be used with --enable-debug flags]) fi fi else MOZ_DEBUG_SYMBOLS= fi ]) AC_ARG_ENABLE(win32-target, [ --enable-win32-target=\$t Specify win32 flavor. (WIN95 or WINNT)], OS_TARGET=`echo $enableval | tr a-z A-Z`) AC_ARG_ENABLE(symbian-target, [ --enable-symbian-target=\$t Specify symbian flavor. (WINSCW or GCCE)], OS_TARGET=`echo $enableval | tr a-z A-Z`) AC_ARG_ENABLE(debug-rtl, [ --enable-debug-rtl Use the MSVC debug runtime library], [ if test "$enableval" = "yes"; then USE_DEBUG_RTL=1 else USE_DEBUG_RTL=0 fi ]) AC_ARG_ENABLE(static-rtl, [ --enable-static-rtl Use the MSVC static runtime library], [ if test "$enableval" = "yes"; then USE_STATIC_RTL=1 fi ]) AC_ARG_ENABLE(n32, [ --enable-n32 Enable n32 ABI support (IRIX only)], [ if test "$enableval" = "yes"; then USE_N32=1 else if test "$enableval" = "no"; then USE_N32= fi fi ]) AC_ARG_ENABLE(x32, [ --enable-x32 Enable x32 ABI support (x86_64 only)], [ if test "$enableval" = "yes"; then USE_X32=1 else if test "$enableval" = "no"; then USE_X32= fi fi ]) AC_ARG_ENABLE(64bit, [ --enable-64bit Enable 64-bit support (on certain platforms)], [ if test "$enableval" = "yes"; then USE_64=1 fi ]) AC_ARG_ENABLE(mdupdate, [ --enable-mdupdate Enable use of certain compilers' mdupdate feature], [ if test "$enableval" = "yes"; then USE_MDUPDATE=1 fi ]) AC_ARG_ENABLE(cplus, [ --enable-cplus Enable some c++ api routines], [ if test "$enableval" = "yes"; then USE_CPLUS=1 fi]) AC_ARG_WITH(arm-kuser, [ --with-arm-kuser Use kuser helpers (Linux/ARM only) (Requires kernel 2.6.13 or later)], [ if test "$withval" = "yes"; then AC_DEFINE(_PR_ARM_KUSER) fi ]) dnl ======================================================== dnl = Mac OS X SDK support dnl ======================================================== AC_ARG_WITH(macos-sdk, [ --with-macos-sdk=dir Location of platform SDK to use (Mac OS X only)], MACOS_SDK_DIR=$withval) AC_ARG_ENABLE(macos-target, [ --enable-macos-target=VER Set the minimum MacOS version needed at runtime [10.2 for ppc, 10.4 for x86]], [_MACOSX_DEPLOYMENT_TARGET=$enableval]) dnl ======================================================== dnl = dnl = Set the threading model dnl = dnl ======================================================== case "$target" in *-aix*) case "${target_os}" in aix3.2*) USE_NSPR_THREADS=1 ;; *) USE_PTHREADS=1 ;; esac ;; esac dnl ======================================================== dnl = dnl = Set the default C compiler dnl = dnl ======================================================== if test -z "$CC"; then case "$target" in *-aix*) if test -z "$USE_NSPR_THREADS"; then CC=xlc_r else CC=xlc fi ;; *-hpux*) CC=cc ;; *-irix*) CC=cc ;; *-osf*) CC=cc ;; *-solaris*) CC=cc ;; esac fi dnl ======================================================== dnl = dnl = Set the default C++ compiler dnl = dnl ======================================================== if test -z "$CXX"; then case "$target" in *-aix*) if test -z "$USE_NSPR_THREADS"; then CXX=xlC_r else CXX=xlC fi ;; *-hpux*) case "${target_os}" in hpux10.30) CXX=aCC ;; hpux11.*) CXX=aCC ;; *) CXX=CC ;; esac ;; *-irix*) CXX=CC ;; *-osf*) CXX=cxx ;; *-solaris*) CXX=CC ;; esac fi if test -z "$SKIP_PATH_CHECKS"; then AC_PATH_PROG(WHOAMI, $WHOAMI whoami, echo not_whoami) fi if test -n "$MOZ_DEBUG"; then AC_DEFINE(DEBUG) DEFINES="$DEFINES -UNDEBUG" case "${target_os}" in beos*) DEFINES="$DEFINES -DDEBUG_${USER}" ;; mks*|cygwin*|mingw*|msys*|os2*) DEFINES="$DEFINES -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`" ;; *) DEFINES="$DEFINES -DDEBUG_`$WHOAMI`" ;; esac else AC_DEFINE(NDEBUG) DEFINES="$DEFINES -UDEBUG" fi if test -z "$SKIP_COMPILER_CHECKS"; then dnl ======================================================== dnl Checks for compilers. dnl ======================================================== if test "$target" != "$host"; then echo "cross compiling from $host to $target" cross_compiling=yes case "$build:$target" in powerpc-apple-darwin8*:i?86-apple-darwin*) dnl The Darwin cross compiler doesn't necessarily point itself at a dnl root that has libraries for the proper architecture, it defaults dnl to the system root. The libraries in the system root on current dnl versions of PPC OS X 10.4 aren't fat, so these target compiler dnl checks will fail. Fake a working SDK in that case. _SAVE_CFLAGS=$CFLAGS _SAVE_CXXFLAGS=$CXXFLAGS CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CFLAGS" CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk $CXXFLAGS" ;; esac AC_CHECK_PROGS(CC, $CC "${target_alias}-gcc" "${target}-gcc", echo) unset ac_cv_prog_CC dnl Now exit the conditional block to invoke AC_PROG_CC. fi dnl In the latest versions of autoconf, AC_PROG_CC is a one-shot macro, dnl declared with AC_DEFUN_ONCE. So it must not be expanded inside a dnl conditional block. Invoke AC_PROG_CC outside any conditional block dnl and before invoking AC_TRY_COMPILE (which requires AC_PROG_CC). AC_PROG_CC dnl Reenter the conditional blocks after invoking AC_PROG_CC. if test "$target" != "$host"; then if test -n "$USE_CPLUS"; then AC_CHECK_PROGS(CXX, $CXX "${target_alias}-g++" "${target}-g++", echo) unset ac_cv_prog_CXX AC_PROG_CXX fi case "$build:$target" in powerpc-apple-darwin8*:i?86-apple-darwin*|*:arm*-apple-darwin*) dnl Revert the changes made above. From this point on, the target dnl compiler will never be used without applying the SDK to CFLAGS dnl (see --with-macos-sdk below). CFLAGS=$_SAVE_CFLAGS CXXFLAGS=$_SAVE_CXXFLAGS ;; esac AC_CHECK_PROGS(RANLIB, $RANLIB "${target_alias}-ranlib" "${target}-ranlib", echo) AC_CHECK_PROGS(AR, $AR "${target_alias}-ar" "${target}-ar", echo) AC_CHECK_PROGS(AS, $AS "${target_alias}-as" "${target}-as", echo) AC_CHECK_PROGS(LD, $LD "${target_alias}-ld" "${target}-ld", echo) AC_CHECK_PROGS(STRIP, $STRIP "${target_alias}-strip" "${target}-strip", echo) AC_CHECK_PROGS(WINDRES, $WINDRES "${target_alias}-windres" "${target}-windres", echo) _SAVE_CC="$CC" _SAVE_CFLAGS="$CFLAGS" _SAVE_LDFLAGS="$LDFLAGS" AC_MSG_CHECKING([for $host compiler]) AC_CHECK_PROGS(HOST_CC, $HOST_CC gcc cc /usr/ucb/cc, "") if test -z "$HOST_CC"; then AC_MSG_ERROR([no acceptable cc found in \$PATH]) fi AC_MSG_RESULT([$HOST_CC]) CC="$HOST_CC" CFLAGS="$HOST_CFLAGS" LDFLAGS="$HOST_LDFLAGS" AC_MSG_CHECKING([whether the $host compiler ($HOST_CC $HOST_CFLAGS $HOST_LDFLAGS) works]) AC_TRY_COMPILE([], [return 0;], [AC_MSG_RESULT([yes])], [AC_MSG_ERROR([installation or configuration problem: $host compiler $HOST_CC cannot create executables.])] ) CC=$_SAVE_CC CFLAGS=$_SAVE_CFLAGS LDFLAGS=$_SAVE_LDFLAGS else if test -n "$USE_CPLUS"; then if test "$CC" = "cl" -a -z "$CXX"; then CXX=$CC else AC_PROG_CXX fi fi AC_PROG_RANLIB AC_PATH_PROGS(AS, as, $CC) AC_PATH_PROGS(AR, ar, echo not_ar) AC_PATH_PROGS(LD, ld link, echo not_ld) AC_PATH_PROGS(STRIP, strip, echo not_strip) AC_PATH_PROGS(WINDRES, windres, echo not_windres) if test -z "$HOST_CC"; then HOST_CC="$CC" fi if test -z "$HOST_CFLAGS"; then HOST_CFLAGS="$CFLAGS" fi fi AC_PROG_CPP if test "$GCC" = "yes"; then GNU_CC=1 fi if test "$GXX" = "yes"; then GNU_CXX=1 fi if test "`echo | $AS -v 2>&1 | grep -c GNU`" != "0"; then GNU_AS=1 fi rm -f a.out case "$build:$target" in i?86-apple-darwin*:powerpc-apple-darwin*) dnl cross_compiling will have erroneously been set to "no" in this dnl case, because the x86 build host is able to run ppc code in a dnl translated environment, making a cross compiler appear native. cross_compiling=yes ;; esac if test "$cross_compiling" = "yes"; then CROSS_COMPILE=1 else CROSS_COMPILE= fi dnl ======================================================== dnl Check for gcc -pipe support dnl ======================================================== AC_MSG_CHECKING([for gcc -pipe support]) if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then echo '#include ' > dummy-hello.c echo 'int main() { printf("Hello World\n"); return 0; }' >> dummy-hello.c ${CC} -S dummy-hello.c -o dummy-hello.s 2>&5 cat dummy-hello.s | ${AS} -o dummy-hello.S - 2>&5 if test $? = 0; then _res_as_stdin="yes" else _res_as_stdin="no" fi if test "$_res_as_stdin" = "yes"; then _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -pipe" AC_TRY_COMPILE( [ #include ], [printf("Hello World\n");], [_res_gcc_pipe="yes"], [_res_gcc_pipe="no"] ) CFLAGS=$_SAVE_CFLAGS fi if test "$_res_as_stdin" = "yes" && test "$_res_gcc_pipe" = "yes"; then _res="yes"; CFLAGS="$CFLAGS -pipe" CXXFLAGS="$CXXFLAGS -pipe" else _res="no" fi rm -f dummy-hello.c dummy-hello.s dummy-hello.S dummy-hello a.out AC_MSG_RESULT([$_res]) else AC_MSG_RESULT([no]) fi dnl ======================================================== dnl Profile guided optimization dnl ======================================================== dnl Test for profiling options dnl Under gcc 3.4+, use -fprofile-generate/-fprofile-use _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fprofile-generate -fprofile-correction" AC_MSG_CHECKING([whether C compiler supports -fprofile-generate]) AC_TRY_COMPILE([], [return 0;], [ PROFILE_GEN_CFLAGS="-fprofile-generate" result="yes" ], result="no") AC_MSG_RESULT([$result]) if test $result = "yes"; then PROFILE_GEN_LDFLAGS="-fprofile-generate" PROFILE_USE_CFLAGS="-fprofile-use -fprofile-correction -Wcoverage-mismatch" PROFILE_USE_LDFLAGS="-fprofile-use" fi CFLAGS="$_SAVE_CFLAGS" dnl =============================================================== dnl Check for .hidden assembler directive and visibility attribute. dnl Borrowed from glibc configure.in dnl =============================================================== if test "$GNU_CC"; then AC_CACHE_CHECK(for visibility(hidden) attribute, ac_cv_visibility_hidden, [cat > conftest.c </dev/null 2>&1; then if grep '\.hidden.*foo' conftest.s >/dev/null; then ac_cv_visibility_hidden=yes fi fi rm -f conftest.[cs] ]) if test "$ac_cv_visibility_hidden" = "yes"; then AC_DEFINE(HAVE_VISIBILITY_HIDDEN_ATTRIBUTE) AC_CACHE_CHECK(for visibility pragma support, ac_cv_visibility_pragma, [cat > conftest.c </dev/null 2>&1; then if grep '\.hidden.*foo_hidden' conftest.s >/dev/null; then if ! grep '\.hidden.*foo_default' conftest.s > /dev/null; then ac_cv_visibility_pragma=yes fi fi fi rm -f conftest.[cs] ]) if test "$ac_cv_visibility_pragma" = "yes"; then AC_DEFINE(HAVE_VISIBILITY_PRAGMA) # To work around a build problem on Linux x86-64 (Bugzilla bug # 293438), we use the -fvisibility=hidden flag. This flag is less # optimal than #pragma GCC visibility push(hidden) because the flag # assumes that symbols defined outside the current source file have # the default visibility. This has the advantage that we don't need # to wrap system header files, but has the disadvantage that calls # to hidden symbols defined in other source files cannot be # optimized by the compiler. The -fvisibility=hidden flag does # hide and export symbols correctly. #VISIBILITY_FLAGS='-I$(dist_includedir)/system_wrappers -include $(topsrcdir)/config/gcc_hidden.h' #WRAP_SYSTEM_INCLUDES=1 VISIBILITY_FLAGS="-fvisibility=hidden" WRAP_SYSTEM_INCLUDES= fi fi fi # GNU_CC fi # SKIP_COMPILER_CHECKS dnl ======================================================== dnl Checks for programs. dnl ======================================================== if test -z "$SKIP_PATH_CHECKS"; then AC_PATH_PROGS(PERL, perl5 perl, echo not_perl) elif test -z "$PERL"; then PERL=perl fi dnl ======================================================== dnl Default platform specific options dnl ======================================================== OBJ_SUFFIX=o LIB_SUFFIX=a DLL_SUFFIX=so ASM_SUFFIX=s MKSHLIB='$(LD) $(DSO_LDOPTS) -o $@' PR_MD_ASFILES= PR_MD_CSRCS= PR_MD_ARCH_DIR=unix AR_FLAGS='cr $@' AS='$(CC)' ASFLAGS='$(CFLAGS)' if test -n "$CROSS_COMPILE"; then OS_ARCH=`echo $target_os | sed -e 's|/|_|g'` OS_RELEASE= OS_TEST="${target_cpu}" case "${target_os}" in linux*) OS_ARCH=Linux ;; solaris*) OS_ARCH=SunOS OS_RELEASE=5 ;; mingw*) OS_ARCH=WINNT CPU_ARCH=x86 ;; darwin*) OS_ARCH=Darwin ;; riscos*) OS_ARCH=RISCOS ;; esac else OS_ARCH=`uname -s | sed -e 's|/|_|g'` OS_RELEASE=`uname -r` OS_TEST=`uname -m` fi if test "$OS_ARCH" = "IRIX64"; then OS_ARCH=IRIX fi if test "$OS_ARCH" = "AIX"; then OS_RELEASE=`uname -v`.`uname -r` fi if test "$OS_ARCH" = "FreeBSD"; then OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'` fi if test "$OS_ARCH" = "Linux"; then OS_RELEASE=`echo $OS_RELEASE | sed 's/-.*//'` OS_RELEASE=`echo $OS_RELEASE | awk -F\. '{ print $1 "." $2 }'` fi ####################################################################### # Master "Core Components" macros for getting the OS target # ####################################################################### # # Note: OS_TARGET should be specified on the command line for gmake. # When OS_TARGET=WIN95 is specified, then a Windows 95 target is built. # The difference between the Win95 target and the WinNT target is that # the WinNT target uses Windows NT specific features not available # in Windows 95. The Win95 target will run on Windows NT, but (supposedly) # at lesser performance (the Win95 target uses threads; the WinNT target # uses fibers). # # If OS_TARGET is not specified, it defaults to $(OS_ARCH), i.e., no # cross-compilation. # # # The following hack allows one to build on a WIN95 machine (as if # s/he were cross-compiling on a WINNT host for a WIN95 target). # It also accomodates for MKS's uname.exe. If you never intend # to do development on a WIN95 machine, you don't need this hack. # case "$OS_ARCH" in Windows_95) OS_ARCH=Windows_NT OS_TARGET=WIN95 ;; Windows_98) OS_ARCH=Windows_NT OS_TARGET=WIN95 ;; CYGWIN_9*|CYGWIN_ME*) OS_ARCH='CYGWIN_NT-4.0' OS_TARGET=WIN95 ;; OS_2) OS_ARCH=OS2 OS_TARGET=OS2 ;; esac # # On WIN32, we also define the variable CPU_ARCH. # case "$OS_ARCH" in Windows_NT) # # If uname -s returns "Windows_NT", we assume that we are using # the uname.exe in MKS toolkit. # # The -r option of MKS uname only returns the major version number. # So we need to use its -v option to get the minor version number. # Moreover, it doesn't have the -p option, so we need to use uname -m. # OS_ARCH=WINNT OS_MINOR_RELEASE=`uname -v` if test "$OS_MINOR_RELEASE" = "00"; then OS_MINOR_RELEASE=0 fi OS_RELEASE="${OS_RELEASE}.${OS_MINOR_RELEASE}" CPU_ARCH=`uname -m` # # MKS's uname -m returns "586" on a Pentium machine. # if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then CPU_ARCH=x86 fi ;; CYGWIN_NT*|MINGW*_NT*|MSYS_NT*) # # If uname -s returns "CYGWIN_NT-4.0", we assume that we are using # the uname.exe in the Cygwin tools. # If uname -s returns "MINGW32_NT-5.1", we assume that we are using # the uname.exe in the MSYS tools. # If uname -s returns "MSYS_NT-6.3", we assume that we are using # the uname.exe in the MSYS2 tools. # OS_RELEASE=`expr $OS_ARCH : '.*NT-\(.*\)'` OS_ARCH=WINNT CPU_ARCH=`uname -m` # # Cygwin's uname -m returns "i686" on a Pentium Pro machine. # if echo "$CPU_ARCH" | grep -c 86 >/dev/null; then CPU_ARCH=x86 fi ;; esac if test -n "$MOZILLA_CLIENT" && test "$OS_ARCH" = "WINNT"; then OS_TARGET=WIN95 if test -n "$MOZ_DEBUG" -a -z "$USE_DEBUG_RTL"; then USE_DEBUG_RTL=1 fi fi if test -z "$OS_TARGET"; then OS_TARGET=$OS_ARCH fi if test "$OS_TARGET" = "WIN95"; then OS_RELEASE="4.0" fi OS_CONFIG="${OS_TARGET}${OS_RELEASE}" dnl ======================================================== dnl Enable high-memory support on OS/2 by default. dnl ======================================================== AC_ARG_ENABLE(os2-high-mem, [ --disable-os2-high-mem Disable high-memory support on OS/2], [ if test "$enableval" = "no"; then MOZ_OS2_HIGH_MEMORY= else MOZ_OS2_HIGH_MEMORY=1 fi ]) dnl ======================================================== dnl = ARM toolchain tweaks dnl ======================================================== dnl Defaults MOZ_ALIGN=toolchain-default case "$target" in arm*-android*|arm*-linuxandroid*) MOZ_THUMB=yes MOZ_ARCH=armv7-a MOZ_FPU=vfp MOZ_FLOAT_ABI=softfp MOZ_SOFT_FLOAT=yes MOZ_ALIGN=no ;; arm*-*) if test -n "$MOZ_PLATFORM_MAEMO"; then MOZ_THUMB=no MOZ_ARCH=armv7-a MOZ_FLOAT_ABI=softfp fi if test "$MOZ_PLATFORM_MAEMO" = 6; then MOZ_THUMB=yes fi ;; esac dnl Kept for compatibility with some buildbot mozconfig AC_ARG_ENABLE(thumb2, [], MOZ_THUMB=$enableval) AC_ARG_WITH(thumb, [ --with-thumb[[=yes|no|toolchain-default]]] [ Use Thumb instruction set (-mthumb)], if test -z "$GNU_CC"; then AC_MSG_ERROR([--with-thumb is not supported on non-GNU toolchain-defaults]) fi MOZ_THUMB=$withval) AC_ARG_WITH(thumb-interwork, [ --with-thumb-interwork[[=yes|no|toolchain-default]] Use Thumb/ARM instuctions interwork (-mthumb-interwork)], if test -z "$GNU_CC"; then AC_MSG_ERROR([--with-thumb-interwork is not supported on non-GNU toolchain-defaults]) fi MOZ_THUMB_INTERWORK=$withval) AC_ARG_WITH(arch, [ --with-arch=[[type|toolchain-default]] Use specific CPU features (-march=type)], if test -z "$GNU_CC"; then AC_MSG_ERROR([--with-arch is not supported on non-GNU toolchain-defaults]) fi MOZ_ARCH=$withval) AC_ARG_WITH(fpu, [ --with-fpu=[[type|toolchain-default]] Use specific FPU type (-mfpu=type)], if test -z "$GNU_CC"; then AC_MSG_ERROR([--with-fpu is not supported on non-GNU toolchain-defaults]) fi MOZ_FPU=$withval) AC_ARG_WITH(float-abi, [ --with-float-abi=[[type|toolchain-default]] Use specific arm float ABI (-mfloat-abi=type)], if test -z "$GNU_CC"; then AC_MSG_ERROR([--with-float-abi is not supported on non-GNU toolchain-defaults]) fi MOZ_FLOAT_ABI=$withval) AC_ARG_WITH(soft-float, [ --with-soft-float[[=yes|no|toolchain-default]] Use soft float library (-msoft-float)], if test -z "$GNU_CC"; then AC_MSG_ERROR([--with-soft-float is not supported on non-GNU toolchain-defaults]) fi MOZ_SOFT_FLOAT=$withval) case "$MOZ_ARCH" in toolchain-default|"") arch_flag="" ;; *) arch_flag="-march=$MOZ_ARCH" ;; esac case "$MOZ_THUMB" in yes) MOZ_THUMB2=1 thumb_flag="-mthumb" ;; no) MOZ_THUMB2= thumb_flag="-marm" ;; *) _SAVE_CFLAGS="$CFLAGS" CFLAGS="$arch_flag" AC_TRY_COMPILE([],[return sizeof(__thumb2__);], MOZ_THUMB2=1, MOZ_THUMB2=) CFLAGS="$_SAVE_CFLAGS" thumb_flag="" ;; esac case "$MOZ_THUMB_INTERWORK" in yes) thumb_interwork_flag="-mthumb-interwork" ;; no) thumb_interwork_flag="-mno-thumb-interwork" ;; *) # toolchain-default thumb_interwork_flag="" ;; esac case "$MOZ_FPU" in toolchain-default|"") fpu_flag="" ;; *) fpu_flag="-mfpu=$MOZ_FPU" ;; esac case "$MOZ_FLOAT_ABI" in toolchain-default|"") float_abi_flag="" ;; *) float_abi_flag="-mfloat-abi=$MOZ_FLOAT_ABI" ;; esac case "$MOZ_SOFT_FLOAT" in yes) soft_float_flag="-msoft-float" ;; no) soft_float_flag="-mno-soft-float" ;; *) # toolchain-default soft_float_flag="" ;; esac case "$MOZ_ALIGN" in toolchain-default|"") align_flag="" ;; no) align_flag="-mno-unaligned-access" ;; yes) align_flag="-munaligned-access" ;; *) align_flag="" ;; esac if test -n "$align_flag"; then _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $align_flag" AC_MSG_CHECKING(whether alignment flag ($align_flag) is supported) AC_TRY_COMPILE([],[],,align_flag="") CFLAGS="$_SAVE_CFLAGS" fi dnl Use echo to avoid accumulating space characters all_flags=`echo $arch_flag $thumb_flag $thumb_interwork_flag $fpu_flag $float_abi_flag $soft_float_flag $align_flag` if test -n "$all_flags"; then _SAVE_CFLAGS="$CFLAGS" CFLAGS="$all_flags" AC_MSG_CHECKING(whether the chosen combination of compiler flags ($all_flags) works) AC_TRY_COMPILE([],[return 0;], AC_MSG_RESULT([yes]), AC_MSG_ERROR([no])) CFLAGS="$_SAVE_CFLAGS $all_flags" CXXFLAGS="$CXXFLAGS $all_flags" ASFLAGS="$ASFLAGS $all_flags" if test -n "$thumb_flag"; then LDFLAGS="$LDFLAGS $thumb_flag" fi fi dnl ======================================================== dnl Override of system specific host options dnl ======================================================== case "$host" in *-mingw*|*-msys*) NSINSTALL=nsinstall ;; *-cygwin*|*-mks*) NSINSTALL='$(CYGWIN_WRAPPER) nsinstall' if test `echo "${PATH}" | grep -c \;` = 0; then CYGWIN_WRAPPER='sh $(topsrcdir)/build/cygwin-wrapper' fi ;; *-beos*) HOST_CFLAGS="$HOST_CFLAGS -DXP_BEOS -DBeOS -DBEOS -D_POSIX_SOURCE" ;; *os2*) ;; *) HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX" ;; esac dnl ======================================================== dnl Override of system specific target options dnl ======================================================== case "$target" in *-aix*) AC_DEFINE(XP_UNIX) AC_DEFINE(AIX) AC_DEFINE(SYSV) DSO_LDOPTS='-brtl -bnortllib -bM:SRE -bnoentry -bexpall -blibpath:/usr/lib:/lib' AC_CHECK_HEADER(sys/atomic_op.h, AC_DEFINE(AIX_HAVE_ATOMIC_OP_H)) case "${target_os}" in aix3.2*) AC_DEFINE(AIX_RENAME_SELECT) AC_DEFINE(_PR_NO_LARGE_FILES) AIX_LINK_OPTS='-bnso -berok' PR_MD_ASFILES=os_AIX.s ;; aix4.1*) AC_DEFINE(AIX_TIMERS) AC_DEFINE(_PR_NO_LARGE_FILES) AC_DEFINE(AIX4_1) MKSHLIB= DSO_LDOPTS= AIX_LINK_OPTS='-bnso -berok' LIBNSPR='-L$(dist_libdir) -lnspr$(MOD_MAJOR_VERSION)_shr' LIBPLC='-L$(dist_libdir) -lplc$(MOD_MAJOR_VERSION)_shr' ;; aix4.2*) AC_DEFINE(AIX_TIMERS) AC_DEFINE(_PR_HAVE_OFF64_T) AIX_LINK_OPTS='-brtl -bnso -berok' ;; aix4.3*) AC_DEFINE(AIX_TIMERS) AC_DEFINE(_PR_HAVE_OFF64_T) AC_DEFINE(AIX4_3_PLUS) AC_DEFINE(HAVE_SOCKLEN_T) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) USE_IPV6=1 AIX_LINK_OPTS='-brtl -bnso -berok' ;; *) AC_DEFINE(AIX_TIMERS) AC_DEFINE(_PR_HAVE_OFF64_T) AC_DEFINE(AIX4_3_PLUS) AC_DEFINE(HAVE_SOCKLEN_T) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) USE_IPV6=1 AIX_LINK_OPTS='-brtl -bnso -berok' ;; esac CFLAGS="$CFLAGS -qro -qroconst" AIX_WRAP='$(DIST)/lib/aixwrap.o' AIX_TMP='./_aix_tmp.o' if test -n "$USE_64"; then MDCPUCFG_H=_aix64.cfg OBJECT_MODE=64 else MDCPUCFG_H=_aix32.cfg fi PR_MD_CSRCS=aix.c RESOLVE_LINK_SYMBOLS=1 ;; *-beos*) AC_DEFINE(XP_BEOS) AC_DEFINE(BeOS) AC_DEFINE(BEOS) AC_DEFINE(_POSIX_SOURCE) DSO_LDOPTS=-nostart MDCPUCFG_H=_beos.cfg USE_BTHREADS=1 PR_MD_ARCH_DIR=beos RESOLVE_LINK_SYMBOLS=1 case "${target_cpu}" in i*86) _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS='-gdwarf-2 -O0' MKSHLIB='$(CCC) $(DSO_LDOPTS) -o $@' AC_CHECK_LIB(bind, gethostbyaddr, [OS_LIBS="$OS_LIBS -lbind -lsocket"]) ;; powerpc) CC=mwcc CCC=mwcc LD=mwld DSO_LDOPTS='-xms -export pragma -init _init_routine_ -term _term_routine_ -lroot -lnet /boot/develop/lib/ppc/glue-noinit.a /boot/develop/lib/ppc/init_term_dyn.o /boot/develop/lib/ppc/start_dyn.o' _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS='-g -O0' ;; esac ;; *-bsdi*) AC_DEFINE(XP_UNIX) AC_DEFINE(BSDI) AC_DEFINE(NEED_BSDREGEX) CFLAGS="$CFLAGS -Wall -Wno-format" CXXFLAGS="$CXXFLAGS -Wall -Wno-format" if echo "$OS_TEST" | grep -c 86 >/dev/null; then CPU_ARCH=x86 elif echo "$OS_TEST" | grep -c sparc >/dev/null; then CPU_ARCH=sparc fi MDCPUCFG_H=_bsdi.cfg PR_MD_CSRCS=bsdi.c DSO_LDOPTS=-r case "$target_os" in bsdi1.1*) AC_DEFINE(_PR_BSDI_JMPBUF_IS_ARRAY) AC_DEFINE(_PR_STAT_HAS_ONLY_ST_ATIME) AC_DEFINE(_PR_NEED_H_ERRNO) MKSHLIB= DSO_CFLAGS= DSO_LDOPTS= ;; bsdi2.1*) AC_DEFINE(_PR_TIMESPEC_HAS_TS_SEC) AC_DEFINE(_PR_BSDI_JMPBUF_IS_ARRAY) AC_DEFINE(HAVE_DLL) AC_DEFINE(USE_DLFCN) AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC) PR_MD_ASFILES=os_BSD_OS_386_2.s ;; bsdi4.* | bsdi5.*) AC_DEFINE(_PR_SELECT_CONST_TIMEVAL) AC_DEFINE(_PR_BSDI_JMPBUF_IS_STRUCT) AC_DEFINE(HAVE_DLL) AC_DEFINE(USE_DLFCN) AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC) MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)' DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname,$(@:$(OBJDIR)/%.so=%.so)' STRIP="$STRIP -d" case "$target_os" in bsdi4.2* | bsdi4.3* | bsdi5.*) AC_DEFINE(_PR_HAVE_GETPROTO_R) AC_DEFINE(_PR_HAVE_GETPROTO_R_POINTER) ;; esac ;; *) AC_DEFINE(_PR_SELECT_CONST_TIMEVAL) AC_DEFINE(_PR_BSDI_JMPBUF_IS_STRUCT) AC_DEFINE(HAVE_DLL) AC_DEFINE(USE_DLFCN) AC_DEFINE(_PR_STAT_HAS_ST_ATIMESPEC) ;; esac ;; *-darwin*) AC_DEFINE(XP_UNIX) AC_DEFINE(DARWIN) AC_DEFINE(HAVE_BSD_FLOCK) AC_DEFINE(HAVE_SOCKLEN_T) AS='$(CC) -x assembler-with-cpp' CFLAGS="$CFLAGS -Wall -fno-common" case "${target_cpu}" in arm*) CPU_ARCH=arm ;; i*86*|x86_64) if test -n "$USE_64"; then CPU_ARCH=x86_64 else CPU_ARCH=i386 fi ;; *) CPU_ARCH=ppc ;; esac if test "`echo $CC | grep -c '\-arch '`" = "0"; then CC="$CC -arch $CPU_ARCH" fi AC_CHECK_HEADER(crt_externs.h, AC_DEFINE(HAVE_CRT_EXTERNS_H)) DSO_CFLAGS=-fPIC DSO_LDOPTS='-dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name @executable_path/$@ -headerpad_max_install_names' _OPTIMIZE_FLAGS=-O2 MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' STRIP="$STRIP -x -S" DLL_SUFFIX=dylib USE_PTHREADS=1 MDCPUCFG_H=_darwin.cfg PR_MD_CSRCS=darwin.c PR_MD_ASFILES=os_Darwin.s # Add Mac OS X support for loading CFM & CFBundle plugins if test -f "${MACOS_SDK_DIR}/System/Library/Frameworks/Carbon.framework/Carbon"; then AC_DEFINE(XP_MACOSX) OS_TARGET=MacOSX if test -n "$_MACOSX_DEPLOYMENT_TARGET" ; then dnl Use the specified value export MACOSX_DEPLOYMENT_TARGET=$_MACOSX_DEPLOYMENT_TARGET elif test -z "$MACOSX_DEPLOYMENT_TARGET" ; then dnl No value specified on the command line or in the environment, dnl use the lesser of the library's minimum or the architecture's dnl minimum. case "${target_cpu}" in powerpc*) dnl Architecture minimum 10.2 export MACOSX_DEPLOYMENT_TARGET=10.2 ;; i*86*) dnl Architecture minimum 10.4 export MACOSX_DEPLOYMENT_TARGET=10.4 ;; esac fi dnl MACOS_SDK_DIR will be set to the SDK location whenever one is dnl in use. NEXT_ROOT will be set and exported if it's needed for dnl ld. if test "$MACOS_SDK_DIR"; then dnl Sync this section with the one in Mozilla's top level. if test ! -d "$MACOS_SDK_DIR"; then AC_MSG_ERROR([SDK not found. When using --with-macos-sdk, you must specify a valid SDK. SDKs are installed when the optional cross-development tools are selected during the Xcode/Developer Tools installation.]) fi changequote(,) CC_VERSION=`$CC -v 2>&1 | grep 'gcc version'` GCC_VERSION_FULL=`echo $CC_VERSION | $PERL -pe 's/^.*gcc version ([^ ]*).*/$1/'` GCC_VERSION=`echo $GCC_VERSION_FULL | $PERL -pe '(split(/\./))[0]>=4&&s/(^\d*\.\d*).*/$1/;'` changequote([,]) GCC_VERSION_MAJOR=`echo $GCC_VERSION_FULL | $PERL -pe 's/(^\d*).*/$1/;'` if test "$GCC_VERSION_MAJOR" -lt "4" ; then SDK_C_FRAMEWORK="-F${MACOS_SDK_DIR}/System/Library/Frameworks" if test -d "${MACOS_SDK_DIR}/Library/Frameworks" ; then SDK_C_FRAMEWORK="$SDK_C_FRAMEWORK -F${MACOS_SDK_DIR}/Library/Frameworks" fi SDK_C_INCLUDE="-isystem ${MACOS_SDK_DIR}/usr/include/gcc/darwin/${GCC_VERSION} -isystem ${MACOS_SDK_DIR}/usr/include ${SDK_C_FRAMEWORK}" CFLAGS="$CFLAGS -nostdinc ${SDK_C_INCLUDE}" dnl CPP needs to be set for AC_CHECK_HEADER. CPP="$CPP -nostdinc ${SDK_C_INCLUDE}" changequote(,) HOST_DARWIN_MAJOR=`echo "$build_os" | sed -E -e 's/^darwin([0-9]+).*$/\1/'` changequote([,]) if test "$HOST_DARWIN_MAJOR" -lt 9 ; then dnl The build host is running Tiger (10.4) or earlier. dnl ld support for -syslibroot is compiler-agnostic, but dnl only available on Tiger and later. On Tiger and dnl earlier build hosts, just rely on NEXT_ROOT, because dnl it's not been shown to cause any problems. MACOS_SDK_LIBS="-L${MACOS_SDK_DIR}/usr/lib/gcc/darwin -L${MACOS_SDK_DIR}/usr/lib/gcc/darwin/${GCC_VERSION_FULL} -L${MACOS_SDK_DIR}/usr/lib ${SDK_C_FRAMEWORK}" else dnl The build host is running Leopard (10.5) or later. dnl With NEXT_ROOT set, the linker will still not apply dnl it when resolving dependencies. This causes problems dnl on Leopard, where an SDK depends on frameworks which dnl were present in earlier OS releases (and the associated dnl SDK) but not in Leopard. -syslibroot does not have dnl this problem, but it results in harmless warnings when dnl NEXT_ROOT is set. NEXT_ROOT needs to remain set even dnl on Leopard because the compiler uses it too. MACOS_SDK_LIBS="-Wl,-syslibroot,${MACOS_SDK_DIR}" fi LDFLAGS="${MACOS_SDK_LIBS} $LDFLAGS" export NEXT_ROOT=$MACOS_SDK_DIR if test -n "$CROSS_COMPILE" ; then dnl NEXT_ROOT will be in the environment, but it dnl shouldn't be set for the build host. HOST_CXX is dnl presently unused. HOST_CC="NEXT_ROOT= $HOST_CC" HOST_CXX="NEXT_ROOT= $HOST_CXX" fi else dnl gcc >= 4.0 uses different paths than above, but knows dnl how to find them itself. CFLAGS="$CFLAGS -isysroot ${MACOS_SDK_DIR}" dnl CPP needs to be set for AC_CHECK_HEADER. CPP="$CPP -isysroot ${MACOS_SDK_DIR}" dnl If gcc >= 4.0.0, we're guaranteed to be on Tiger, which dnl has an ld that supports -syslibroot. Don't set dnl NEXT_ROOT because it will be ignored and cause dnl warnings when -syslibroot is specified. if test "$GCC_VERSION_FULL" != "4.0.0" ; then dnl gcc > 4.0.0 will pass -syslibroot to ld automatically dnl based on the -isysroot it receives. LDFLAGS="$LDFLAGS -isysroot ${MACOS_SDK_DIR}" else dnl gcc 4.0.0 doesn't pass -syslibroot to ld, it needs dnl to be explicit. LDFLAGS="$LDFLAGS -Wl,-syslibroot,${MACOS_SDK_DIR}" fi fi fi fi ;; *-dgux*) AC_DEFINE(XP_UNIX) AC_DEFINE(_PR_LOCAL_THREADS_ONLY) AC_DEFINE(SVR4) AC_DEFINE(SYSV) AC_DEFINE(DGUX) AC_DEFINE(_DGUX_SOURCE) AC_DEFINE(_POSIX4A_DRAFT6_SOURCE) DSO_LDOPTS=-G _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS= MDCPUCFG_H=_dgux.cfg PR_MD_CSRCS=dgux.c ;; *-freebsd*) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi AC_DEFINE(XP_UNIX) AC_DEFINE(FREEBSD) AC_DEFINE(HAVE_BSD_FLOCK) AC_DEFINE(HAVE_SOCKLEN_T) CFLAGS="$CFLAGS $(DSO_CFLAGS) -ansi -Wall" MOZ_OBJFORMAT=`test -x /usr/bin/objformat && /usr/bin/objformat || echo elf` if test "$MOZ_OBJFORMAT" = "elf"; then DLL_SUFFIX=so else DLL_SUFFIX=so.1.0 fi MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' MDCPUCFG_H=_freebsd.cfg PR_MD_CSRCS=freebsd.c ;; *-hpux*) AC_DEFINE(XP_UNIX) AC_DEFINE(HPUX) AC_DEFINE(_HPUX_SOURCE) # OSF1 and HPUX report the POLLHUP event for a socket when the # shutdown(SHUT_WR) operation is called for the remote end, even though # the socket is still writeable. Use select(), instead of poll(), to # workaround this problem. AC_DEFINE(_PR_POLL_WITH_SELECT) AC_DEFINE(_USE_BIG_FDS) DSO_LDOPTS='-b +h $(notdir $@)' PR_MD_CSRCS=hpux.c if test "$OS_TEST" = "ia64"; then DLL_SUFFIX=so DSO_LDOPTS="$DSO_LDOPTS +b '\$\$ORIGIN'" CPU_ARCH_TAG=_$OS_TEST if test -z "$USE_64"; then COMPILER_TAG=_32 fi PR_MD_ASFILES=os_HPUX_ia64.s else AC_DEFINE(hppa) DLL_SUFFIX=sl PR_MD_ASFILES=os_HPUX.s fi if test -n "$USE_64"; then MDCPUCFG_H=_hpux64.cfg else MDCPUCFG_H=_hpux32.cfg fi if test -z "$GNU_CC"; then CC="$CC -Ae" CXX="$CXX -ext" DSO_CFLAGS=+Z else DSO_CFLAGS=-fPIC ASFLAGS="$ASFLAGS -x assembler-with-cpp" fi if test -n "$MOZILLA_CLIENT"; then DEFAULT_IMPL_STRATEGY=_EMU fi if echo "$OS_RELEASE" | grep ^A.09 >/dev/null; then AC_DEFINE(_PR_NEED_H_ERRNO) AC_DEFINE(HPUX9) DEFAULT_IMPL_STRATEGY=_EMU USE_NSPR_THREADS=1 fi if echo "$OS_RELEASE" | egrep '^(A.09|B.10)' >/dev/null; then AC_DEFINE(_PR_NO_LARGE_FILES) fi if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then AC_DEFINE(_PR_NEED_H_ERRNO) fi if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then AC_DEFINE(HAVE_INT_LOCALTIME_R) fi if echo "$OS_RELEASE" | egrep '^(B.10.30|B.11)' >/dev/null; then AC_DEFINE(HAVE_POINTER_LOCALTIME_R) fi # HP-UX 11i v2 (B.11.23) or higher changequote(<<,>>) case "$OS_RELEASE" in [C-Z]*|B.[2-9]*|B.1[2-9]*|B.11.[3-9]*|B.11.2[3-9]*) USE_IPV6=1 ;; esac changequote([,]) if test "$OS_RELEASE" = "B.10.01"; then AC_DEFINE(HPUX10) DEFAULT_IMPL_STRATEGY=_EMU fi if test "$OS_RELEASE" = "B.10.10"; then AC_DEFINE(HPUX10) AC_DEFINE(HPUX10_10) DEFAULT_IMPL_STRATEGY=_PTH fi if test "$OS_RELEASE" = "B.10.20"; then AC_DEFINE(HPUX10) AC_DEFINE(HPUX10_20) if test -z "$GNU_CC"; then CFLAGS="$CFLAGS +DAportable +DS1.1" CXXFLAGS="$CXXFLAGS +DAportable +DS1.1" fi DEFAULT_IMPL_STRATEGY=_PTH fi if test "$OS_RELEASE" = "B.10.30"; then AC_DEFINE(HPUX10) AC_DEFINE(HPUX10_30) if test -z "$GNU_CC"; then CFLAGS="$CFLAGS +DAportable +DS1.1" CXXFLAGS="$CXXFLAGS +DAportable +DS1.1" fi DEFAULT_IMPL_STRATEGY=_PTH fi if echo "$OS_RELEASE" | grep ^B.11 >/dev/null; then AC_DEFINE(HPUX10) AC_DEFINE(HPUX11) AC_DEFINE(_LARGEFILE64_SOURCE) AC_DEFINE(_PR_HAVE_OFF64_T) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) if test -z "$GNU_CC"; then if test -z "$USE_64"; then if test "$OS_TEST" = "ia64"; then CFLAGS="$CFLAGS +DD32" CXXFLAGS="$CXXFLAGS +DD32" else CFLAGS="$CFLAGS +DAportable +DS2.0" CXXFLAGS="$CXXFLAGS +DAportable +DS2.0" fi else if test "$OS_TEST" = "ia64"; then CFLAGS="$CFLAGS +DD64" CXXFLAGS="$CXXFLAGS +DD64" else CFLAGS="$CFLAGS +DA2.0W +DS2.0" CXXFLAGS="$CXXFLAGS +DA2.0W +DS2.0" fi fi fi DEFAULT_IMPL_STRATEGY=_PTH fi if test "$DEFAULT_IMPL_STRATEGY" = "_EMU"; then USE_NSPR_THREADS=1 USE_PTHREADS= USE_USER_PTHREADS= elif test "$DEFAULT_IMPL_STRATEGY" = "_PTH"; then USE_PTHREADS=1 if test "$USE_NSPR_THREADS"; then USE_PTHREADS= fi if test "$USE_USER_PTHREADS"; then USE_PTHREADS= fi fi ;; *-irix*) AC_DEFINE(XP_UNIX) AC_DEFINE(IRIX) AC_DEFINE(SVR4) AC_DEFINE(_SGI_MP_SOURCE) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) PR_MD_CSRCS=irix.c PR_MD_ASFILES=os_Irix.s MKSHLIB='$(LD) $(DSO_LDOPTS) -rdata_shared -shared -soname $(notdir $@) -o $@' STRIP="$STRIP -f" RESOLVE_LINK_SYMBOLS=1 if test -n "$USE_64"; then MDCPUCFG_H=_irix64.cfg else MDCPUCFG_H=_irix32.cfg fi case "${target_os}" in irix6*) AC_DEFINE(IRIX6) USE_PTHREADS=1 USE_N32=1 COMPILER_TAG=_n32 IMPL_STRATEGY=_PTH ;; irix5*) AC_DEFINE(IRIX5) USE_NSPR_THREADS=1 ;; *) USE_PTHREADS=1 USE_N32=1 ;; esac if test "$GNU_CC"; then dnl dnl If we are using gcc with native binutils, we need to dnl suppress the dnl #lineno "filename" num num dnl lines, which confuse IRIX native as. Add -Wp,-P to the dnl gcc command line, which passes -P to the preprocessor. dnl AS='$(CC) -Wp,-P -x assembler-with-cpp -D_ASM -mips2 $(INCLUDES)' CFLAGS="$CFLAGS -Wall -Wno-format" _OPTIMIZE_FLAGS="-O6" else if test -n "$USE_N32"; then AS='as -D_ASM $(INCLUDES) -n32' else AS='as -D_ASM $(INCLUDES)' fi CFLAGS="$CFLAGS -fullwarn -xansi" if test "$USE_N32"; then _OPTIMIZE_FLAGS="-O -OPT:Olimit=4000" else _OPTIMIZE_FLAGS="-O -Olimit 4000" fi if test "$USE_MDUPDATE"; then CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)" fi case "${target}" in *-irix6.*) CFLAGS="$CFLAGS -multigot" DSO_LDOPTS="-no_unresolved" if test "$USE_N32"; then CFLAGS="$CFLAGS -n32 -woff 1209" DSO_LDOPTS="$DSO_LDOPTS -n32" else if test "$USE_64"; then CFLAGS="$CFLAGS -64" else CFLAGS="$CFLAGS -32" fi fi ;; *) CFLAGS="$CFLAGS -xgot" ;; esac fi if test "${target_os}" = "irix5.3"; then AC_DEFINE(IRIX5_3) fi case "${target_os}" in irix6.5) if test -z "$GNU_CC"; then CFLAGS="$CFLAGS -mips3" fi AC_DEFINE(_PR_HAVE_GETPROTO_R) AC_DEFINE(_PR_HAVE_GETPROTO_R_POINTER) AC_DEFINE(_PR_HAVE_SGI_PRDA_PROCMASK) ;; irix5*) ;; *) AC_DEFINE(_PR_HAVE_SGI_PRDA_PROCMASK) ;; esac ;; *-linux*|*-gnu*|*-k*bsd*-gnu|*-android*|*-linuxandroid*) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 IMPL_STRATEGY=_PTH fi AC_DEFINE(XP_UNIX) AC_DEFINE(_GNU_SOURCE) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) case "${target}" in *-android*|*-linuxandroid*) OS_TARGET=Android AC_DEFINE(LINUX) ;; *-linux*) AC_DEFINE(LINUX) ;; esac CFLAGS="$CFLAGS -Wall" CXXFLAGS="$CXXFLAGS -Wall" MDCPUCFG_H=_linux.cfg PR_MD_CSRCS=linux.c MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' _OPTIMIZE_FLAGS=-O2 _DEBUG_FLAGS="-g -fno-inline" # most people on linux use gcc/gdb, and that # combo is not yet good at debugging inlined # functions (even when using DWARF2 as the # debugging format) COMPILER_TAG=_glibc if echo "$OS_TEST" | grep -c 86 >/dev/null; then CPU_ARCH=x86 else CPU_ARCH=$OS_TEST fi CPU_ARCH_TAG=_${CPU_ARCH} case "${target_cpu}" in alpha) AC_DEFINE(_ALPHA_) AC_DEFINE(__alpha) CFLAGS="$CFLAGS -mieee" CXXFLAGS="$CXXFLAGS -mieee" ;; i*86) AC_DEFINE(i386) PR_MD_ASFILES=os_Linux_x86.s ;; ia64) PR_MD_ASFILES=os_Linux_ia64.s ;; x86_64) if test -n "$USE_64"; then PR_MD_ASFILES=os_Linux_x86_64.s elif test -n "$USE_X32"; then PR_MD_ASFILES=os_Linux_x86_64.s CC="$CC -mx32" CXX="$CXX -mx32" else AC_DEFINE(i386) PR_MD_ASFILES=os_Linux_x86.s CC="$CC -m32" CXX="$CXX -m32" fi ;; ppc|powerpc) PR_MD_ASFILES=os_Linux_ppc.s ;; powerpc64) if test -n "$USE_64"; then CC="$CC -m64" CXX="$CXX -m64" else PR_MD_ASFILES=os_Linux_ppc.s fi ;; m68k) CFLAGS="$CFLAGS -m68020-60" CXXFLAGS="$CXXFLAGS -m68020-60" ;; esac ;; *-mingw*|*-msys*|*-cygwin*|*-mks*) AC_DEFINE(XP_PC) AC_DEFINE(WIN32) PR_MD_ARCH_DIR=windows RESOLVE_LINK_SYMBOLS=1 if test -n "$GNU_CC"; then CC="$CC -mwindows" CXX="$CXX -mwindows" DLL_SUFFIX=dll MKSHLIB='$(CC) -shared -Wl,--export-all-symbols -Wl,--out-implib -Wl,$(IMPORT_LIBRARY) $(DLLBASE) -o $(subst $(OBJDIR)/,,$(SHARED_LIBRARY))' RC=$WINDRES # Use temp file for windres (bug 213281) RCFLAGS='-O coff --use-temp-file' else LD=link AR='lib -NOLOGO -OUT:"$@"' AR_FLAGS= RANLIB='echo not_ranlib' STRIP='echo not_strip' RC=rc.exe GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb' OBJ_SUFFIX=obj LIB_SUFFIX=lib DLL_SUFFIX=dll # Determine compiler version changequote(,) _MSVC_VER_FILTER='s|.* \([0-9]\+\.[0-9]\+\.[0-9]\+\(\.[0-9]\+\)\?\).*|\1|p' changequote([,]) CC_VERSION=`${CC} -v 2>&1 | sed -ne "$_MSVC_VER_FILTER"` if test -z "$CC_VERSION"; then AC_MSG_ERROR([Could not determine MSC version.]) fi _CC_MAJOR_VERSION=`echo ${CC_VERSION} | awk -F\. '{ print $1 }'` _CC_MINOR_VERSION=`echo ${CC_VERSION} | awk -F\. '{ print $2 }'` _CC_RELEASE=`echo ${CC_VERSION} | awk -F\. '{ print $3 }'` _CC_BUILD=`echo ${CC_VERSION} | awk -F\. '{ print $4 }'` MSC_VER=${_CC_MAJOR_VERSION}${_CC_MINOR_VERSION} if test "$_CC_MAJOR_VERSION" -eq "14"; then dnl -DYNAMICBASE is only supported on VC8SP1 or newer, dnl so be very specific here! dnl VC8 is 14.00.50727.42, VC8SP1 is 14.00.50727.762 if test $_CC_RELEASE -gt 50727; then _USE_DYNAMICBASE=1 elif test $_CC_BUILD -ge 762; then _USE_DYNAMICBASE=1 fi AC_DEFINE(_CRT_SECURE_NO_DEPRECATE) AC_DEFINE(_CRT_NONSTDC_NO_DEPRECATE) elif test $_CC_MAJOR_VERSION -ge 15; then _USE_DYNAMICBASE=1 AC_DEFINE(_CRT_SECURE_NO_WARNINGS) AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS) fi if test -n "$_USE_DYNAMICBASE"; then DLLFLAGS="$DLLFLAGS -DYNAMICBASE" fi # Ensure that mt is Microsoft (R) Manifest Tool and not magnetic # tape manipulation utility (or something else) if test "$MSC_VER" -ge "1400"; then changequote(,) _MSMT_VER_FILTER='s|.* \([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*|\1|p' changequote([,]) MSMT_TOOL=`mt 2>&1|grep 'Microsoft (R) Manifest Tool'` if test -n "$MSMT_TOOL"; then MSMANIFEST_TOOL_VERSION=`echo ${MSMT_TOOL}|sed -ne "$_MSMT_VER_FILTER"` if test -z "$MSMANIFEST_TOOL_VERSION"; then AC_MSG_WARN([Unknown version of the Microsoft (R) Manifest Tool.]) fi MT=mt unset MSMT_TOOL else AC_MSG_ERROR([Microsoft (R) Manifest Tool must be in your \$PATH.]) fi fi CFLAGS="$CFLAGS -W3 -nologo -GF -Gy" DLLFLAGS="$DLLFLAGS -OUT:\"\$@\"" _DEBUG_FLAGS=-Zi _OPTIMIZE_FLAGS=-O2 PROFILE_GEN_CFLAGS="-GL" PROFILE_GEN_LDFLAGS="-LTCG:PGINSTRUMENT" PROFILE_USE_CFLAGS="-GL -wd4624 -wd4952" PROFILE_USE_LDFLAGS="-LTCG:PGUPDATE" if test "$MSC_VER" -ge "1800"; then dnl Visual C++ 2013 requires -FS when parallel building with dnl make -jN. If not specified, compiler sometimes emits C1041 dnl error. CFLAGS="$CFLAGS -FS" dnl -Gw can benefit when using linker optimization on PGO. dnl http://blogs.msdn.com/b/vcblog/archive/2013/09/11/introducing-gw-compiler-switch.aspx PROFILE_GEN_CFLAGS="$PROFILE_GEN_CFLAGS -Gw" PROFILE_USE_CFLAGS="$PROFILE_USE_CFLAGS -Gw" fi if test -z "$MOZ_OPTIMIZE"; then CFLAGS="$CFLAGS -Od" fi if test "$USE_DEBUG_RTL" = 1; then if test -n "$USE_STATIC_RTL"; then CFLAGS="$CFLAGS -MTd" else CFLAGS="$CFLAGS -MDd" fi else if test -n "$USE_STATIC_RTL"; then CFLAGS="$CFLAGS -MT" else CFLAGS="$CFLAGS -MD" fi fi if test -n "$MOZ_DEBUG"; then AC_DEFINE(_DEBUG) else DEFINES="$DEFINES -U_DEBUG" fi if test -n "$MOZ_DEBUG_SYMBOLS"; then if test -n "$MOZ_OPTIMIZE"; then DLLFLAGS="$DLLFLAGS -DEBUG -OPT:REF" LDFLAGS="$LDFLAGS -DEBUG -OPT:REF" else DLLFLAGS="$DLLFLAGS -DEBUG" LDFLAGS="$LDFLAGS -DEBUG" fi fi OS_DLLFLAGS="-nologo -DLL -SUBSYSTEM:WINDOWS" if test "$MSC_VER" -le "1200" -a -z "$MOZ_DEBUG_SYMBOLS"; then OS_DLLFLAGS="$OS_DLLFLAGS -PDB:NONE" fi if test "$OS_TARGET" = "WINNT"; then CFLAGS="$CFLAGS -GT" LIBNSPR='$(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' LIBPLC='$(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' else LIBNSPR='$(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' LIBPLC='$(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX)' fi fi # GNU_CC if test -n "$USE_STATIC_TLS"; then AC_DEFINE(_PR_USE_STATIC_TLS) fi if test "$OS_TARGET" = "WINNT"; then AC_DEFINE(WINNT) else AC_DEFINE(WIN95) # undefine WINNT as some versions of mingw gcc define it by default DEFINES="$DEFINES -UWINNT" AC_DEFINE(_PR_GLOBAL_THREADS_ONLY) fi if test "$CPU_ARCH" = "x86"; then CPU_ARCH_TAG= else CPU_ARCH_TAG=$CPU_ARCH fi if test "$USE_DEBUG_RTL" = 1; then OBJDIR_SUFFIX=OBJD fi case "$OS_TARGET" in WINNT) MDCPUCFG_H=_winnt.cfg ;; WIN95) MDCPUCFG_H=_win95.cfg ;; *) AC_MSG_ERROR([Missing OS_TARGET for ${target}. Use --enable-win32-target to set.]) ;; esac case "$target_cpu" in i*86) if test -n "$USE_64"; then AC_DEFINE(_AMD64_) else AC_DEFINE(_X86_) if test -z "$GNU_CC" -a "$MSC_VER" -ge "1700"; then dnl Visual C++ 2012 defaults to -arch:SSE2. Use -arch:IA32 dnl to avoid requiring SSE2. CFLAGS="$CFLAGS -arch:IA32" fi fi ;; x86_64) AC_DEFINE(_AMD64_) USE_64=1 ;; ia64) AC_DEFINE(_IA64_) USE_64=1 ;; *) AC_DEFINE(_CPU_ARCH_NOT_DEFINED) ;; esac ;; *-netbsd*) AC_DEFINE(XP_UNIX) AC_DEFINE(NETBSD) AC_DEFINE(HAVE_BSD_FLOCK) AC_DEFINE(HAVE_SOCKLEN_T) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi MDCPUCFG_H=_netbsd.cfg PR_MD_CSRCS=netbsd.c DSO_CFLAGS='-fPIC -DPIC' CFLAGS="$CFLAGS -ansi -Wall" CXXFLAGS="$CXXFLAGS -ansi -Wall" MKSHLIB='$(CC) -o $@ $(DSO_LDOPTS)' if test -z "$OBJECT_FMT"; then if echo __ELF__ | ${CC-cc} -E - | grep -q __ELF__ 2>/dev/null; then OBJECT_FMT=a.out DLL_SUFFIX=so.1.0 DSO_LDOPTS='-shared' else OBJECT_FMT=ELF DLL_SUFFIX=so DSO_LDOPTS='-shared -Wl,-soname,$(notdir $@)' fi fi if test "$LIBRUNPATH"; then DSO_LDOPTS="$DSO_LDOPTS -Wl,-R$LIBRUNPATH" fi ;; *-nto*) AC_DEFINE(XP_UNIX) AC_DEFINE(NTO) AC_DEFINE(_QNX_SOURCE) AC_DEFINE(HAVE_POINTER_LOCALTIME_R) MDCPUCFG_H=_nto.cfg PR_MD_CSRCS=nto.c MKSHLIB='$(CC) $(DSO_LDOPTS) -Wl,-soname -Wl,$(notdir $@) -o $@' DSO_CFLAGS=-fPIC DSO_LDOPTS=-shared OS_LIBS="$OS_LIBS -lsocket" _OPTIMIZE_FLAGS="-O1" _DEBUG_FLAGS="-gstabs" ;; *-openbsd*) AC_DEFINE(XP_UNIX) AC_DEFINE(OPENBSD) AC_DEFINE(HAVE_BSD_FLOCK) AC_DEFINE(HAVE_SOCKLEN_T) CFLAGS="$CFLAGS -ansi -Wall" CXXFLAGS="$CXXFLAGS -ansi -Wall" DLL_SUFFIX=so.1.0 DSO_CFLAGS=-fPIC MDCPUCFG_H=_openbsd.cfg PR_MD_CSRCS=openbsd.c OS_LIBS="-lc" if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi DSO_LDOPTS='-shared -fPIC -Wl,-soname,$(notdir $@)' MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' ;; *-osf*) SHELL_OVERRIDE="SHELL = /usr/bin/ksh" AC_DEFINE(XP_UNIX) AC_DEFINE(OSF1) AC_DEFINE(_REENTRANT) # OSF1 and HPUX report the POLLHUP event for a socket when the # shutdown(SHUT_WR) operation is called for the remote end, even though # the socket is still writeable. Use select(), instead of poll(), to # workaround this problem. AC_DEFINE(_PR_POLL_WITH_SELECT) if echo "$OS_RELEASE" | egrep -c '(V2.0|V3.2)' 2>/dev/null ; then USE_NSPR_THREADS=1 fi if test -z "$GNU_CC"; then CC="$CC -std1 -ieee_with_inexact" if test "$OS_RELEASE" != "V2.0"; then CC="$CC -readonly_strings" fi _OPTIMIZE_FLAGS="$_OPTIMIZE_FLAGS -Olimit 4000" AC_CHECK_HEADER(machine/builtins.h, AC_DEFINE(OSF1_HAVE_MACHINE_BUILTINS_H)) else CFLAGS="$CFLAGS -mieee" CXXFLAGS="$CXXFLAGS -mieee" fi if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then AC_DEFINE(HAVE_INT_LOCALTIME_R) else AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) AC_DEFINE(HAVE_POINTER_LOCALTIME_R) fi if echo $OS_RELEASE | grep -c V4.0 >/dev/null; then AC_DEFINE(OSF1V4_MAP_PRIVATE_BUG) fi DSO_LDOPTS='-shared -all -expect_unresolved "*" -soname $(notdir $@)' MDCPUCFG_H=_osf1.cfg PR_MD_CSRCS=osf1.c ;; *-qnx*) AC_DEFINE(XP_UNIX) AC_DEFINE(QNX) AC_DEFINE(_PR_NEED_H_ERRNO) USE_NSPR_THREADS=1 MDCPUCFG_H=_qnx.cfg PR_MD_CSRCS=qnx.c ;; *-riscos*) AC_DEFINE(XP_UNIX) AC_DEFINE(RISCOS) AC_DEFINE(_PR_NEED_H_ERRNO) USE_PTHREADS=1 MDCPUCFG_H=_riscos.cfg PR_MD_CSRCS=riscos.c DSO_CFLAGS=-fPIC DSO_LDOPTS='-shared -Wl,-soname -Wl,$(notdir $@)' MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' ;; *-*-sco*) AC_DEFINE(XP_UNIX) AC_DEFINE(SCO) AC_DEFINE(sco) AC_DEFINE(SYSV) AC_DEFINE(_SVID3) AC_DEFINE(_PR_NEED_H_ERRNO) CC='cc -b elf -KPIC' CXX='$(NSDEPTH)/build/hcpp CC +.cpp +w' USE_NSPR_THREADS=1 CPU_ARCH=x86 DSO_LDOPTS='-b elf -G' MDCPUCFG_H=_scoos.cfg PR_MD_SRCS=scoos.c ;; *-solaris*) if test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 fi AC_DEFINE(XP_UNIX) AC_DEFINE(SVR4) AC_DEFINE(SYSV) AC_DEFINE(__svr4) AC_DEFINE(__svr4__) AC_DEFINE(SOLARIS) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) CPU_ARCH=`uname -p` MDCPUCFG_H=_solaris.cfg PR_MD_CSRCS=solaris.c LD=/usr/ccs/bin/ld MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' RESOLVE_LINK_SYMBOLS=1 case "${OS_RELEASE}" in 5.8|5.9) ;; *) # It is safe to use the -Bdirect linker flag on Solaris 10 or later. USE_B_DIRECT=1 ;; esac if test -n "$GNU_CC"; then DSO_CFLAGS=-fPIC if `$CC -print-prog-name=ld` -v 2>&1 | grep -c GNU >/dev/null; then GCC_USE_GNU_LD=1 fi DSO_LDOPTS='-shared -Wl,-h,$(notdir $@),-z,combreloc,-z,defs,-z,ignore' if test -n "$USE_B_DIRECT"; then DSO_LDOPTS="$DSO_LDOPTS,-Bdirect" fi else DSO_CFLAGS=-KPIC DSO_LDOPTS='-G -h $(notdir $@) -z combreloc -z defs -z ignore' if test -n "$USE_B_DIRECT"; then DSO_LDOPTS="$DSO_LDOPTS -Bdirect" fi fi if test -n "$GNU_CC"; then CFLAGS="$CFLAGS -Wall" CXXFLAGS="$CXXFLAGS -Wall" if test -n "$USE_MDUPDATE"; then CFLAGS="$CFLAGS -MDupdate \$(DEPENDENCIES)" CXXFLAGS="$CXXFLAGS -MDupdate \$(DEPENDENCIES)" fi GCC_AS=`$CC -print-prog-name=as` if test "`echo | $GCC_AS -v 2>&1 | grep -c GNU`" != "0"; then GNU_AS=1 fi else CFLAGS="$CFLAGS -xstrconst" CXXFLAGS="$CXXFLAGS -Qoption cg -xstrconst -features=tmplife" if test -z "$MOZ_OPTIMIZE"; then CFLAGS="$CFLAGS -xs" CXXFLAGS="$CXXFLAGS -xs" fi _OPTIMIZE_FLAGS=-xO4 fi if test -z "$GNU_AS"; then ASFLAGS="$ASFLAGS -Wa,-P" fi if test -n "$USE_64"; then if test -n "$GNU_CC"; then CC="$CC -m64" CXX="$CXX -m64" else if test "$OS_TEST" = "i86pc"; then CC="$CC -xarch=amd64" CXX="$CXX -xarch=amd64" else CC="$CC -xarch=v9" CXX="$CXX -xarch=v9" fi fi fi if test "$OS_TEST" = "i86pc"; then if test -z "$USE_64"; then AC_DEFINE(i386) fi CPU_ARCH_TAG=_$OS_TEST # The default debug format, DWARF (-g), is not supported by gcc # on i386-ANY-sysv4/solaris, but the stabs format is. It is # assumed that the Solaris assembler /usr/ccs/bin/as is used. # If your gcc uses GNU as, you do not need the -Wa,-s option. if test -n "$MOZ_DEBUG" && test -n "$GNU_CC"; then _DEBUG_FLAGS=-gstabs if test -z "$GNU_AS"; then _DEBUG_FLAGS="$_DEBUG_FLAGS -Wa,-s" fi fi fi case "${target_os}" in solaris2.3*) AC_DEFINE(_PR_NO_LARGE_FILES) ;; solaris2.4*) AC_DEFINE(_PR_NO_LARGE_FILES) ;; solaris2.5*) AC_DEFINE(SOLARIS2_5) ;; *) AC_DEFINE(_PR_HAVE_OFF64_T) # The lfcompile64(5) man page on Solaris 2.6 says: # For applications that do not wish to conform to the POSIX or # X/Open specifications, the 64-bit transitional interfaces # are available by default. No compile-time flags need to be # set. # But gcc 2.7.2.x fails to define _LARGEFILE64_SOURCE by default. # The native compiler, gcc 2.8.x, and egcs don't have this problem. if test -n "$GNU_CC"; then AC_DEFINE(_LARGEFILE64_SOURCE) fi ;; esac case "${target_os}" in solaris2.3*) ;; solaris2.4*) ;; solaris2.5*) ;; solaris2.6*) ;; solaris2.7*) ;; *) # Solaris 8 or higher has IPv6. AC_DEFINE(_PR_INET6) ;; esac if test "$CPU_ARCH" = "sparc"; then # 64-bit Solaris SPARC requires V9 architecture, so the following # is not needed. if test -z "$USE_64"; then ULTRASPARC_LIBRARY=nspr_flt fi fi # Purify requires that binaries linked against nspr also # be linked against -lrt (or -lposix4) so add it to OS_LIBS _rev=`uname -r` _librt=`echo $_rev 5.6 | awk '{ if ($1 > $2) print "-lrt"; else print "-lposix4" }'` OS_LIBS="$OS_LIBS $_librt" ;; *-sco-sysv5*) AC_DEFINE(XP_UNIX) AC_DEFINE(UNIXWARE) AC_DEFINE(SVR4) AC_DEFINE(SYSV) USE_NSPR_THREADS=1 if echo $OS_RELEASE | grep -c 2.1 2>/dev/null; then AC_DEFINE(_PR_NO_LARGE_FILES) CC='$(NSDEPTH)/build/hcc cc' CXX='$(NSDEPTH)/build/hcpp CC' MDCPUCFG_H=_unixware.cfg else AC_DEFINE(_LARGEFILE64_SOURCE) AC_DEFINE(_PR_HAVE_OFF64_T) AC_DEFINE(_PR_HAVE_SOCKADDR_LEN) MDCPUCFG_H=_unixware7.cfg fi PR_MD_CSRCS=unixware.c DSO_LDOPTS=-G CPU_ARCH=x86 ;; *-symbian*) AC_ARG_WITH(symbian-sdk, [ --with-symbian-sdk=SYMBIAN_SDK_DIR The path to the Symbian SDK], SYMBIAN_SDK_DIR=$withval) echo ----------------------------------------------------------------------------- echo Building with Symbian SDK in: $SYMBIAN_SDK_DIR echo ----------------------------------------------------------------------------- AC_DEFINE(XP_UNIX) AC_DEFINE(SYMBIAN) AC_DEFINE(__arm__) AC_DEFINE(__SYMBIAN32__) AC_DEFINE(_UNICODE) AC_DEFINE(NDEBUG) AC_DEFINE(__SUPPORT_CPP_EXCEPTIONS__) AC_DEFINE(MOZ_STDERR_TO_STDOUT) AC_DEFINE(HAVE_FCNTL_FILE_LOCKING) AC_DEFINE(HAVE_SOCKLEN_T) USE_PTHREADS=1 LIB_SUFFIX=lib DLL_SUFFIX=dll MKSHLIB= DSO_LDOPTS= DSO_CFLAGS= VISIBILITY_FLAGS= MDCPUCFG_H=_symbian.cfg PR_MD_CSRCS=symbian.c NSINSTALL=nsinstall RANLIB='echo no ranlib ' CPU_ARCH=ARM OS_ARCH=SYMBIAN OS_EXE_CFLAGS="$OS_EXE_CFLAGS -D__EXE__" CFLAGS="$CFLAGS -MD -nostdinc" SYMBIAN_SYS_INCLUDE="-I$SYMBIAN_SDK_DIR/Epoc32/include/variant -I$SYMBIAN_SDK_DIR/Epoc32/include -I$SYMBIAN_SDK_DIR/Epoc32/include/stdapis" echo ------------------------------------------------------- echo SYMBIAN_SYS_INCLUDE is: $SYMBIAN_SYS_INCLUDE echo ------------------------------------------------------- case "$OS_TARGET" in WINSCW) CC=mwccsym2.exe CXX=mwccsym2.exe LD=mwldsym2.exe AR=mwldsym2.exe WINSCW_LD_DIR="\$(SYMBIAN_SDK_DIR)/EPOC32/RELEASE/WINSCW/UDEB" CFLAGS="$CFLAGS -O0 -inline off -wchar_t off -align 4 -warnings on -w nohidevirtual,nounusedexpr -msgstyle gcc -enum int -str pool -exc ms -trigraphs on -nostderr -gccdep -cwd source -i- -I\$(VPATH)" SYMBIAN_SYS_INCLUDE="$SYMBIAN_SYS_INCLUDE -include Symbian_OS_v9.2.hrh" AR_FLAGS="-library -msgstyle gcc -stdlib -subsystem windows -noimplib -o \$@" AC_DEFINE(_DEBUG) AC_DEFINE(__CW32__) AC_DEFINE(__WINS__) AC_DEFINE(__WINSCW__) DEFINES="$DEFINES -U_WIN32" ;; GCCE) CFLAGS="$CFLAGS -Wall -Wno-unknown-pragmas -fexceptions -march=armv5t -mapcs -pipe -x c -msoft-float" CXXFLAGS="$CXXFLAGS $CFLAGS -Wno-ctor-dtor-privacy" SYMBIAN_SYS_INCLUDE="$SYMBIAN_SYS_INCLUDE -include $SYMBIAN_SDK_DIR/EPOC32/INCLUDE/GCCE/GCCE.h" AC_DEFINE(__GCCE__) AC_DEFINE(__EABI__) DEFINES="$DEFINES -D__PRODUCT_INCLUDE__=$SYMBIAN_SDK_DIR/Epoc32/include/variant/Symbian_OS_v9.2.hrh" ;; *) AC_MSG_ERROR([Missing OS_TARGET for ${target}. Set --enable-symbian-target to with 'WINSCW' or 'GCCE'.]) ;; esac CFLAGS="$CFLAGS ${SYMBIAN_SYS_INCLUDE}" ;; *-os2*) AC_DEFINE(XP_OS2) AC_DEFINE(XP_PC) AC_DEFINE(BSD_SELECT) AC_DEFINE(TCPV40HDRS) LIB_SUFFIX=lib DLL_SUFFIX=dll RC=rc.exe PR_MD_ARCH_DIR=os2 PROG_SUFFIX=.exe NSINSTALL=nsinstall MDCPUCFG_H=_os2.cfg RESOLVE_LINK_SYMBOLS=1 AC_DEFINE(OS2) AR=emxomfar AR_FLAGS='r $@' CFLAGS="$CFLAGS -Wall -Zomf" CXXFLAGS="$CFLAGS -Wall -Zomf" MKSHLIB='$(CC) $(DSO_LDOPTS) -o $@' DSO_CFLAGS= DSO_LDOPTS='-Zomf -Zdll' LDFLAGS='-Zmap' _OPTIMIZE_FLAGS="-O2 -s" _DEBUG_FLAGS="-g -fno-inline" if test -n "$MOZ_OPTIMIZE"; then DSO_LDOPTS="$DSO_LDOPTS -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA" fi IMPLIB='emximp -o' FILTER='emxexp -o' if test -n "$MOZ_OS2_HIGH_MEMORY"; then LDFLAGS="$LDFLAGS -Zhigh-mem" AC_DEFINE(MOZ_OS2_HIGH_MEMORY) fi # GCC for OS/2 currently predefines these, but we don't want them DEFINES="$DEFINES -Uunix -U__unix -U__unix__" ;; *) AC_DEFINE(XP_UNIX) ;; esac if test -z "$SKIP_LIBRARY_CHECKS"; then dnl ======================================================== dnl Check for system libraries dnl ======================================================== dnl We don't want anything to link with libdl even if it's present on OS X, dnl since it's not used and not part of the default installation. dnl The same goes for BeOS. dnl OS/2 has dlfcn in libc. case $target in *-darwin*|*-beos*|*-os2*) ;; *) AC_CHECK_LIB(dl, dlopen, [AC_CHECK_HEADER(dlfcn.h, OS_LIBS="-ldl $OS_LIBS")]) ;; esac dnl ======================================================== dnl Check for system header files. dnl ======================================================== dnl ======================================================== dnl Check for typedefs and structs dnl ======================================================== dnl ======================================================== dnl Checks for library functions. dnl ======================================================== AC_PROG_GCC_TRADITIONAL _SAVE_LIBS="$LIBS" LIBS="$LIBS $OS_LIBS" AC_CHECK_FUNCS(dladdr gettid lchown setpriority strerror syscall) LIBS="$_SAVE_LIBS" dnl ======================================================== dnl Check options dnl ======================================================== dnl ====================================================== dnl = Enable compiling with ccache dnl ====================================================== AC_ARG_WITH(ccache, [ --with-ccache[=path/to/ccache] Enable compiling with ccache], CCACHE=$withval, CCACHE="no") if test "$CCACHE" != "no"; then if test -n "$CCACHE"; then if test "$CCACHE" = "yes"; then CCACHE= else if test ! -e "$CCACHE"; then AC_MSG_ERROR([$CCACHE not found]) fi fi fi AC_PATH_PROGS(CCACHE, $CCACHE ccache) if test -z "$CCACHE" -o "$CCACHE" = ":"; then AC_MSG_ERROR([ccache not found]) elif test -x "$CCACHE"; then CC="$CCACHE $CC" CXX="$CCACHE $CXX" else AC_MSG_ERROR([$CCACHE is not executable]) fi fi dnl ======================================================== dnl = dnl = --enable-strip dnl = dnl = Enable stripping of libs and executables dnl = dnl ======================================================== AC_ARG_ENABLE(strip, [ --enable-strip Enable stripping of shared libs and programs], [ if test "$enableval" = "yes"; then ENABLE_STRIP=1 fi ]) dnl Check for hpux options case "${target_os}" in hpux*) if test -z "$GNU_CC"; then AC_CACHE_CHECK(for +Olit support, ac_cv_hpux_usable_olit_option, dnl since aCC doesn't throw an error on invalid options, dnl we have to test this the hard way [ac_cv_hpux_usable_olit_option=no rm -f conftest* echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} ${CFLAGS} +Olit=all -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out`"; then ac_cv_hpux_usable_olit_option=yes fi fi rm -f conftest* ]) if test "$ac_cv_hpux_usable_olit_option" = "yes"; then CFLAGS="$CFLAGS +Olit=all" CXXFLAGS="$CXXFLAGS +Olit=all" else CFLAGS="$CFLAGS +ESlit" CXXFLAGS="$CXXFLAGS +ESlit" fi fi ;; esac case "$target_os" in darwin*) _HAVE_PTHREADS=1 ;; *) AC_CHECK_LIB(pthreads, pthread_create, _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads", AC_CHECK_LIB(pthread, pthread_create, _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread", AC_CHECK_LIB(c_r, pthread_create, _HAVE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r", AC_CHECK_LIB(c, pthread_create, _HAVE_PTHREADS=1 ) ) ) ) ;; esac AC_ARG_WITH(pthreads, [ --with-pthreads Use system pthreads library as thread subsystem], [ if test "$withval" = "yes"; then if test -n "$_HAVE_PTHREADS"; then USE_PTHREADS=1 USE_USER_PTHREADS= USE_NSPR_THREADS= else AC_MSG_ERROR([ --with-pthreads specified for a system without pthread support ]); fi else USE_PTHREADS= _PTHREAD_LDFLAGS= fi], [ if test -n "$_HAVE_PTHREADS" && test -z "$USE_USER_PTHREADS" && test -z "$USE_NSPR_THREADS"; then USE_PTHREADS=1 USE_USER_PTHREADS= USE_NSPR_THREADS= fi]) AC_ARG_ENABLE(user-pthreads, [ --enable-user-pthreads Build using userland pthreads], [ if test "$enableval" = "yes"; then if test -n "$_HAVE_PTHREADS"; then USE_PTHREADS= USE_USER_PTHREADS=1 USE_NSPR_THREADS= else AC_MSG_ERROR([ --enable-user-pthreads specified for a system without pthread support ]); fi fi]) AC_ARG_ENABLE(nspr-threads, [ --enable-nspr-threads Build using classic nspr threads], [ if test "$enableval" = "yes"; then USE_PTHREADS= USE_USER_PTHREADS= USE_NSPR_THREADS=1 fi]) case "$target" in *-beos*) AC_ARG_WITH(bthreads, [ --with-bthreads Use system bthreads library as thread subsystem (BeOS only)], [ if test "$withval" = "yes"; then USE_BTHREADS=1 USE_USER_PTHREADS= USE_PTHREADS= fi]) ;; esac fi # SKIP_LIBRARY_CHECKS AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Compile ipv6 support], [ if test "$enableval" = "yes"; then USE_IPV6=1 else USE_IPV6= fi]) if test -n "$USE_PTHREADS"; then dnl See if -pthread is supported. rm -f conftest* ac_cv_have_dash_pthread=no AC_MSG_CHECKING(whether ${CC-cc} accepts -pthread) echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthread -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthread`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthread=yes case "$target_os" in freebsd*) # Freebsd doesn't use -pthread for compiles, it uses them for linking ;; *) CFLAGS="$CFLAGS -pthread" CXXFLAGS="$CXXFLAGS -pthread" ;; esac fi fi rm -f conftest* AC_MSG_RESULT($ac_cv_have_dash_pthread) dnl dnl See if -pthreads is supported. dnl ac_cv_have_dash_pthreads=no if test "$ac_cv_have_dash_pthread" = "no"; then AC_MSG_CHECKING(whether ${CC-cc} accepts -pthreads) echo 'int main() { return 0; }' | cat > conftest.c ${CC-cc} -pthreads -o conftest conftest.c > conftest.out 2>&1 if test $? -eq 0; then if test -z "`egrep -i '(unrecognize|unknown)' conftest.out | grep pthreads`" && test -z "`egrep -i '(error|incorrect)' conftest.out`" ; then ac_cv_have_dash_pthreads=yes CFLAGS="$CFLAGS -pthreads" CXXFLAGS="$CXXFLAGS -pthreads" fi fi rm -f conftest* AC_MSG_RESULT($ac_cv_have_dash_pthreads) fi case "$target" in *-solaris*) if test "$ac_cv_have_dash_pthreads" = "yes"; then _PTHREAD_LDFLAGS= fi ;; *-freebsd*) AC_DEFINE(_REENTRANT) AC_DEFINE(_THREAD_SAFE) dnl -pthread links in -lc_r, so don't specify it explicitly. if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS="-pthread" else _PTHREAD_LDFLAGS="-lc_r" fi ;; *-netbsd*) if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS="-pthread" fi ;; *-bsdi*) AC_DEFINE(_THREAD_SAFE) dnl -pthread links in -lc_r, so don't specify it explicitly. if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS= fi ;; *-openbsd*) if test "$ac_cv_have_dash_pthread" = "yes"; then _PTHREAD_LDFLAGS=-pthread fi ;; *-linux*|*-gnu*|*-k*bsd*-gnu) AC_DEFINE(_REENTRANT) ;; esac else if test -n "$USE_USER_PTHREADS"; then USE_PTHREADS= USE_NSPR_THREADS= else _PTHREAD_LDFLAGS= fi fi dnl Special thread exceptions case "$target" in *-aix*) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi case "$target_os" in aix4.1*) if test -z "$USE_PTHREADS"; then AC_DEFINE(AIX_RENAME_SELECT) fi ;; aix4.2*) if test -z "$USE_NSPR_THREADS"; then AC_DEFINE(HAVE_POINTER_LOCALTIME_R) fi ;; aix4.3*) if test -z "$USE_NSPR_THREADS"; then AC_DEFINE(HAVE_POINTER_LOCALTIME_R) fi if test -n "$USE_PTHREADS"; then AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST) fi ;; *) if test -z "$USE_NSPR_THREADS"; then AC_DEFINE(HAVE_POINTER_LOCALTIME_R) fi if test -n "$USE_PTHREADS"; then AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST) fi ;; esac ;; *-bsdi*) if test -n "$USE_PTHREADS"; then AC_DEFINE(_PR_NEED_PTHREAD_INIT) fi ;; *-freebsd*) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi ;; *-hpux*) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi if test "$USE_PTHREADS"; then if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then AC_DEFINE(_REENTRANT) AC_DEFINE(_PR_DCETHREADS) else AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L) AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST) fi fi if test "$USE_USER_PTHREADS"; then AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L) fi ;; *-irix*) if test "${target_os}" = "irix6.5"; then if test -n "$USE_PTHREADS"; then AC_DEFINE(_PR_HAVE_GETHOST_R) AC_DEFINE(_PR_HAVE_GETHOST_R_POINTER) fi fi ;; *-linux*|*-gnu*|*-k*bsd*-gnu) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi ;; *-mingw*|*-msys*|*-cygwin*|*-mks*|*-os2*|*-beos*) dnl win32, os2 & beos cannot use pthreads USE_PTHREADS= _PTHREAD_LDFLAGS= USE_USER_PTHREADS= ;; *-netbsd*|*-openbsd*) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi ;; *-osf*) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi if test -n "$USE_PTHREADS"; then if echo $OS_RELEASE | egrep -c '(V2.0|V3.2)' 2>/dev/null; then : else AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST) fi fi ;; *-solaris*) if test -n "$USE_NSPR_THREADS"; then AC_DEFINE(_PR_LOCAL_THREADS_ONLY) fi if test -n "$USE_PTHREADS"; then AC_DEFINE(_REENTRANT) AC_DEFINE(HAVE_POINTER_LOCALTIME_R) if test "$OS_TEST" = "i86pc"; then if test -n "$USE_64"; then PR_MD_ASFILES=os_SunOS_x86_64.s else PR_MD_ASFILES=os_SunOS_x86.s fi else if test -n "$USE_64"; then PR_MD_ASFILES=os_SunOS_sparcv9.s fi fi fi ;; *-nto*) if test -n "$USE_PTHREADS"; then AC_DEFINE(_PR_HAVE_GETHOST_R) AC_DEFINE(_PR_HAVE_GETHOST_R_POINTER) fi ;; esac OS_LIBS="$_PTHREAD_LDFLAGS $OS_LIBS" dnl If the user passed in arg to --enable-optimize or --enable-debug, dnl make sure that we use it. if test -n "$_SAVE_OPTIMIZE_FLAGS"; then _OPTIMIZE_FLAGS="$_SAVE_OPTIMIZE_FLAGS" fi if test -n "$_SAVE_DEBUG_FLAGS"; then _DEBUG_FLAGS="$_SAVE_DEBUG_FLAGS" fi if test -n "$MOZ_OPTIMIZE"; then CFLAGS="$CFLAGS $_OPTIMIZE_FLAGS" CXXFLAGS="$CXXFLAGS $_OPTIMIZE_FLAGS" fi if test -n "$MOZ_DEBUG_SYMBOLS"; then CFLAGS="$CFLAGS $_DEBUG_FLAGS" CXXFLAGS="$CXXFLAGS $_DEBUG_FLAGS" fi if test -n "$MOZ_OPTIMIZE"; then OBJDIR_TAG=_OPT else OBJDIR_TAG=_DBG fi if test -n "$USE_64"; then COMPILER_TAG=_64 fi RELEASE_OBJDIR_NAME="${OS_CONFIG}${CPU_ARCH_TAG}${COMPILER_TAG}${IMPL_STRATEGY}${OBJDIR_TAG}.${OBJDIR_SUFFIX}" dnl ======================================================== dnl Use cygwin wrapper for win32 builds, except MSYS/MinGW dnl ======================================================== case "$target_os" in cygwin*|mks*) CC="\$(CYGWIN_WRAPPER) $CC" CXX="\$(CYGWIN_WRAPPER) $CXX" RC="\$(CYGWIN_WRAPPER) $RC" ;; esac dnl ======================================================== dnl = Use malloc wrapper lib dnl ======================================================== AC_ARG_ENABLE(wrap-malloc, [ --enable-wrap-malloc Wrap malloc calls (gnu linker only)], [ if test "$enableval" = "yes"; then _WRAP_MALLOC=1 fi ]) if test -n "$_WRAP_MALLOC"; then if test -n "$GNU_CC"; then WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign" WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete" WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup" WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size" else AC_MSG_ERROR([--enable-wrap-malloc is not supported for non-GNU toolchains]) fi fi dnl ======================================================== dnl = Location of malloc wrapper lib dnl ======================================================== AC_ARG_WITH(wrap-malloc, [ --with-wrap-malloc=SHAREDLIB Location of malloc wrapper library], WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval") dnl ======================================================== dnl Substitution of found variables. dnl ======================================================== AC_SUBST(SHELL_OVERRIDE) AC_SUBST(MOZILLA_CLIENT) AC_SUBST(CC) AC_SUBST(CXX) AC_SUBST(CFLAGS) AC_SUBST(CXXFLAGS) AC_SUBST(CPPFLAGS) AC_SUBST(HOST_CC) AC_SUBST(HOST_CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST(HOST_LDFLAGS) AC_SUBST(GNU_CC) AC_SUBST(GCC_USE_GNU_LD) AC_SUBST(MSC_VER) AC_SUBST(CROSS_COMPILE) AC_SUBST(MOZ_OPTIMIZE) AC_SUBST(MOZ_DEBUG) AC_SUBST(MOZ_DEBUG_SYMBOLS) AC_SUBST(USE_CPLUS) AC_SUBST(USE_IPV6) AC_SUBST(USE_N32) AC_SUBST(USE_X32) AC_SUBST(USE_64) AC_SUBST(OBJECT_MODE) AC_SUBST(ENABLE_STRIP) AC_SUBST(USE_PTHREADS) AC_SUBST(USE_BTHREADS) AC_SUBST(USE_USER_PTHREADS) AC_SUBST(USE_NSPR_THREADS) AC_SUBST(LIBNSPR) AC_SUBST(LIBPLC) AC_SUBST(MOD_MAJOR_VERSION) AC_SUBST(MOD_MINOR_VERSION) AC_SUBST(MOD_PATCH_VERSION) AC_SUBST(NSPR_MODNAME) AC_SUBST(MDCPUCFG_H) AC_SUBST(PR_MD_CSRCS) AC_SUBST(PR_MD_ASFILES) AC_SUBST(PR_MD_ARCH_DIR) AC_SUBST(CPU_ARCH) AC_SUBST(OBJ_SUFFIX) AC_SUBST(LIB_SUFFIX) AC_SUBST(DLL_SUFFIX) AC_SUBST(ASM_SUFFIX) AC_SUBST(WRAP_LDFLAGS) AC_SUBST(MKSHLIB) AC_SUBST(DSO_CFLAGS) AC_SUBST(DSO_LDOPTS) AC_SUBST(OS_TARGET) AC_SUBST(OS_ARCH) AC_SUBST(OS_RELEASE) AC_SUBST(OS_TEST) AC_SUBST(MACOSX_DEPLOYMENT_TARGET) AC_SUBST(DEFINES) AC_SUBST(DEFS) AC_SUBST(AR) AC_SUBST(AR_FLAGS) AC_SUBST(AS) AC_SUBST(ASFLAGS) AC_SUBST(LD) AC_SUBST(RANLIB) AC_SUBST(PERL) AC_SUBST(STRIP) AC_SUBST(FILTER) AC_SUBST(IMPLIB) AC_SUBST(PROFILE_GEN_CFLAGS) AC_SUBST(PROFILE_GEN_LDFLAGS) AC_SUBST(PROFILE_USE_CFLAGS) AC_SUBST(PROFILE_USE_LDFLAGS) AC_SUBST(OS_LIBS) AC_SUBST(RESOLVE_LINK_SYMBOLS) AC_SUBST(AIX_LINK_OPTS) AC_SUBST(NOSUCHFILE) AC_SUBST(MOZ_OBJFORMAT) AC_SUBST(ULTRASPARC_LIBRARY) AC_SUBST(OBJDIR) AC_SUBST(OBJDIR_NAME) AC_SUBST(RELEASE_OBJDIR_NAME) AC_SUBST(NSINSTALL) AC_SUBST(OPTIMIZER) AC_SUBST(RC) AC_SUBST(RCFLAGS) AC_SUBST(DLLFLAGS) AC_SUBST(EXEFLAGS) AC_SUBST(OS_DLLFLAGS) AC_SUBST(CYGWIN_WRAPPER) AC_SUBST(VISIBILITY_FLAGS) AC_SUBST(WRAP_SYSTEM_INCLUDES) AC_SUBST(MACOS_SDK_DIR) AC_SUBST(SYMBIAN_SDK_DIR) AC_SUBST(NEXT_ROOT) AC_SUBST(MT) dnl ======================================================== dnl Generate output files. dnl ======================================================== MAKEFILES=" Makefile config/Makefile config/autoconf.mk config/nsprincl.mk config/nsprincl.sh config/nspr-config config/nspr.pc lib/Makefile lib/ds/Makefile lib/libc/Makefile lib/libc/include/Makefile lib/libc/src/Makefile lib/tests/Makefile pkg/Makefile pr/Makefile pr/include/Makefile pr/include/md/Makefile pr/include/obsolete/Makefile pr/include/private/Makefile pr/src/Makefile pr/src/io/Makefile pr/src/linking/Makefile pr/src/malloc/Makefile pr/src/md/Makefile pr/src/md/${PR_MD_ARCH_DIR}/Makefile pr/src/memory/Makefile pr/src/misc/Makefile pr/src/threads/Makefile pr/tests/Makefile pr/tests/dll/Makefile " if test "$OS_TARGET" = "Linux"; then MAKEFILES="$MAKEFILES pkg/linux/Makefile " elif test "$OS_TARGET" = "SunOS"; then MAKEFILES="$MAKEFILES pkg/solaris/Makefile pkg/solaris/SUNWpr/Makefile pkg/solaris/SUNWprd/Makefile " fi if test -z "$USE_PTHREADS" && test -z "$USE_BTHREADS"; then MAKEFILES="$MAKEFILES pr/src/threads/combined/Makefile " elif test -n "$USE_PTHREADS"; then MAKEFILES="$MAKEFILES pr/src/pthreads/Makefile " elif test -n "$USE_BTHREADS"; then MAKEFILES="$MAKEFILES pr/src/bthreads/Makefile " fi if test -n "$USE_CPLUS"; then MAKEFILES="$MAKEFILES pr/src/cplus/Makefile pr/src/cplus/tests/Makefile " fi echo $MAKEFILES > unallmakefiles AC_CONFIG_FILES([$MAKEFILES]) AC_CONFIG_COMMANDS([default], [chmod +x config/nspr-config]) AC_OUTPUT nspr-4.11/nspr/lib/.cvsignore0000644000000000000000000000001112623070344014270 0ustar 00000000000000Makefile nspr-4.11/nspr/lib/Makefile.in0000644000000000000000000000071712623070344014352 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = .. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk export NSPR20=1 include $(topsrcdir)/config/config.mk DIRS = ds libc include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/lib/ds/.cvsignore0000644000000000000000000000002312623070344014701 0ustar 00000000000000Makefile _pl_bld.h nspr-4.11/nspr/lib/ds/Makefile.in0000644000000000000000000000613712623070344014762 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include CSRCS = \ plarena.c \ plhash.c \ plvrsion.c \ $(NULL) HEADERS = \ plarenas.h \ plarena.h \ plhash.h \ $(NULL) HEADERS := $(addprefix $(srcdir)/, $(HEADERS)) ifeq ($(OS_ARCH), WINNT) RES=$(OBJDIR)/plds.res RESNAME=plds.rc endif # WINNT ifeq ($(OS_ARCH), AIX) ifeq ($(CLASSIC_NSPR),1) OS_LIBS = -lc else OS_LIBS = -lc_r endif endif ifeq ($(OS_ARCH),IRIX) OS_LIBS = -lc endif ifeq ($(OS_ARCH),SunOS) OS_LIBS = -lc MAPFILE = $(OBJDIR)/pldsmap.sun GARBAGE += $(MAPFILE) ifdef NS_USE_GCC ifdef GCC_USE_GNU_LD MKSHLIB += -Wl,--version-script,$(MAPFILE) else MKSHLIB += -Wl,-M,$(MAPFILE) endif else MKSHLIB += -M $(MAPFILE) endif # The -R '$ORIGIN' linker option instructs this library to search for its # dependencies in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' endif ifeq ($(OS_ARCH),OS2) MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def GARBAGE += $(MAPFILE) MKSHLIB += $(MAPFILE) endif EXTRA_LIBS = $(LIBNSPR) # On SCOOS, we can't link with extra libraries when # we build a shared library. If we do so, the linker doesn't # complain, but we would run into weird problems at run-time. # Therefore on these platforms, we link just the .o files. ifeq ($(OS_ARCH),SCOOS) EXTRA_LIBS = endif ifdef RESOLVE_LINK_SYMBOLS EXTRA_LIBS += $(OS_LIBS) endif LIBRARY_NAME = plds LIBRARY_VERSION = $(MOD_MAJOR_VERSION) RELEASE_HEADERS = $(HEADERS) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR) RELEASE_LIBS = $(TARGETS) include $(topsrcdir)/config/rules.mk # # Version information generation (begin) # ECHO = echo TINC = $(OBJDIR)/_pl_bld.h PROD = $(notdir $(SHARED_LIBRARY)) NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now SH_DATE = $(shell date "+%Y-%m-%d %T") SH_NOW = $(shell $(NOW)) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) SUF = i64 else SUF = LL endif GARBAGE += $(TINC) $(TINC): @$(MAKE_OBJDIR) @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC) @if test ! -z "$(SH_NOW)"; then \ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \ else \ true; \ fi @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC) $(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $< else $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< endif # # Version information generation (end) # # # The Client build wants the shared libraries in $(dist_bindir), # so we also install them there. # export:: $(TARGETS) $(INSTALL) -m 444 $(HEADERS) $(dist_includedir) $(INSTALL) -m 444 $(TARGETS) $(dist_libdir) ifdef SHARED_LIBRARY ifeq ($(OS_ARCH),HP-UX) $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir) $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir) else $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir) endif endif nspr-4.11/nspr/lib/ds/plarena.c0000644000000000000000000003175512623070344014507 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Lifetime-based fast allocation, inspired by much prior art, including * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). */ #include #include #include "plarena.h" #include "prmem.h" #include "prbit.h" #include "prlog.h" #include "prlock.h" #include "prinit.h" static PLArena *arena_freelist; #ifdef PL_ARENAMETER static PLArenaStats *arena_stats_list; #define COUNT(pool,what) (pool)->stats.what++ #else #define COUNT(pool,what) /* nothing */ #endif #define PL_ARENA_DEFAULT_ALIGN sizeof(double) static PRLock *arenaLock; static PRCallOnceType once; static const PRCallOnceType pristineCallOnce; /* ** InitializeArenas() -- Initialize arena operations. ** ** InitializeArenas() is called exactly once and only once from ** LockArena(). This function creates the arena protection ** lock: arenaLock. ** ** Note: If the arenaLock cannot be created, InitializeArenas() ** fails quietly, returning only PR_FAILURE. This percolates up ** to the application using the Arena API. He gets no arena ** from PL_ArenaAllocate(). It's up to him to fail gracefully ** or recover. ** */ static PRStatus InitializeArenas( void ) { PR_ASSERT( arenaLock == NULL ); arenaLock = PR_NewLock(); if ( arenaLock == NULL ) return PR_FAILURE; else return PR_SUCCESS; } /* end ArenaInitialize() */ static PRStatus LockArena( void ) { PRStatus rc = PR_CallOnce( &once, InitializeArenas ); if ( PR_FAILURE != rc ) PR_Lock( arenaLock ); return(rc); } /* end LockArena() */ static void UnlockArena( void ) { PR_Unlock( arenaLock ); return; } /* end UnlockArena() */ PR_IMPLEMENT(void) PL_InitArenaPool( PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align) { /* * Look-up table of PR_BITMASK(PR_CeilingLog2(align)) values for * align = 1 to 32. */ static const PRUint8 pmasks[33] = { 0, /* not used */ 0, 1, 3, 3, 7, 7, 7, 7,15,15,15,15,15,15,15,15, /* 1 ... 16 */ 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31}; /* 17 ... 32 */ if (align == 0) align = PL_ARENA_DEFAULT_ALIGN; if (align < sizeof(pmasks)/sizeof(pmasks[0])) pool->mask = pmasks[align]; else pool->mask = PR_BITMASK(PR_CeilingLog2(align)); pool->first.next = NULL; /* Set all three addresses in pool->first to the same dummy value. * These addresses are only compared with each other, but never * dereferenced. */ pool->first.base = pool->first.avail = pool->first.limit = (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; /* * Compute the net size so that each arena's gross size is |size|. * sizeof(PLArena) + pool->mask is the header and alignment slop * that PL_ArenaAllocate adds to the net size. */ if (size > sizeof(PLArena) + pool->mask) pool->arenasize = size - (sizeof(PLArena) + pool->mask); else pool->arenasize = size; #ifdef PL_ARENAMETER memset(&pool->stats, 0, sizeof pool->stats); pool->stats.name = strdup(name); pool->stats.next = arena_stats_list; arena_stats_list = &pool->stats; #endif } /* ** PL_ArenaAllocate() -- allocate space from an arena pool ** ** Description: PL_ArenaAllocate() allocates space from an arena ** pool. ** ** First, try to satisfy the request from arenas starting at ** pool->current. ** ** If there is not enough space in the arena pool->current, try ** to claim an arena, on a first fit basis, from the global ** freelist (arena_freelist). ** ** If no arena in arena_freelist is suitable, then try to ** allocate a new arena from the heap. ** ** Returns: pointer to allocated space or NULL ** ** Notes: The original implementation had some difficult to ** solve bugs; the code was difficult to read. Sometimes it's ** just easier to rewrite it. I did that. larryh. ** ** See also: bugzilla: 45343. ** */ PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb) { PLArena *a; char *rp; /* returned pointer */ PRUint32 nbOld; PR_ASSERT((nb & pool->mask) == 0); nbOld = nb; nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */ if (nb < nbOld) return NULL; /* attempt to allocate from arenas at pool->current */ { a = pool->current; do { if ( nb <= a->limit - a->avail ) { pool->current = a; rp = (char *)a->avail; a->avail += nb; return rp; } } while( NULL != (a = a->next) ); } /* attempt to allocate from arena_freelist */ { PLArena *p; /* previous pointer, for unlinking from freelist */ /* lock the arena_freelist. Make access to the freelist MT-Safe */ if ( PR_FAILURE == LockArena()) return(0); for ( a = arena_freelist, p = NULL; a != NULL ; p = a, a = a->next ) { if ( nb <= a->limit - a->base ) { if ( p == NULL ) arena_freelist = a->next; else p->next = a->next; UnlockArena(); a->avail = a->base; rp = (char *)a->avail; a->avail += nb; /* the newly allocated arena is linked after pool->current * and becomes pool->current */ a->next = pool->current->next; pool->current->next = a; pool->current = a; if ( NULL == pool->first.next ) pool->first.next = a; return(rp); } } UnlockArena(); } /* attempt to allocate from the heap */ { PRUint32 sz = PR_MAX(pool->arenasize, nb); if (PR_UINT32_MAX - sz < sizeof *a + pool->mask) { a = NULL; } else { sz += sizeof *a + pool->mask; /* header and alignment slop */ a = (PLArena*)PR_MALLOC(sz); } if ( NULL != a ) { a->limit = (PRUword)a + sz; a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail); rp = (char *)a->avail; a->avail += nb; PR_ASSERT(a->avail <= a->limit); /* the newly allocated arena is linked after pool->current * and becomes pool->current */ a->next = pool->current->next; pool->current->next = a; pool->current = a; if ( NULL == pool->first.next ) pool->first.next = a; PL_COUNT_ARENA(pool,++); COUNT(pool, nmallocs); return(rp); } } /* we got to here, and there's no memory to allocate */ return(NULL); } /* --- end PL_ArenaAllocate() --- */ PR_IMPLEMENT(void *) PL_ArenaGrow( PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr) { void *newp; if (PR_UINT32_MAX - size < incr) return NULL; PL_ARENA_ALLOCATE(newp, pool, size + incr); if (newp) memcpy(newp, p, size); return newp; } static void ClearArenaList(PLArena *a, PRInt32 pattern) { for (; a; a = a->next) { PR_ASSERT(a->base <= a->avail && a->avail <= a->limit); a->avail = a->base; PL_CLEAR_UNUSED_PATTERN(a, pattern); PL_MAKE_MEM_NOACCESS((void*)a->avail, a->limit - a->avail); } } PR_IMPLEMENT(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern) { ClearArenaList(pool->first.next, pattern); } /* * Free tail arenas linked after head, which may not be the true list head. * Reset pool->current to point to head in case it pointed at a tail arena. */ static void FreeArenaList(PLArenaPool *pool, PLArena *head, PRBool reallyFree) { PLArena **ap, *a; ap = &head->next; a = *ap; if (!a) return; #ifdef DEBUG ClearArenaList(a, PL_FREE_PATTERN); #endif if (reallyFree) { do { *ap = a->next; PL_CLEAR_ARENA(a); PL_COUNT_ARENA(pool,--); PR_DELETE(a); } while ((a = *ap) != 0); } else { /* Insert the whole arena chain at the front of the freelist. */ do { PL_MAKE_MEM_NOACCESS((void*)(*ap)->base, (*ap)->limit - (*ap)->base); ap = &(*ap)->next; } while (*ap); LockArena(); *ap = arena_freelist; arena_freelist = a; head->next = 0; UnlockArena(); } pool->current = head; } PR_IMPLEMENT(void) PL_ArenaRelease(PLArenaPool *pool, char *mark) { PLArena *a; for (a = &pool->first; a; a = a->next) { if (PR_UPTRDIFF(mark, a->base) <= PR_UPTRDIFF(a->avail, a->base)) { a->avail = (PRUword)PL_ARENA_ALIGN(pool, mark); FreeArenaList(pool, a, PR_FALSE); return; } } } PR_IMPLEMENT(void) PL_FreeArenaPool(PLArenaPool *pool) { FreeArenaList(pool, &pool->first, PR_FALSE); COUNT(pool, ndeallocs); } PR_IMPLEMENT(void) PL_FinishArenaPool(PLArenaPool *pool) { FreeArenaList(pool, &pool->first, PR_TRUE); #ifdef PL_ARENAMETER { PLArenaStats *stats, **statsp; if (pool->stats.name) PR_DELETE(pool->stats.name); for (statsp = &arena_stats_list; (stats = *statsp) != 0; statsp = &stats->next) { if (stats == &pool->stats) { *statsp = stats->next; return; } } } #endif } PR_IMPLEMENT(void) PL_CompactArenaPool(PLArenaPool *ap) { } PR_IMPLEMENT(void) PL_ArenaFinish(void) { PLArena *a, *next; for (a = arena_freelist; a; a = next) { next = a->next; PR_DELETE(a); } arena_freelist = NULL; if (arenaLock) { PR_DestroyLock(arenaLock); arenaLock = NULL; } once = pristineCallOnce; } PR_IMPLEMENT(size_t) PL_SizeOfArenaPoolExcludingPool( const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf) { /* * The first PLArena is within |pool|, so don't measure it. Subsequent * PLArenas are separate and must be measured. */ size_t size = 0; const PLArena *arena = pool->first.next; while (arena) { size += mallocSizeOf(arena); arena = arena->next; } return size; } #ifdef PL_ARENAMETER PR_IMPLEMENT(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb) { pool->stats.nallocs++; pool->stats.nbytes += nb; if (nb > pool->stats.maxalloc) pool->stats.maxalloc = nb; pool->stats.variance += nb * nb; } PR_IMPLEMENT(void) PL_ArenaCountInplaceGrowth( PLArenaPool *pool, PRUint32 size, PRUint32 incr) { pool->stats.ninplace++; } PR_IMPLEMENT(void) PL_ArenaCountGrowth( PLArenaPool *pool, PRUint32 size, PRUint32 incr) { pool->stats.ngrows++; pool->stats.nbytes += incr; pool->stats.variance -= size * size; size += incr; if (size > pool->stats.maxalloc) pool->stats.maxalloc = size; pool->stats.variance += size * size; } PR_IMPLEMENT(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark) { pool->stats.nreleases++; } PR_IMPLEMENT(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark) { pool->stats.nfastrels++; } #include #include PR_IMPLEMENT(void) PL_DumpArenaStats(FILE *fp) { PLArenaStats *stats; double mean, variance; for (stats = arena_stats_list; stats; stats = stats->next) { if (stats->nallocs != 0) { mean = (double)stats->nbytes / stats->nallocs; variance = fabs(stats->variance / stats->nallocs - mean * mean); } else { mean = variance = 0; } fprintf(fp, "\n%s allocation statistics:\n", stats->name); fprintf(fp, " number of arenas: %u\n", stats->narenas); fprintf(fp, " number of allocations: %u\n", stats->nallocs); fprintf(fp, " number of free arena reclaims: %u\n", stats->nreclaims); fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs); fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs); fprintf(fp, " number of allocation growths: %u\n", stats->ngrows); fprintf(fp, " number of in-place growths: %u\n", stats->ninplace); fprintf(fp, "number of released allocations: %u\n", stats->nreleases); fprintf(fp, " number of fast releases: %u\n", stats->nfastrels); fprintf(fp, " total bytes allocated: %u\n", stats->nbytes); fprintf(fp, " mean allocation size: %g\n", mean); fprintf(fp, " standard deviation: %g\n", sqrt(variance)); fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc); } } #endif /* PL_ARENAMETER */ nspr-4.11/nspr/lib/ds/plarena.h0000644000000000000000000002174012623070344014505 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef plarena_h___ #define plarena_h___ /* * Lifetime-based fast allocation, inspired by much prior art, including * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes" * David R. Hanson, Software -- Practice and Experience, Vol. 20(1). * * Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE). */ #include "prtypes.h" #include "plarenas.h" PR_BEGIN_EXTERN_C typedef struct PLArena PLArena; struct PLArena { PLArena *next; /* next arena for this lifetime */ PRUword base; /* aligned base address, follows this header */ PRUword limit; /* one beyond last byte in arena */ PRUword avail; /* points to next available byte */ }; #ifdef PL_ARENAMETER typedef struct PLArenaStats PLArenaStats; struct PLArenaStats { PLArenaStats *next; /* next in arenaStats list */ char *name; /* name for debugging */ PRUint32 narenas; /* number of arenas in pool */ PRUint32 nallocs; /* number of PL_ARENA_ALLOCATE() calls */ PRUint32 nreclaims; /* number of reclaims from freeArenas */ PRUint32 nmallocs; /* number of malloc() calls */ PRUint32 ndeallocs; /* number of lifetime deallocations */ PRUint32 ngrows; /* number of PL_ARENA_GROW() calls */ PRUint32 ninplace; /* number of in-place growths */ PRUint32 nreleases; /* number of PL_ARENA_RELEASE() calls */ PRUint32 nfastrels; /* number of "fast path" releases */ PRUint32 nbytes; /* total bytes allocated */ PRUint32 maxalloc; /* maximum allocation size in bytes */ PRFloat64 variance; /* size variance accumulator */ }; #endif struct PLArenaPool { PLArena first; /* first arena in pool list */ PLArena *current; /* arena from which to allocate space */ PRUint32 arenasize; /* net exact size of a new arena */ PRUword mask; /* alignment mask (power-of-2 - 1) */ #ifdef PL_ARENAMETER PLArenaStats stats; #endif }; /* * WARNING: The PL_MAKE_MEM_ macros are for internal use by NSPR. Do NOT use * them in your code. * * NOTE: Valgrind support to be added. * * The PL_MAKE_MEM_ macros are modeled after the MOZ_MAKE_MEM_ macros in * Mozilla's mfbt/MemoryChecking.h. Only AddressSanitizer is supported now. * * Provides a common interface to the ASan (AddressSanitizer) and Valgrind * functions used to mark memory in certain ways. In detail, the following * three macros are provided: * * PL_MAKE_MEM_NOACCESS - Mark memory as unsafe to access (e.g. freed) * PL_MAKE_MEM_UNDEFINED - Mark memory as accessible, with content undefined * PL_MAKE_MEM_DEFINED - Mark memory as accessible, with content defined * * With Valgrind in use, these directly map to the three respective Valgrind * macros. With ASan in use, the NOACCESS macro maps to poisoning the memory, * while the UNDEFINED/DEFINED macros unpoison memory. * * With no memory checker available, all macros expand to the empty statement. */ /* WARNING: PL_SANITIZE_ADDRESS is for internal use by this header. Do NOT * define or test this macro in your code. */ #if defined(__has_feature) #if __has_feature(address_sanitizer) #define PL_SANITIZE_ADDRESS 1 #endif #elif defined(__SANITIZE_ADDRESS__) #define PL_SANITIZE_ADDRESS 1 #endif #if defined(PL_SANITIZE_ADDRESS) /* These definitions are usually provided through the * sanitizer/asan_interface.h header installed by ASan. * See https://code.google.com/p/address-sanitizer/wiki/ManualPoisoning */ void __asan_poison_memory_region(void const volatile *addr, size_t size); void __asan_unpoison_memory_region(void const volatile *addr, size_t size); #define PL_MAKE_MEM_NOACCESS(addr, size) \ __asan_poison_memory_region((addr), (size)) #define PL_MAKE_MEM_UNDEFINED(addr, size) \ __asan_unpoison_memory_region((addr), (size)) #define PL_MAKE_MEM_DEFINED(addr, size) \ __asan_unpoison_memory_region((addr), (size)) #else #define PL_MAKE_MEM_NOACCESS(addr, size) #define PL_MAKE_MEM_UNDEFINED(addr, size) #define PL_MAKE_MEM_DEFINED(addr, size) #endif /* * If the including .c file uses only one power-of-2 alignment, it may define * PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions * per ALLOCATE and GROW. */ #ifdef PL_ARENA_CONST_ALIGN_MASK #define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \ & ~PL_ARENA_CONST_ALIGN_MASK) #define PL_INIT_ARENA_POOL(pool, name, size) \ PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1) #else #define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask) #endif #define PL_ARENA_ALLOCATE(p, pool, nb) \ PR_BEGIN_MACRO \ PLArena *_a = (pool)->current; \ PRUint32 _nb = PL_ARENA_ALIGN(pool, (PRUint32)nb); \ PRUword _p = _a->avail; \ if (_nb < (PRUint32)nb) { \ _p = 0; \ } else if (_nb > (_a->limit - _a->avail)) { \ _p = (PRUword)PL_ArenaAllocate(pool, _nb); \ } else { \ _a->avail += _nb; \ } \ p = (void *)_p; \ if (p) { \ PL_MAKE_MEM_UNDEFINED(p, (PRUint32)nb); \ PL_ArenaCountAllocation(pool, (PRUint32)nb); \ } \ PR_END_MACRO #define PL_ARENA_GROW(p, pool, size, incr) \ PR_BEGIN_MACRO \ PLArena *_a = (pool)->current; \ PRUint32 _incr = PL_ARENA_ALIGN(pool, (PRUint32)incr); \ if (_incr < (PRUint32)incr) { \ p = NULL; \ } else if (_a->avail == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \ _incr <= (_a->limit - _a->avail)) { \ PL_MAKE_MEM_UNDEFINED((unsigned char *)(p) + size, (PRUint32)incr); \ _a->avail += _incr; \ PL_ArenaCountInplaceGrowth(pool, size, (PRUint32)incr); \ } else { \ p = PL_ArenaGrow(pool, p, size, (PRUint32)incr); \ } \ if (p) {\ PL_ArenaCountGrowth(pool, size, (PRUint32)incr); \ } \ PR_END_MACRO #define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail) #define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q)) #define PL_CLEAR_UNUSED_PATTERN(a, pattern) \ PR_BEGIN_MACRO \ PR_ASSERT((a)->avail <= (a)->limit); \ PL_MAKE_MEM_UNDEFINED((void*)(a)->avail, (a)->limit - (a)->avail); \ memset((void*)(a)->avail, (pattern), (a)->limit - (a)->avail); \ PR_END_MACRO #ifdef DEBUG #define PL_FREE_PATTERN 0xDA #define PL_CLEAR_UNUSED(a) PL_CLEAR_UNUSED_PATTERN((a), PL_FREE_PATTERN) #define PL_CLEAR_ARENA(a) \ PR_BEGIN_MACRO \ PL_MAKE_MEM_UNDEFINED((void*)(a), (a)->limit - (PRUword)(a)); \ memset((void*)(a), PL_FREE_PATTERN, (a)->limit - (PRUword)(a)); \ PR_END_MACRO #else #define PL_CLEAR_UNUSED(a) #define PL_CLEAR_ARENA(a) #endif #define PL_ARENA_RELEASE(pool, mark) \ PR_BEGIN_MACRO \ char *_m = (char *)(mark); \ PLArena *_a = (pool)->current; \ if (PR_UPTRDIFF(_m, _a->base) <= PR_UPTRDIFF(_a->avail, _a->base)) { \ _a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \ PL_CLEAR_UNUSED(_a); \ PL_MAKE_MEM_NOACCESS((void*)_a->avail, _a->limit - _a->avail); \ PL_ArenaCountRetract(pool, _m); \ } else { \ PL_ArenaRelease(pool, _m); \ } \ PL_ArenaCountRelease(pool, _m); \ PR_END_MACRO #ifdef PL_ARENAMETER #define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op) #else #define PL_COUNT_ARENA(pool,op) #endif #define PL_ARENA_DESTROY(pool, a, pnext) \ PR_BEGIN_MACRO \ PL_COUNT_ARENA(pool,--); \ if ((pool)->current == (a)) (pool)->current = &(pool)->first; \ *(pnext) = (a)->next; \ PL_CLEAR_ARENA(a); \ free(a); \ (a) = 0; \ PR_END_MACRO #ifdef PL_ARENAMETER #include PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb); PR_EXTERN(void) PL_ArenaCountInplaceGrowth( PLArenaPool *pool, PRUint32 size, PRUint32 incr); PR_EXTERN(void) PL_ArenaCountGrowth( PLArenaPool *pool, PRUint32 size, PRUint32 incr); PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark); PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark); PR_EXTERN(void) PL_DumpArenaStats(FILE *fp); #else /* !PL_ARENAMETER */ #define PL_ArenaCountAllocation(ap, nb) /* nothing */ #define PL_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */ #define PL_ArenaCountGrowth(ap, size, incr) /* nothing */ #define PL_ArenaCountRelease(ap, mark) /* nothing */ #define PL_ArenaCountRetract(ap, mark) /* nothing */ #endif /* !PL_ARENAMETER */ PR_END_EXTERN_C #endif /* plarena_h___ */ nspr-4.11/nspr/lib/ds/plarenas.h0000644000000000000000000000462512623070344014673 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef PLARENAS_H #define PLARENAS_H PR_BEGIN_EXTERN_C typedef struct PLArenaPool PLArenaPool; /* ** Initialize an arena pool with the given name for debugging and metering, ** with a minimum gross size per arena of size bytes. The net size per arena ** is smaller than the gross size by a header of four pointers plus any ** necessary padding for alignment. ** ** Note: choose a gross size that's a power of two to avoid the heap allocator ** rounding the size up. **/ PR_EXTERN(void) PL_InitArenaPool( PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align); /* ** Finish using arenas, freeing all memory associated with them. **/ PR_EXTERN(void) PL_ArenaFinish(void); /* ** Free the arenas in pool. The user may continue to allocate from pool ** after calling this function. There is no need to call PL_InitArenaPool() ** again unless PL_FinishArenaPool(pool) has been called. **/ PR_EXTERN(void) PL_FreeArenaPool(PLArenaPool *pool); /* ** Free the arenas in pool and finish using it altogether. **/ PR_EXTERN(void) PL_FinishArenaPool(PLArenaPool *pool); /* ** Compact all of the arenas in a pool so that no space is wasted. ** NOT IMPLEMENTED. Do not use. **/ PR_EXTERN(void) PL_CompactArenaPool(PLArenaPool *pool); /* ** Friend functions used by the PL_ARENA_*() macros. ** ** WARNING: do not call these functions directly. Always use the ** PL_ARENA_*() macros. **/ PR_EXTERN(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb); PR_EXTERN(void *) PL_ArenaGrow( PLArenaPool *pool, void *p, PRUint32 size, PRUint32 incr); PR_EXTERN(void) PL_ArenaRelease(PLArenaPool *pool, char *mark); /* ** memset contents of all arenas in pool to pattern */ PR_EXTERN(void) PL_ClearArenaPool(PLArenaPool *pool, PRInt32 pattern); /* ** A function like malloc_size() or malloc_usable_size() that measures the ** size of a heap block. */ typedef size_t (*PLMallocSizeFn)(const void *ptr); /* ** Measure all memory used by a PLArenaPool, excluding the PLArenaPool ** structure. */ PR_EXTERN(size_t) PL_SizeOfArenaPoolExcludingPool( const PLArenaPool *pool, PLMallocSizeFn mallocSizeOf); PR_END_EXTERN_C #endif /* PLARENAS_H */ nspr-4.11/nspr/lib/ds/plds.def0000644000000000000000000000333012623070344014327 0ustar 00000000000000;+# ;+# This Source Code Form is subject to the terms of the Mozilla Public ;+# License, v. 2.0. If a copy of the MPL was not distributed with this ;+# file, You can obtain one at http://mozilla.org/MPL/2.0/. ;+# ;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS ;+# 1. For all unix platforms, the string ";-" means "remove this line" ;+# 2. For all unix platforms, the string " DATA " will be removed from any ;+# line on which it occurs. ;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. ;+# On AIX, lines containing ";+" will be removed. ;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. ;+# 5. For all unix platforms, after the above processing has taken place, ;+# all characters after the first ";" on the line will be removed. ;+# And for AIX, the first ";" will also be removed. ;+# This file is passed directly to windows. Since ';' is a comment, all UNIX ;+# directives are hidden behind ";", ";+", and ";-" ;+NSPR_4.0 { ;+ global: LIBRARY plds4 ;- EXPORTS ;- PL_ArenaAllocate; PL_ArenaFinish; PL_ArenaGrow; PL_ArenaRelease; PL_CompactArenaPool; PL_CompareStrings; PL_CompareValues; PL_FinishArenaPool; PL_FreeArenaPool; PL_HashString; PL_HashTableAdd; PL_HashTableDestroy; PL_HashTableDump; PL_HashTableEnumerateEntries; PL_HashTableLookup; PL_HashTableRawAdd; PL_HashTableRawLookup; PL_HashTableRawRemove; PL_HashTableRemove; PL_InitArenaPool; PL_NewHashTable; libVersionPoint; ;+ local: *; ;+}; ;+ ;+NSPR_4.1 { ;+ global: PL_HashTableLookupConst; PL_HashTableRawLookupConst; ;+} NSPR_4.0; ;+ ;+NSPR_4.8.5 { ;+ global: PL_ClearArenaPool; ;+} NSPR_4.1; ;+NSPR_4.9.6 { ;+ global: PL_SizeOfArenaPoolExcludingPool; ;+} NSPR_4.8.5; nspr-4.11/nspr/lib/ds/plds.rc0000644000000000000000000000366412623070344014207 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include #define MY_LIBNAME "plds" #define MY_FILEDESCRIPTION "PLDS Library" #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG #else #define MY_DEBUG_STR "" #define MY_FILEFLAGS_1 0x0L #endif #if PR_BETA #define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE #else #define MY_FILEFLAGS_2 MY_FILEFLAGS_1 #endif #ifdef WINNT #define MY_FILEOS VOS_NT_WINDOWS32 #define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR #else #define MY_FILEOS VOS__WINDOWS32 #define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR #endif ///////////////////////////////////////////////////////////////////////////// // // Version-information resource // VS_VERSION_INFO VERSIONINFO FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS MY_FILEFLAGS_2 FILEOS MY_FILEOS FILETYPE VFT_DLL FILESUBTYPE 0x0L // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" // Lang=US English, CharSet=Unicode BEGIN VALUE "CompanyName", "Mozilla Foundation\0" VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END nspr-4.11/nspr/lib/ds/plhash.c0000644000000000000000000003034312623070344014334 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * PL hash table package. */ #include "plhash.h" #include "prbit.h" #include "prlog.h" #include "prmem.h" #include "prtypes.h" #include #include /* Compute the number of buckets in ht */ #define NBUCKETS(ht) (1 << (PL_HASH_BITS - (ht)->shift)) /* The smallest table has 16 buckets */ #define MINBUCKETSLOG2 4 #define MINBUCKETS (1 << MINBUCKETSLOG2) /* Compute the maximum entries given n buckets that we will tolerate, ~90% */ #define OVERLOADED(n) ((n) - ((n) >> 3)) /* Compute the number of entries below which we shrink the table by half */ #define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0) /* ** Stubs for default hash allocator ops. */ static void * PR_CALLBACK DefaultAllocTable(void *pool, PRSize size) { return PR_MALLOC(size); } static void PR_CALLBACK DefaultFreeTable(void *pool, void *item) { PR_Free(item); } static PLHashEntry * PR_CALLBACK DefaultAllocEntry(void *pool, const void *key) { return PR_NEW(PLHashEntry); } static void PR_CALLBACK DefaultFreeEntry(void *pool, PLHashEntry *he, PRUintn flag) { if (flag == HT_FREE_ENTRY) PR_Free(he); } static PLHashAllocOps defaultHashAllocOps = { DefaultAllocTable, DefaultFreeTable, DefaultAllocEntry, DefaultFreeEntry }; PR_IMPLEMENT(PLHashTable *) PL_NewHashTable(PRUint32 n, PLHashFunction keyHash, PLHashComparator keyCompare, PLHashComparator valueCompare, const PLHashAllocOps *allocOps, void *allocPriv) { PLHashTable *ht; PRSize nb; if (n <= MINBUCKETS) { n = MINBUCKETSLOG2; } else { n = PR_CeilingLog2(n); if ((PRInt32)n < 0) return 0; } if (!allocOps) allocOps = &defaultHashAllocOps; ht = (PLHashTable*)((*allocOps->allocTable)(allocPriv, sizeof *ht)); if (!ht) return 0; memset(ht, 0, sizeof *ht); ht->shift = PL_HASH_BITS - n; n = 1 << n; nb = n * sizeof(PLHashEntry *); ht->buckets = (PLHashEntry**)((*allocOps->allocTable)(allocPriv, nb)); if (!ht->buckets) { (*allocOps->freeTable)(allocPriv, ht); return 0; } memset(ht->buckets, 0, nb); ht->keyHash = keyHash; ht->keyCompare = keyCompare; ht->valueCompare = valueCompare; ht->allocOps = allocOps; ht->allocPriv = allocPriv; return ht; } PR_IMPLEMENT(void) PL_HashTableDestroy(PLHashTable *ht) { PRUint32 i, n; PLHashEntry *he, *next; const PLHashAllocOps *allocOps = ht->allocOps; void *allocPriv = ht->allocPriv; n = NBUCKETS(ht); for (i = 0; i < n; i++) { for (he = ht->buckets[i]; he; he = next) { next = he->next; (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY); } } #ifdef DEBUG memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]); #endif (*allocOps->freeTable)(allocPriv, ht->buckets); #ifdef DEBUG memset(ht, 0xDB, sizeof *ht); #endif (*allocOps->freeTable)(allocPriv, ht); } /* ** Multiplicative hash, from Knuth 6.4. */ #define GOLDEN_RATIO 0x9E3779B9U /* 2/(1+sqrt(5))*(2^32) */ PR_IMPLEMENT(PLHashEntry **) PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key) { PLHashEntry *he, **hep, **hep0; PLHashNumber h; #ifdef HASHMETER ht->nlookups++; #endif h = keyHash * GOLDEN_RATIO; h >>= ht->shift; hep = hep0 = &ht->buckets[h]; while ((he = *hep) != 0) { if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) { /* Move to front of chain if not already there */ if (hep != hep0) { *hep = he->next; he->next = *hep0; *hep0 = he; } return hep0; } hep = &he->next; #ifdef HASHMETER ht->nsteps++; #endif } return hep; } /* ** Same as PL_HashTableRawLookup but doesn't reorder the hash entries. */ PR_IMPLEMENT(PLHashEntry **) PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash, const void *key) { PLHashEntry *he, **hep; PLHashNumber h; #ifdef HASHMETER ht->nlookups++; #endif h = keyHash * GOLDEN_RATIO; h >>= ht->shift; hep = &ht->buckets[h]; while ((he = *hep) != 0) { if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key)) { break; } hep = &he->next; #ifdef HASHMETER ht->nsteps++; #endif } return hep; } PR_IMPLEMENT(PLHashEntry *) PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash, const void *key, void *value) { PRUint32 i, n; PLHashEntry *he, *next, **oldbuckets; PRSize nb; /* Grow the table if it is overloaded */ n = NBUCKETS(ht); if (ht->nentries >= OVERLOADED(n)) { oldbuckets = ht->buckets; nb = 2 * n * sizeof(PLHashEntry *); ht->buckets = (PLHashEntry**) ((*ht->allocOps->allocTable)(ht->allocPriv, nb)); if (!ht->buckets) { ht->buckets = oldbuckets; return 0; } memset(ht->buckets, 0, nb); #ifdef HASHMETER ht->ngrows++; #endif ht->shift--; for (i = 0; i < n; i++) { for (he = oldbuckets[i]; he; he = next) { next = he->next; hep = PL_HashTableRawLookup(ht, he->keyHash, he->key); PR_ASSERT(*hep == 0); he->next = 0; *hep = he; } } #ifdef DEBUG memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); #endif (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); hep = PL_HashTableRawLookup(ht, keyHash, key); } /* Make a new key value entry */ he = (*ht->allocOps->allocEntry)(ht->allocPriv, key); if (!he) return 0; he->keyHash = keyHash; he->key = key; he->value = value; he->next = *hep; *hep = he; ht->nentries++; return he; } PR_IMPLEMENT(PLHashEntry *) PL_HashTableAdd(PLHashTable *ht, const void *key, void *value) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookup(ht, keyHash, key); if ((he = *hep) != 0) { /* Hit; see if values match */ if ((*ht->valueCompare)(he->value, value)) { /* key,value pair is already present in table */ return he; } if (he->value) (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE); he->value = value; return he; } return PL_HashTableRawAdd(ht, hep, keyHash, key, value); } PR_IMPLEMENT(void) PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he) { PRUint32 i, n; PLHashEntry *next, **oldbuckets; PRSize nb; *hep = he->next; (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY); /* Shrink table if it's underloaded */ n = NBUCKETS(ht); if (--ht->nentries < UNDERLOADED(n)) { oldbuckets = ht->buckets; nb = n * sizeof(PLHashEntry*) / 2; ht->buckets = (PLHashEntry**)( (*ht->allocOps->allocTable)(ht->allocPriv, nb)); if (!ht->buckets) { ht->buckets = oldbuckets; return; } memset(ht->buckets, 0, nb); #ifdef HASHMETER ht->nshrinks++; #endif ht->shift++; for (i = 0; i < n; i++) { for (he = oldbuckets[i]; he; he = next) { next = he->next; hep = PL_HashTableRawLookup(ht, he->keyHash, he->key); PR_ASSERT(*hep == 0); he->next = 0; *hep = he; } } #ifdef DEBUG memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); #endif (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); } } PR_IMPLEMENT(PRBool) PL_HashTableRemove(PLHashTable *ht, const void *key) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookup(ht, keyHash, key); if ((he = *hep) == 0) return PR_FALSE; /* Hit; remove element */ PL_HashTableRawRemove(ht, hep, he); return PR_TRUE; } PR_IMPLEMENT(void *) PL_HashTableLookup(PLHashTable *ht, const void *key) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookup(ht, keyHash, key); if ((he = *hep) != 0) { return he->value; } return 0; } /* ** Same as PL_HashTableLookup but doesn't reorder the hash entries. */ PR_IMPLEMENT(void *) PL_HashTableLookupConst(PLHashTable *ht, const void *key) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookupConst(ht, keyHash, key); if ((he = *hep) != 0) { return he->value; } return 0; } /* ** Iterate over the entries in the hash table calling func for each ** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP). ** Return a count of the number of elements scanned. */ PR_IMPLEMENT(int) PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg) { PLHashEntry *he, **hep; PRUint32 i, nbuckets; int rv, n = 0; PLHashEntry *todo = 0; nbuckets = NBUCKETS(ht); for (i = 0; i < nbuckets; i++) { hep = &ht->buckets[i]; while ((he = *hep) != 0) { rv = (*f)(he, n, arg); n++; if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) { *hep = he->next; if (rv & HT_ENUMERATE_REMOVE) { he->next = todo; todo = he; } } else { hep = &he->next; } if (rv & HT_ENUMERATE_STOP) { goto out; } } } out: hep = &todo; while ((he = *hep) != 0) { PL_HashTableRawRemove(ht, hep, he); } return n; } #ifdef HASHMETER #include #include PR_IMPLEMENT(void) PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp) { double mean, variance; PRUint32 nchains, nbuckets; PRUint32 i, n, maxChain, maxChainLen; PLHashEntry *he; variance = 0; nchains = 0; maxChainLen = 0; nbuckets = NBUCKETS(ht); for (i = 0; i < nbuckets; i++) { he = ht->buckets[i]; if (!he) continue; nchains++; for (n = 0; he; he = he->next) n++; variance += n * n; if (n > maxChainLen) { maxChainLen = n; maxChain = i; } } mean = (double)ht->nentries / nchains; variance = fabs(variance / nchains - mean * mean); fprintf(fp, "\nHash table statistics:\n"); fprintf(fp, " number of lookups: %u\n", ht->nlookups); fprintf(fp, " number of entries: %u\n", ht->nentries); fprintf(fp, " number of grows: %u\n", ht->ngrows); fprintf(fp, " number of shrinks: %u\n", ht->nshrinks); fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps / ht->nlookups); fprintf(fp, "mean hash chain length: %g\n", mean); fprintf(fp, " standard deviation: %g\n", sqrt(variance)); fprintf(fp, " max hash chain length: %u\n", maxChainLen); fprintf(fp, " max hash chain: [%u]\n", maxChain); for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++) if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT) break; } #endif /* HASHMETER */ PR_IMPLEMENT(int) PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp) { int count; count = PL_HashTableEnumerateEntries(ht, dump, fp); #ifdef HASHMETER PL_HashTableDumpMeter(ht, dump, fp); #endif return count; } PR_IMPLEMENT(PLHashNumber) PL_HashString(const void *key) { PLHashNumber h; const PRUint8 *s; h = 0; for (s = (const PRUint8*)key; *s; s++) h = PR_ROTATE_LEFT32(h, 4) ^ *s; return h; } PR_IMPLEMENT(int) PL_CompareStrings(const void *v1, const void *v2) { return strcmp((const char*)v1, (const char*)v2) == 0; } PR_IMPLEMENT(int) PL_CompareValues(const void *v1, const void *v2) { return v1 == v2; } nspr-4.11/nspr/lib/ds/plhash.h0000644000000000000000000001134212623070344014337 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef plhash_h___ #define plhash_h___ /* * API to portable hash table code. */ #include #include "prtypes.h" PR_BEGIN_EXTERN_C typedef struct PLHashEntry PLHashEntry; typedef struct PLHashTable PLHashTable; typedef PRUint32 PLHashNumber; #define PL_HASH_BITS 32 /* Number of bits in PLHashNumber */ typedef PLHashNumber (PR_CALLBACK *PLHashFunction)(const void *key); typedef PRIntn (PR_CALLBACK *PLHashComparator)(const void *v1, const void *v2); typedef PRIntn (PR_CALLBACK *PLHashEnumerator)(PLHashEntry *he, PRIntn i, void *arg); /* Flag bits in PLHashEnumerator's return value */ #define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ #define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ #define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ #define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */ typedef struct PLHashAllocOps { void * (PR_CALLBACK *allocTable)(void *pool, PRSize size); void (PR_CALLBACK *freeTable)(void *pool, void *item); PLHashEntry * (PR_CALLBACK *allocEntry)(void *pool, const void *key); void (PR_CALLBACK *freeEntry)(void *pool, PLHashEntry *he, PRUintn flag); } PLHashAllocOps; #define HT_FREE_VALUE 0 /* just free the entry's value */ #define HT_FREE_ENTRY 1 /* free value and entire entry */ struct PLHashEntry { PLHashEntry *next; /* hash chain linkage */ PLHashNumber keyHash; /* key hash function result */ const void *key; /* ptr to opaque key */ void *value; /* ptr to opaque value */ }; struct PLHashTable { PLHashEntry **buckets; /* vector of hash buckets */ PRUint32 nentries; /* number of entries in table */ PRUint32 shift; /* multiplicative hash shift */ PLHashFunction keyHash; /* key hash function */ PLHashComparator keyCompare; /* key comparison function */ PLHashComparator valueCompare; /* value comparison function */ const PLHashAllocOps *allocOps; /* allocation operations */ void *allocPriv; /* allocation private data */ #ifdef HASHMETER PRUint32 nlookups; /* total number of lookups */ PRUint32 nsteps; /* number of hash chains traversed */ PRUint32 ngrows; /* number of table expansions */ PRUint32 nshrinks; /* number of table contractions */ #endif }; /* * Create a new hash table. * If allocOps is null, use default allocator ops built on top of malloc(). */ PR_EXTERN(PLHashTable *) PL_NewHashTable(PRUint32 numBuckets, PLHashFunction keyHash, PLHashComparator keyCompare, PLHashComparator valueCompare, const PLHashAllocOps *allocOps, void *allocPriv); PR_EXTERN(void) PL_HashTableDestroy(PLHashTable *ht); /* Higher level access methods */ PR_EXTERN(PLHashEntry *) PL_HashTableAdd(PLHashTable *ht, const void *key, void *value); PR_EXTERN(PRBool) PL_HashTableRemove(PLHashTable *ht, const void *key); PR_EXTERN(void *) PL_HashTableLookup(PLHashTable *ht, const void *key); PR_EXTERN(void *) PL_HashTableLookupConst(PLHashTable *ht, const void *key); PR_EXTERN(PRIntn) PL_HashTableEnumerateEntries(PLHashTable *ht, PLHashEnumerator f, void *arg); /* General-purpose C string hash function. */ PR_EXTERN(PLHashNumber) PL_HashString(const void *key); /* Compare strings using strcmp(), return true if equal. */ PR_EXTERN(PRIntn) PL_CompareStrings(const void *v1, const void *v2); /* Stub function just returns v1 == v2 */ PR_EXTERN(PRIntn) PL_CompareValues(const void *v1, const void *v2); /* Low level access methods */ PR_EXTERN(PLHashEntry **) PL_HashTableRawLookup(PLHashTable *ht, PLHashNumber keyHash, const void *key); PR_EXTERN(PLHashEntry **) PL_HashTableRawLookupConst(PLHashTable *ht, PLHashNumber keyHash, const void *key); PR_EXTERN(PLHashEntry *) PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash, const void *key, void *value); PR_EXTERN(void) PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he); /* This can be trivially implemented using PL_HashTableEnumerateEntries. */ PR_EXTERN(PRIntn) PL_HashTableDump(PLHashTable *ht, PLHashEnumerator dump, FILE *fp); PR_END_EXTERN_C #endif /* plhash_h___ */ nspr-4.11/nspr/lib/ds/plvrsion.c0000644000000000000000000000612012623070344014725 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include "prvrsion.h" /************************************************************************/ /**************************IDENTITY AND VERSIONING***********************/ /************************************************************************/ #include "_pl_bld.h" #if !defined(_BUILD_TIME) #ifdef HAVE_LONG_LONG #define _BUILD_TIME 0 #else #define _BUILD_TIME {0, 0} #endif #endif #if !defined(_BUILD_STRING) #define _BUILD_STRING "" #endif #if !defined(_PRODUCTION) #define _PRODUCTION "" #endif #if defined(DEBUG) #define _DEBUG_STRING " (debug)" #else #define _DEBUG_STRING "" #endif /* * A trick to expand the PR_VMAJOR macro before concatenation. */ #define CONCAT(x, y) x ## y #define CONCAT2(x, y) CONCAT(x, y) #define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplds, PR_VMAJOR) PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */ /* vMajor */ PR_VMAJOR, /* NSPR's version number */ /* vMinor */ PR_VMINOR, /* and minor version */ /* vPatch */ PR_VPATCH, /* and patch */ /* beta */ PR_BETA, /* beta build boolean */ #if defined(DEBUG) /* debug */ PR_TRUE, /* a debug build */ #else /* debug */ PR_FALSE, /* an optomized build */ #endif /* special */ PR_FALSE, /* they're all special, but ... */ /* filename */ _PRODUCTION, /* the produced library name */ /* description */ "Portable runtime", /* what we are */ /* security */ "N/A", /* not applicable here */ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved", /* comment */ "http://www.mozilla.org/MPL/", /* specialString */ "" }; #ifdef XP_UNIX /* * Version information for the 'ident' and 'what commands * * NOTE: the first component of the concatenated rcsid string * must not end in a '$' to prevent rcs keyword substitution. */ static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING " $"; static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING; #endif /* XP_UNIX */ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() { #ifdef XP_UNIX /* * Add dummy references to rcsid and sccsid to prevent them * from being optimized away as unused variables. */ const char *dummy; dummy = rcsid; dummy = sccsid; #endif return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* plvrsion.c */ nspr-4.11/nspr/lib/libc/.cvsignore0000644000000000000000000000001112623070344015201 0ustar 00000000000000Makefile nspr-4.11/nspr/lib/libc/Makefile.in0000644000000000000000000000072612623070344015263 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk export NSPR20=1 include $(topsrcdir)/config/config.mk DIRS = include src include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/lib/libc/README0000644000000000000000000000147012623070344014073 0ustar 00000000000000NSPR 2.0 libc functions ----------------------- Last edited: AOF 04 March 1997 This directory contains various libc-types of functions. All functions in this directory are platform independent, thread friendly (both safe and efficient). They are contributed from various sources, though the contri- butions are monitored by the NSPR group (mailto:freier). All API items exported by these functions will contain the same three character prefix, "PL_" (Portable Library). Internal function names that are not exported (static) are of little concern, though some caution must be used on those elements that are 'extern' but not really intended to be part of the API. Those should all have a prefix of "_PL_" (is that legal?). The responsibility for contributions in this area are distributed among all interested parties. nspr-4.11/nspr/lib/libc/include/.cvsignore0000644000000000000000000000001112623070344016624 0ustar 00000000000000Makefile nspr-4.11/nspr/lib/libc/include/Makefile.in0000644000000000000000000000112412623070344016677 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk HEADERS = $(wildcard $(srcdir)/*.h) RELEASE_HEADERS = $(HEADERS) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR) include $(topsrcdir)/config/rules.mk export:: $(HEADERS) $(INSTALL) -m 444 $(HEADERS) $(dist_includedir) nspr-4.11/nspr/lib/libc/include/README0000644000000000000000000000022712623070344015515 0ustar 00000000000000NSPR 2.0 libc functions ----------------------- Last edited: AOF 04 March 1997 This directory contains the API for various libc-types of functions. nspr-4.11/nspr/lib/libc/include/plbase64.h0000644000000000000000000000551712623070344016435 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _plbase64_h #define _plbase64_h #include "prtypes.h" PR_BEGIN_EXTERN_C /* * PL_Base64Encode * * This routine encodes the data pointed to by the "src" parameter using the * base64 algorithm, and returns a pointer to the result. If the "srclen" * parameter is not zero, it specifies the length of the source data. If it * is zero, the source data is assumed to be null-terminated, and PL_strlen * is used to determine the source length. If the "dest" parameter is not * null, it is assumed to point to a buffer of sufficient size (which may be * calculated: ((srclen + 2)/3)*4) into which the encoded data is placed * (without any termination). If the "dest" parameter is null, a buffer is * allocated from the heap to hold the encoded data, and the result *will* * be terminated with an extra null character. It is the caller's * responsibility to free the result when it is allocated. A null is returned * if the allocation fails. * * NOTE: when calculating ((srclen + 2)/3)*4), first ensure that * srclen <= (PR_UINT32_MAX/4) * 3 * to avoid PRUint32 overflow. */ PR_EXTERN(char *) PL_Base64Encode ( const char *src, PRUint32 srclen, char *dest ); /* * PL_Base64Decode * * This routine decodes the data pointed to by the "src" parameter using * the base64 algorithm, and returns a pointer to the result. The source * may either include or exclude any trailing '=' characters. If the * "srclen" parameter is not zero, it specifies the length of the source * data. If it is zero, PL_strlen will be used to determine the source * length. If the "dest" parameter is not null, it is assumed to point to * a buffer of sufficient size (which may be calculated: (srclen * 3)/4 * when srclen includes the '=' characters) into which the decoded data * is placed (without any termination). If the "dest" parameter is null, * a buffer is allocated from the heap to hold the decoded data, and the * result *will* be terminated with an extra null character. It is the * caller's responsibility to free the result when it is allocated. A null * is retuned if the allocation fails, or if the source is not well-coded. * * NOTE: when calculating (srclen * 3)/4, first ensure that * srclen <= PR_UINT32_MAX/3 * to avoid PRUint32 overflow. Alternatively, calculate * (srclen/4) * 3 + ((srclen%4) * 3)/4 * which is equivalent but doesn't overflow for any value of srclen. */ PR_EXTERN(char *) PL_Base64Decode ( const char *src, PRUint32 srclen, char *dest ); PR_END_EXTERN_C #endif /* _plbase64_h */ nspr-4.11/nspr/lib/libc/include/plerror.h0000644000000000000000000000156012623070344016474 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: plerror.h ** Description: Simple routine to print translate the calling thread's ** error numbers and print them. */ #if defined(PLERROR_H) #else #define PLERROR_H #include "prio.h" #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** Print the messages to "syserr" prepending 'msg' if not NULL. */ PR_EXTERN(void) PL_PrintError(const char *msg); /* ** Print the messages to specified output file prepending 'msg' if not NULL. */ PR_EXTERN(void) PL_FPrintError(PRFileDesc *output, const char *msg); PR_END_EXTERN_C #endif /* defined(PLERROR_H) */ /* plerror.h */ nspr-4.11/nspr/lib/libc/include/plgetopt.h0000644000000000000000000001127612623070344016652 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: plgetopt.h ** Description: utilities to parse argc/argv */ #if defined(PLGETOPT_H_) #else #define PLGETOPT_H_ #include "prtypes.h" PR_BEGIN_EXTERN_C typedef struct PLOptionInternal PLOptionInternal; typedef enum { PL_OPT_OK, /* all's well with the option */ PL_OPT_EOL, /* end of options list */ PL_OPT_BAD /* invalid option (and value) */ } PLOptStatus; typedef struct PLLongOpt { const char * longOptName; /* long option name string */ PRIntn longOption; /* value put in PLOptState for this option. */ PRBool valueRequired; /* If option name not followed by '=', */ /* value is the next argument from argv. */ } PLLongOpt; typedef struct PLOptState { char option; /* the name of the option */ const char *value; /* the value of that option | NULL */ PLOptionInternal *internal; /* private processing state */ PRIntn longOption; /* value from PLLongOpt put here */ PRIntn longOptIndex; /* index into caller's array of PLLongOpts */ } PLOptState; /* * PL_CreateOptState * * The argument "options" points to a string of single-character option * names. Option names that may have an option argument value must be * followed immediately by a ':' character. */ PR_EXTERN(PLOptState*) PL_CreateOptState( PRIntn argc, char **argv, const char *options); /* * PL_CreateLongOptState * * Alternative to PL_CreateOptState. * Allows caller to specify BOTH a string of single-character option names, * AND an array of structures describing "long" (keyword) option names. * The array is terminated by a structure in which longOptName is NULL. * Long option values (arguments) may always be given as "--name=value". * If PLLongOpt.valueRequired is not PR_FALSE, and the option name was not * followed by '=' then the next argument from argv is taken as the value. */ PR_EXTERN(PLOptState*) PL_CreateLongOptState( PRIntn argc, char **argv, const char *options, const PLLongOpt *longOpts); /* * PL_DestroyOptState * * Call this to destroy the PLOptState returned from PL_CreateOptState or * PL_CreateLongOptState. */ PR_EXTERN(void) PL_DestroyOptState(PLOptState *opt); /* * PL_GetNextOpt * * When this function returns PL_OPT_OK, * - opt->option will hold the single-character option name that was parsed, * or zero. * When opt->option is zero, the token parsed was either a "long" (keyword) * option or a positional parameter. * For a positional parameter, * - opt->longOptIndex will contain -1, and * - opt->value will point to the positional parameter string. * For a long option name, * - opt->longOptIndex will contain the non-negative index of the * PLLongOpt structure in the caller's array of PLLongOpt structures * corresponding to the long option name, and * For a single-character or long option, * - opt->longOption will contain the value of the single-character option * name, or the value of the longOption from the PLLongOpt structure * for that long option. See notes below. * - opt->value will point to the argument option string, or will * be NULL if option does not require argument. If option requires * argument but it is not provided, PL_OPT_BAD is returned. * When opt->option is non-zero, * - opt->longOptIndex will be -1 * When this function returns PL_OPT_EOL, or PL_OPT_BAD, the contents of * opt are undefined. * * Notes: It is possible to ignore opt->option, and always look at * opt->longOption instead. opt->longOption will contain the same value * as opt->option for single-character option names, and will contain the * value of longOption from the PLLongOpt structure for long option names. * This means that it is possible to equivalence long option names to * single character names by giving the longOption in the PLLongOpt struct * the same value as the single-character option name. * For long options that are NOT intended to be equivalent to any single- * character option, the longOption value should be chosen to not match * any possible single character name. It might be advisable to choose * longOption values greater than 0xff for such long options. */ PR_EXTERN(PLOptStatus) PL_GetNextOpt(PLOptState *opt); PR_END_EXTERN_C #endif /* defined(PLGETOPT_H_) */ /* plgetopt.h */ nspr-4.11/nspr/lib/libc/include/plstr.h0000644000000000000000000003220212623070344016150 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _plstr_h #define _plstr_h /* * plstr.h * * This header file exports the API to the NSPR portable library or string- * handling functions. * * This API was not designed as an "optimal" or "ideal" string library; it * was based on the good ol' unix string.3 functions, and was written to * * 1) replace the libc functions, for cross-platform consistency, * 2) complete the API on platforms lacking common functions (e.g., * strcase*), and * 3) to implement some obvious "closure" functions that I've seen * people hacking around in our code. * * Point number three largely means that most functions have an "strn" * limited-length version, and all comparison routines have a non-case- * sensitive version available. */ #include "prtypes.h" PR_BEGIN_EXTERN_C /* * PL_strlen * * Returns the length of the provided string, not including the trailing '\0'. */ PR_EXTERN(PRUint32) PL_strlen(const char *str); /* * PL_strnlen * * Returns the length of the provided string, not including the trailing '\0', * up to the indicated maximum. The string will not be examined beyond the * maximum; if no terminating '\0' is found, the maximum will be returned. */ PR_EXTERN(PRUint32) PL_strnlen(const char *str, PRUint32 max); /* * PL_strcpy * * Copies the source string, up to and including the trailing '\0', into the * destination buffer. It does not (can not) verify that the destination * buffer is large enough. It returns the "dest" argument. */ PR_EXTERN(char *) PL_strcpy(char *dest, const char *src); /* * PL_strncpy * * Copies the source string into the destination buffer, up to and including * the trailing '\0' or up to and including the max'th character, whichever * comes first. It does not (can not) verify that the destination buffer is * large enough. If the source string is longer than the maximum length, * the result will *not* be null-terminated (JLRU). */ PR_EXTERN(char *) PL_strncpy(char *dest, const char *src, PRUint32 max); /* * PL_strncpyz * * Copies the source string into the destination buffer, up to and including * the trailing '\0' or up but not including the max'th character, whichever * comes first. It does not (can not) verify that the destination buffer is * large enough. The destination string is always terminated with a '\0', * unlike the traditional libc implementation. It returns the "dest" argument. * * NOTE: If you call this with a source "abcdefg" and a max of 5, the * destination will end up with "abcd\0" (i.e., its strlen length will be 4)! * * This means you can do this: * * char buffer[ SOME_SIZE ]; * PL_strncpyz(buffer, src, sizeof(buffer)); * * and the result will be properly terminated. */ PR_EXTERN(char *) PL_strncpyz(char *dest, const char *src, PRUint32 max); /* * PL_strdup * * Returns a pointer to a malloc'd extent of memory containing a duplicate * of the argument string. The size of the allocated extent is one greater * than the length of the argument string, because of the terminator. A * null argument, like a zero-length argument, will result in a pointer to * a one-byte extent containing the null value. This routine returns null * upon malloc failure. */ PR_EXTERN(char *) PL_strdup(const char *s); /* * PL_strfree * * Free memory allocated by PL_strdup */ PR_EXTERN(void) PL_strfree(char *s); /* * PL_strndup * * Returns a pointer to a malloc'd extent of memory containing a duplicate * of the argument string, up to the maximum specified. If the argument * string has a length greater than the value of the specified maximum, the * return value will be a pointer to an extent of memory of length one * greater than the maximum specified. A null string, a zero-length string, * or a zero maximum will all result in a pointer to a one-byte extent * containing the null value. This routine returns null upon malloc failure. */ PR_EXTERN(char *) PL_strndup(const char *s, PRUint32 max); /* * PL_strcat * * Appends a copy of the string pointed to by the second argument to the * end of the string pointed to by the first. The destination buffer is * not (can not be) checked for sufficient size. A null destination * argument returns null; otherwise, the first argument is returned. */ PR_EXTERN(char *) PL_strcat(char *dst, const char *src); /* * PL_strncat * * Appends a copy of the string pointed to by the second argument, up to * the maximum size specified, to the end of the string pointed to by the * first. The destination buffer is not (can not be) checked for sufficient * size. A null destination argument returns null; otherwise, the first * argument is returned. If the maximum size limits the copy, then the * result will *not* be null-terminated (JLRU). A null destination * returns null; otherwise, the destination argument is returned. */ PR_EXTERN(char *) PL_strncat(char *dst, const char *src, PRUint32 max); /* * PL_strcatn * * Appends a copy of the string pointed to by the third argument, to the * end of the string pointed to by the first. The second argument specifies * the maximum size of the destination buffer, including the null termination. * If the existing string in dst is longer than the max, no action is taken. * The resulting string will be null-terminated. A null destination returns * null; otherwise, the destination argument is returned. */ PR_EXTERN(char *) PL_strcatn(char *dst, PRUint32 max, const char *src); /* * PL_strcmp * * Returns an integer, the sign of which -- positive, zero, or negative -- * reflects the lexical sorting order of the two strings indicated. The * result is positive if the first string comes after the second. The * NSPR implementation is not i18n. */ PR_EXTERN(PRIntn) PL_strcmp(const char *a, const char *b); /* * PL_strncmp * * Returns an integer, the sign of which -- positive, zero, or negative -- * reflects the lexical sorting order of the two strings indicated, up to * the maximum specified. The result is positive if the first string comes * after the second. The NSPR implementation is not i18n. If the maximum * is zero, only the existance or non-existance (pointer is null) of the * strings is compared. */ PR_EXTERN(PRIntn) PL_strncmp(const char *a, const char *b, PRUint32 max); /* * PL_strcasecmp * * Returns an integer, the sign of which -- positive, zero or negative -- * reflects the case-insensitive lexical sorting order of the two strings * indicated. The result is positive if the first string comes after the * second. The NSPR implementation is not i18n. */ PR_EXTERN(PRIntn) PL_strcasecmp(const char *a, const char *b); /* * PL_strncasecmp * * Returns an integer, the sign of which -- positive, zero or negative -- * reflects the case-insensitive lexical sorting order of the first n characters * of the two strings indicated. The result is positive if the first string comes * after the second. The NSPR implementation is not i18n. */ PR_EXTERN(PRIntn) PL_strncasecmp(const char *a, const char *b, PRUint32 max); /* * PL_strchr * * Returns a pointer to the first instance of the specified character in the * provided string. It returns null if the character is not found, or if the * provided string is null. The character may be the null character. */ PR_EXTERN(char *) PL_strchr(const char *s, char c); /* * PL_strrchr * * Returns a pointer to the last instance of the specified character in the * provided string. It returns null if the character is not found, or if the * provided string is null. The character may be the null character. */ PR_EXTERN(char *) PL_strrchr(const char *s, char c); /* * PL_strnchr * * Returns a pointer to the first instance of the specified character within the * first n characters of the provided string. It returns null if the character * is not found, or if the provided string is null. The character may be the * null character. */ PR_EXTERN(char *) PL_strnchr(const char *s, char c, PRUint32 n); /* * PL_strnrchr * * Returns a pointer to the last instance of the specified character within the * first n characters of the provided string. It returns null if the character is * not found, or if the provided string is null. The character may be the null * character. */ PR_EXTERN(char *) PL_strnrchr(const char *s, char c, PRUint32 n); /* * NOTE: Looking for strcasechr, strcaserchr, strncasechr, or strncaserchr? * Use strpbrk, strprbrk, strnpbrk or strnprbrk. */ /* * PL_strpbrk * * Returns a pointer to the first instance in the first string of any character * (not including the terminating null character) of the second string. It returns * null if either string is null. */ PR_EXTERN(char *) PL_strpbrk(const char *s, const char *list); /* * PL_strprbrk * * Returns a pointer to the last instance in the first string of any character * (not including the terminating null character) of the second string. It returns * null if either string is null. */ PR_EXTERN(char *) PL_strprbrk(const char *s, const char *list); /* * PL_strnpbrk * * Returns a pointer to the first instance (within the first n characters) of any * character (not including the terminating null character) of the second string. * It returns null if either string is null. */ PR_EXTERN(char *) PL_strnpbrk(const char *s, const char *list, PRUint32 n); /* * PL_strnprbrk * * Returns a pointer to the last instance (within the first n characters) of any * character (not including the terminating null character) of the second string. * It returns null if either string is null. */ PR_EXTERN(char *) PL_strnprbrk(const char *s, const char *list, PRUint32 n); /* * PL_strstr * * Returns a pointer to the first instance of the little string within the * big one. It returns null if either string is null. */ PR_EXTERN(char *) PL_strstr(const char *big, const char *little); /* * PL_strrstr * * Returns a pointer to the last instance of the little string within the big one. * It returns null if either string is null. */ PR_EXTERN(char *) PL_strrstr(const char *big, const char *little); /* * PL_strnstr * * Returns a pointer to the first instance of the little string within the first * n characters of the big one. It returns null if either string is null. It * returns null if the length of the little string is greater than n. */ PR_EXTERN(char *) PL_strnstr(const char *big, const char *little, PRUint32 n); /* * PL_strnrstr * * Returns a pointer to the last instance of the little string within the first * n characters of the big one. It returns null if either string is null. It * returns null if the length of the little string is greater than n. */ PR_EXTERN(char *) PL_strnrstr(const char *big, const char *little, PRUint32 max); /* * PL_strcasestr * * Returns a pointer to the first instance of the little string within the big one, * ignoring case. It returns null if either string is null. */ PR_EXTERN(char *) PL_strcasestr(const char *big, const char *little); /* * PL_strcaserstr * * Returns a pointer to the last instance of the little string within the big one, * ignoring case. It returns null if either string is null. */ PR_EXTERN(char *) PL_strcaserstr(const char *big, const char *little); /* * PL_strncasestr * * Returns a pointer to the first instance of the little string within the first * n characters of the big one, ignoring case. It returns null if either string is * null. It returns null if the length of the little string is greater than n. */ PR_EXTERN(char *) PL_strncasestr(const char *big, const char *little, PRUint32 max); /* * PL_strncaserstr * * Returns a pointer to the last instance of the little string within the first * n characters of the big one, ignoring case. It returns null if either string is * null. It returns null if the length of the little string is greater than n. */ PR_EXTERN(char *) PL_strncaserstr(const char *big, const char *little, PRUint32 max); /* * PL_strtok_r * * Splits the string s1 into tokens, separated by one or more characters * from the separator string s2. The argument lasts points to a * user-supplied char * pointer in which PL_strtok_r stores information * for it to continue scanning the same string. * * In the first call to PL_strtok_r, s1 points to a string and the value * of *lasts is ignored. PL_strtok_r returns a pointer to the first * token, writes '\0' into the character following the first token, and * updates *lasts. * * In subsequent calls, s1 is null and lasts must stay unchanged from the * previous call. The separator string s2 may be different from call to * call. PL_strtok_r returns a pointer to the next token in s1. When no * token remains in s1, PL_strtok_r returns null. */ PR_EXTERN(char *) PL_strtok_r(char *s1, const char *s2, char **lasts); /* * Things not (yet?) included: strspn/strcspn, strsep. * memchr, memcmp, memcpy, memccpy, index, rindex, bcmp, bcopy, bzero. * Any and all i18n/l10n stuff. */ PR_END_EXTERN_C #endif /* _plstr_h */ nspr-4.11/nspr/lib/libc/src/.cvsignore0000644000000000000000000000002312623070344015773 0ustar 00000000000000Makefile _pl_bld.h nspr-4.11/nspr/lib/libc/src/Makefile.in0000644000000000000000000000575312623070344016057 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk INCLUDES = -I$(dist_includedir) CSRCS =\ plvrsion.c \ strlen.c \ strcpy.c \ strdup.c \ strcase.c \ strcat.c \ strcmp.c \ strchr.c \ strpbrk.c \ strstr.c \ strtok.c \ base64.c \ plerror.c \ plgetopt.c \ $(NULL) LIBRARY_NAME = plc LIBRARY_VERSION = $(MOD_MAJOR_VERSION) RELEASE_LIBS = $(TARGETS) ifeq ($(OS_ARCH),WINNT) RES=$(OBJDIR)/plc.res RESNAME=plc.rc endif # WINNT ifeq ($(OS_ARCH), AIX) ifeq ($(CLASSIC_NSPR),1) OS_LIBS = -lc else OS_LIBS = -lc_r endif endif ifeq ($(OS_ARCH),IRIX) OS_LIBS = -lc endif ifeq ($(OS_ARCH),SunOS) OS_LIBS = -lc MAPFILE = $(OBJDIR)/plcmap.sun GARBAGE += $(MAPFILE) ifdef NS_USE_GCC ifdef GCC_USE_GNU_LD MKSHLIB += -Wl,--version-script,$(MAPFILE) else MKSHLIB += -Wl,-M,$(MAPFILE) endif else MKSHLIB += -M $(MAPFILE) endif # The -R '$ORIGIN' linker option instructs this library to search for its # dependencies in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' endif ifeq ($(OS_ARCH),OS2) MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def GARBAGE += $(MAPFILE) MKSHLIB += $(MAPFILE) endif EXTRA_LIBS = $(LIBNSPR) # On SCOOS, we can't link with extra libraries when # we build a shared library. If we do so, the linker doesn't # complain, but we would run into weird problems at run-time. # Therefore on these platforms, we link just the .o files. ifeq ($(OS_ARCH),SCOOS) EXTRA_LIBS = endif ifdef RESOLVE_LINK_SYMBOLS EXTRA_LIBS += $(OS_LIBS) endif include $(topsrcdir)/config/rules.mk # # Version information generation (begin) # ECHO = echo TINC = $(OBJDIR)/_pl_bld.h PROD = $(notdir $(SHARED_LIBRARY)) NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now SH_DATE = $(shell date "+%Y-%m-%d %T") SH_NOW = $(shell $(NOW)) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) SUF = i64 else SUF = LL endif GARBAGE += $(TINC) $(TINC): @$(MAKE_OBJDIR) @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC) @if test ! -z "$(SH_NOW)"; then \ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \ else \ true; \ fi @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC) $(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $< else $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< endif # # Version information generation (end) # # # The Client build wants the shared libraries in $(dist_bindir), # so we also install them there. # export:: $(TARGETS) $(INSTALL) -m 444 $(TARGETS) $(dist_libdir) ifdef SHARED_LIBRARY ifeq ($(OS_ARCH),HP-UX) $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir) $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir) else $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir) endif endif nspr-4.11/nspr/lib/libc/src/README0000644000000000000000000000147012623070344014662 0ustar 00000000000000NSPR 2.0 libc functions ----------------------- Last edited: AOF 04 March 1997 This directory contains various libc-types of functions. All functions in this directory are platform independent, thread friendly (both safe and efficient). They are contributed from various sources, though the contri- butions are monitored by the NSPR group (mailto:freier). All API items exported by these functions will contain the same three character prefix, "PL_" (Portable Library). Internal function names that are not exported (static) are of little concern, though some caution must be used on those elements that are 'extern' but not really intended to be part of the API. Those should all have a prefix of "_PL_" (is that legal?). The responsibility for contributions in this area are distributed among all interested parties. nspr-4.11/nspr/lib/libc/src/base64.c0000644000000000000000000002003512623070344015230 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plbase64.h" #include "prlog.h" /* For PR_NOT_REACHED */ #include "prmem.h" /* for malloc / PR_MALLOC */ #include /* for strlen */ static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static void encode3to4 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32 = (PRUint32)0; PRIntn i, j = 18; for( i = 0; i < 3; i++ ) { b32 <<= 8; b32 |= (PRUint32)src[i]; } for( i = 0; i < 4; i++ ) { dest[i] = base[ (PRUint32)((b32>>j) & 0x3F) ]; j -= 6; } return; } static void encode2to4 ( const unsigned char *src, unsigned char *dest ) { dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ]; dest[1] = base[ (PRUint32)(((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0F)) ]; dest[2] = base[ (PRUint32)((src[1] & 0x0F) << 2) ]; dest[3] = (unsigned char)'='; return; } static void encode1to4 ( const unsigned char *src, unsigned char *dest ) { dest[0] = base[ (PRUint32)((src[0]>>2) & 0x3F) ]; dest[1] = base[ (PRUint32)((src[0] & 0x03) << 4) ]; dest[2] = (unsigned char)'='; dest[3] = (unsigned char)'='; return; } static void encode ( const unsigned char *src, PRUint32 srclen, unsigned char *dest ) { while( srclen >= 3 ) { encode3to4(src, dest); src += 3; dest += 4; srclen -= 3; } switch( srclen ) { case 2: encode2to4(src, dest); break; case 1: encode1to4(src, dest); break; case 0: break; default: PR_NOT_REACHED("coding error"); } return; } /* * PL_Base64Encode * * If the destination argument is NULL, a return buffer is * allocated, and the data therein will be null-terminated. * If the destination argument is not NULL, it is assumed to * be of sufficient size, and the contents will not be null- * terminated by this routine. * * Returns null if the allocation fails. */ PR_IMPLEMENT(char *) PL_Base64Encode ( const char *src, PRUint32 srclen, char *dest ) { if( 0 == srclen ) { size_t len = strlen(src); srclen = len; /* Detect truncation. */ if( srclen != len ) { return (char *)0; } } if( (char *)0 == dest ) { PRUint32 destlen; /* Ensure all PRUint32 values stay within range. */ if( srclen > (PR_UINT32_MAX/4) * 3 ) { return (char *)0; } destlen = ((srclen + 2)/3) * 4; dest = (char *)PR_MALLOC(destlen + 1); if( (char *)0 == dest ) { return (char *)0; } dest[ destlen ] = (char)0; /* null terminate */ } encode((const unsigned char *)src, srclen, (unsigned char *)dest); return dest; } static PRInt32 codetovalue ( unsigned char c ) { if( (c >= (unsigned char)'A') && (c <= (unsigned char)'Z') ) { return (PRInt32)(c - (unsigned char)'A'); } else if( (c >= (unsigned char)'a') && (c <= (unsigned char)'z') ) { return ((PRInt32)(c - (unsigned char)'a') +26); } else if( (c >= (unsigned char)'0') && (c <= (unsigned char)'9') ) { return ((PRInt32)(c - (unsigned char)'0') +52); } else if( (unsigned char)'+' == c ) { return (PRInt32)62; } else if( (unsigned char)'/' == c ) { return (PRInt32)63; } else { return -1; } } static PRStatus decode4to3 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32 = (PRUint32)0; PRInt32 bits; PRIntn i; for( i = 0; i < 4; i++ ) { bits = codetovalue(src[i]); if( bits < 0 ) { return PR_FAILURE; } b32 <<= 6; b32 |= bits; } dest[0] = (unsigned char)((b32 >> 16) & 0xFF); dest[1] = (unsigned char)((b32 >> 8) & 0xFF); dest[2] = (unsigned char)((b32 ) & 0xFF); return PR_SUCCESS; } static PRStatus decode3to2 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32 = (PRUint32)0; PRInt32 bits; PRUint32 ubits; bits = codetovalue(src[0]); if( bits < 0 ) { return PR_FAILURE; } b32 = (PRUint32)bits; b32 <<= 6; bits = codetovalue(src[1]); if( bits < 0 ) { return PR_FAILURE; } b32 |= (PRUint32)bits; b32 <<= 4; bits = codetovalue(src[2]); if( bits < 0 ) { return PR_FAILURE; } ubits = (PRUint32)bits; b32 |= (ubits >> 2); dest[0] = (unsigned char)((b32 >> 8) & 0xFF); dest[1] = (unsigned char)((b32 ) & 0xFF); return PR_SUCCESS; } static PRStatus decode2to1 ( const unsigned char *src, unsigned char *dest ) { PRUint32 b32; PRUint32 ubits; PRInt32 bits; bits = codetovalue(src[0]); if( bits < 0 ) { return PR_FAILURE; } ubits = (PRUint32)bits; b32 = (ubits << 2); bits = codetovalue(src[1]); if( bits < 0 ) { return PR_FAILURE; } ubits = (PRUint32)bits; b32 |= (ubits >> 4); dest[0] = (unsigned char)b32; return PR_SUCCESS; } static PRStatus decode ( const unsigned char *src, PRUint32 srclen, unsigned char *dest ) { PRStatus rv; while( srclen >= 4 ) { rv = decode4to3(src, dest); if( PR_SUCCESS != rv ) { return PR_FAILURE; } src += 4; dest += 3; srclen -= 4; } switch( srclen ) { case 3: rv = decode3to2(src, dest); break; case 2: rv = decode2to1(src, dest); break; case 1: rv = PR_FAILURE; break; case 0: rv = PR_SUCCESS; break; default: PR_NOT_REACHED("coding error"); } return rv; } /* * PL_Base64Decode * * If the destination argument is NULL, a return buffer is * allocated and the data therein will be null-terminated. * If the destination argument is not null, it is assumed * to be of sufficient size, and the data will not be null- * terminated by this routine. * * Returns null if the allocation fails, or if the source string is * not well-formed. */ PR_IMPLEMENT(char *) PL_Base64Decode ( const char *src, PRUint32 srclen, char *dest ) { PRStatus status; PRBool allocated = PR_FALSE; if( (char *)0 == src ) { return (char *)0; } if( 0 == srclen ) { size_t len = strlen(src); srclen = len; /* Detect truncation. */ if( srclen != len ) { return (char *)0; } } if( srclen && (0 == (srclen & 3)) ) { if( (char)'=' == src[ srclen-1 ] ) { if( (char)'=' == src[ srclen-2 ] ) { srclen -= 2; } else { srclen -= 1; } } } if( (char *)0 == dest ) { /* The following computes ((srclen * 3) / 4) without overflow. */ PRUint32 destlen = (srclen / 4) * 3 + ((srclen % 4) * 3) / 4; dest = (char *)PR_MALLOC(destlen + 1); if( (char *)0 == dest ) { return (char *)0; } dest[ destlen ] = (char)0; /* null terminate */ allocated = PR_TRUE; } status = decode((const unsigned char *)src, srclen, (unsigned char *)dest); if( PR_SUCCESS != status ) { if( PR_TRUE == allocated ) { PR_DELETE(dest); } return (char *)0; } return dest; } nspr-4.11/nspr/lib/libc/src/plc.def0000644000000000000000000000332212623070344015236 0ustar 00000000000000;+# ;+# This Source Code Form is subject to the terms of the Mozilla Public ;+# License, v. 2.0. If a copy of the MPL was not distributed with this ;+# file, You can obtain one at http://mozilla.org/MPL/2.0/. ;+# ;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS ;+# 1. For all unix platforms, the string ";-" means "remove this line" ;+# 2. For all unix platforms, the string " DATA " will be removed from any ;+# line on which it occurs. ;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. ;+# On AIX, lines containing ";+" will be removed. ;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. ;+# 5. For all unix platforms, after the above processing has taken place, ;+# all characters after the first ";" on the line will be removed. ;+# And for AIX, the first ";" will also be removed. ;+# This file is passed directly to windows. Since ';' is a comment, all UNIX ;+# directives are hidden behind ";", ";+", and ";-" ;+NSPR_4.0 { ;+ global: LIBRARY plc4 ;- EXPORTS ;- PL_Base64Decode; PL_Base64Encode; PL_CreateOptState; PL_DestroyOptState; PL_FPrintError; PL_GetNextOpt; PL_PrintError; PL_strcasecmp; PL_strcaserstr; PL_strcasestr; PL_strcat; PL_strcatn; PL_strchr; PL_strcmp; PL_strcpy; PL_strdup; PL_strfree; PL_strlen; PL_strncasecmp; PL_strncaserstr; PL_strncasestr; PL_strncat; PL_strnchr; PL_strncmp; PL_strncpy; PL_strncpyz; PL_strndup; PL_strnlen; PL_strnpbrk; PL_strnprbrk; PL_strnrchr; PL_strnrstr; PL_strnstr; PL_strpbrk; PL_strprbrk; PL_strrchr; PL_strrstr; PL_strstr; libVersionPoint; ;+ local: *; ;+}; ;+ ;+NSPR_4.2 { ;+ global: PL_strtok_r; ;+} NSPR_4.0; ;+ ;+NSPR_4.7 { ;+ global: PL_CreateLongOptState; ;+} NSPR_4.2; nspr-4.11/nspr/lib/libc/src/plc.rc0000644000000000000000000000366312623070344015114 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include #define MY_LIBNAME "plc" #define MY_FILEDESCRIPTION "PLC Library" #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG #else #define MY_DEBUG_STR "" #define MY_FILEFLAGS_1 0x0L #endif #if PR_BETA #define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE #else #define MY_FILEFLAGS_2 MY_FILEFLAGS_1 #endif #ifdef WINNT #define MY_FILEOS VOS_NT_WINDOWS32 #define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR #else #define MY_FILEOS VOS__WINDOWS32 #define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR #endif ///////////////////////////////////////////////////////////////////////////// // // Version-information resource // VS_VERSION_INFO VERSIONINFO FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS MY_FILEFLAGS_2 FILEOS MY_FILEOS FILETYPE VFT_DLL FILESUBTYPE 0x0L // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" // Lang=US English, CharSet=Unicode BEGIN VALUE "CompanyName", "Mozilla Foundation\0" VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END nspr-4.11/nspr/lib/libc/src/plerror.c0000644000000000000000000000221012623070344015624 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File:plerror.c ** Description: Simple routine to print translate the calling thread's ** error numbers and print them to "syserr". */ #include "plerror.h" #include "prprf.h" #include "prerror.h" PR_IMPLEMENT(void) PL_FPrintError(PRFileDesc *fd, const char *msg) { PRErrorCode error = PR_GetError(); PRInt32 oserror = PR_GetOSError(); const char *name = PR_ErrorToName(error); if (NULL != msg) PR_fprintf(fd, "%s: ", msg); if (NULL == name) PR_fprintf( fd, " (%d)OUT OF RANGE, oserror = %d\n", error, oserror); else PR_fprintf( fd, "%s(%d), oserror = %d\n", name, error, oserror); } /* PL_FPrintError */ PR_IMPLEMENT(void) PL_PrintError(const char *msg) { static PRFileDesc *fd = NULL; if (NULL == fd) fd = PR_GetSpecialFD(PR_StandardError); PL_FPrintError(fd, msg); } /* PL_PrintError */ /* plerror.c */ nspr-4.11/nspr/lib/libc/src/plgetopt.c0000644000000000000000000001714712623070344016014 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: plgetopt.c ** Description: utilities to parse argc/argv */ #include "prmem.h" #include "prlog.h" #include "prerror.h" #include "plstr.h" #include "plgetopt.h" #include static char static_Nul = 0; struct PLOptionInternal { const char *options; /* client options list specification */ PRIntn argc; /* original number of arguments */ char **argv; /* vector of pointers to arguments */ PRIntn xargc; /* which one we're processing now */ const char *xargv; /* where within *argv[xargc] */ PRIntn minus; /* do we already have the '-'? */ const PLLongOpt *longOpts; /* Caller's array */ PRBool endOfOpts; /* have reached a "--" argument */ PRIntn optionsLen; /* is strlen(options) */ }; /* ** Create the state in which to parse the tokens. ** ** argc the sum of the number of options and their values ** argv the options and their values ** options vector of single character options w/ | w/o ': */ PR_IMPLEMENT(PLOptState*) PL_CreateOptState( PRIntn argc, char **argv, const char *options) { return PL_CreateLongOptState( argc, argv, options, NULL); } /* PL_CreateOptState */ PR_IMPLEMENT(PLOptState*) PL_CreateLongOptState( PRIntn argc, char **argv, const char *options, const PLLongOpt *longOpts) { PLOptState *opt = NULL; PLOptionInternal *internal; if (NULL == options) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return opt; } opt = PR_NEWZAP(PLOptState); if (NULL == opt) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return opt; } internal = PR_NEW(PLOptionInternal); if (NULL == internal) { PR_DELETE(opt); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } opt->option = 0; opt->value = NULL; opt->internal = internal; opt->longOption = 0; opt->longOptIndex = -1; internal->argc = argc; internal->argv = argv; internal->xargc = 0; internal->xargv = &static_Nul; internal->minus = 0; internal->options = options; internal->longOpts = longOpts; internal->endOfOpts = PR_FALSE; internal->optionsLen = PL_strlen(options); return opt; } /* PL_CreateLongOptState */ /* ** Destroy object created by CreateOptState() */ PR_IMPLEMENT(void) PL_DestroyOptState(PLOptState *opt) { PR_DELETE(opt->internal); PR_DELETE(opt); } /* PL_DestroyOptState */ PR_IMPLEMENT(PLOptStatus) PL_GetNextOpt(PLOptState *opt) { PLOptionInternal *internal = opt->internal; opt->longOption = 0; opt->longOptIndex = -1; /* ** If the current xarg points to nul, advance to the next ** element of the argv vector. If the vector index is equal ** to argc, we're out of arguments, so return an EOL. ** Note whether the first character of the new argument is ** a '-' and skip by it if it is. */ while (0 == *internal->xargv) { internal->xargc += 1; if (internal->xargc >= internal->argc) { opt->option = 0; opt->value = NULL; return PL_OPT_EOL; } internal->xargv = internal->argv[internal->xargc]; internal->minus = 0; if (!internal->endOfOpts && ('-' == *internal->xargv)) { internal->minus++; internal->xargv++; /* and consume */ if ('-' == *internal->xargv && internal->longOpts) { internal->minus++; internal->xargv++; if (0 == *internal->xargv) { internal->endOfOpts = PR_TRUE; } } } } /* ** If we already have a '-' or '--' in hand, xargv points to the next ** option. See if we can find a match in the list of possible ** options supplied. */ if (internal->minus == 2) { char * foundEqual = strchr(internal->xargv,'='); PRIntn optNameLen = foundEqual ? (foundEqual - internal->xargv) : strlen(internal->xargv); const PLLongOpt *longOpt = internal->longOpts; PLOptStatus result = PL_OPT_BAD; opt->option = 0; opt->value = NULL; for (; longOpt->longOptName; ++longOpt) { if (strncmp(longOpt->longOptName, internal->xargv, optNameLen)) continue; /* not a possible match */ if (strlen(longOpt->longOptName) != optNameLen) continue; /* not a match */ /* option name match */ opt->longOptIndex = longOpt - internal->longOpts; opt->longOption = longOpt->longOption; /* value is part of the current argv[] element if = was found */ /* note: this sets value even for long options that do not * require option if specified as --long=value */ if (foundEqual) { opt->value = foundEqual + 1; } else if (longOpt->valueRequired) { /* value is the next argv[] element, if any */ if (internal->xargc + 1 < internal->argc) { opt->value = internal->argv[++(internal->xargc)]; } /* missing value */ else { break; /* return PL_OPT_BAD */ } } result = PL_OPT_OK; break; } internal->xargv = &static_Nul; /* consume this */ return result; } if (internal->minus) { PRIntn cop; PRIntn eoo = internal->optionsLen; for (cop = 0; cop < eoo; ++cop) { if (internal->options[cop] == *internal->xargv) { opt->option = *internal->xargv++; opt->longOption = opt->option & 0xff; /* ** if options indicates that there's an associated ** value, it must be provided, either as part of this ** argv[] element or as the next one */ if (':' == internal->options[cop + 1]) { /* value is part of the current argv[] element */ if (0 != *internal->xargv) { opt->value = internal->xargv; } /* value is the next argv[] element, if any */ else if (internal->xargc + 1 < internal->argc) { opt->value = internal->argv[++(internal->xargc)]; } /* missing value */ else { return PL_OPT_BAD; } internal->xargv = &static_Nul; internal->minus = 0; } else opt->value = NULL; return PL_OPT_OK; } } internal->xargv += 1; /* consume that option */ return PL_OPT_BAD; } /* ** No '-', so it must be a standalone value. The option is nul. */ opt->value = internal->argv[internal->xargc]; internal->xargv = &static_Nul; opt->option = 0; return PL_OPT_OK; } /* PL_GetNextOpt */ /* plgetopt.c */ nspr-4.11/nspr/lib/libc/src/plvrsion.c0000644000000000000000000000611712623070344016025 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include "prvrsion.h" /************************************************************************/ /**************************IDENTITY AND VERSIONING***********************/ /************************************************************************/ #include "_pl_bld.h" #if !defined(_BUILD_TIME) #ifdef HAVE_LONG_LONG #define _BUILD_TIME 0 #else #define _BUILD_TIME {0, 0} #endif #endif #if !defined(_BUILD_STRING) #define _BUILD_STRING "" #endif #if !defined(_PRODUCTION) #define _PRODUCTION "" #endif #if defined(DEBUG) #define _DEBUG_STRING " (debug)" #else #define _DEBUG_STRING "" #endif /* * A trick to expand the PR_VMAJOR macro before concatenation. */ #define CONCAT(x, y) x ## y #define CONCAT2(x, y) CONCAT(x, y) #define VERSION_DESC_NAME CONCAT2(prVersionDescription_libplc, PR_VMAJOR) PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */ /* vMajor */ PR_VMAJOR, /* NSPR's version number */ /* vMinor */ PR_VMINOR, /* and minor version */ /* vPatch */ PR_VPATCH, /* and patch */ /* beta */ PR_BETA, /* beta build boolean */ #if defined(DEBUG) /* debug */ PR_TRUE, /* a debug build */ #else /* debug */ PR_FALSE, /* an optomized build */ #endif /* special */ PR_FALSE, /* they're all special, but ... */ /* filename */ _PRODUCTION, /* the produced library name */ /* description */ "Portable runtime", /* what we are */ /* security */ "N/A", /* not applicable here */ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved", /* comment */ "http://www.mozilla.org/MPL/", /* specialString */ "" }; #ifdef XP_UNIX /* * Version information for the 'ident' and 'what commands * * NOTE: the first component of the concatenated rcsid string * must not end in a '$' to prevent rcs keyword substitution. */ static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING " $"; static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING; #endif /* XP_UNIX */ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() { #ifdef XP_UNIX /* * Add dummy references to rcsid and sccsid to prevent them * from being optimized away as unused variables. */ const char *dummy; dummy = rcsid; dummy = sccsid; #endif return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* plvrsion.c */ nspr-4.11/nspr/lib/libc/src/strcase.c0000644000000000000000000001270412623070344015614 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include static const unsigned char uc[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', '\177', 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 }; PR_IMPLEMENT(PRIntn) PL_strcasecmp(const char *a, const char *b) { const unsigned char *ua = (const unsigned char *)a; const unsigned char *ub = (const unsigned char *)b; if( ((const char *)0 == a) || (const char *)0 == b ) return (PRIntn)(a-b); while( (uc[*ua] == uc[*ub]) && ('\0' != *a) ) { a++; ua++; ub++; } return (PRIntn)(uc[*ua] - uc[*ub]); } PR_IMPLEMENT(PRIntn) PL_strncasecmp(const char *a, const char *b, PRUint32 max) { const unsigned char *ua = (const unsigned char *)a; const unsigned char *ub = (const unsigned char *)b; if( ((const char *)0 == a) || (const char *)0 == b ) return (PRIntn)(a-b); while( max && (uc[*ua] == uc[*ub]) && ('\0' != *a) ) { a++; ua++; ub++; max--; } if( 0 == max ) return (PRIntn)0; return (PRIntn)(uc[*ua] - uc[*ub]); } PR_IMPLEMENT(char *) PL_strcasestr(const char *big, const char *little) { PRUint32 ll; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; ll = strlen(little); for( ; *big; big++ ) /* obvious improvement available here */ if( 0 == PL_strncasecmp(big, little, ll) ) return (char *)big; return (char *)0; } PR_IMPLEMENT(char *) PL_strcaserstr(const char *big, const char *little) { const char *p; PRUint32 bl, ll; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; bl = strlen(big); ll = strlen(little); if( bl < ll ) return (char *)0; p = &big[ bl - ll ]; for( ; p >= big; p-- ) /* obvious improvement available here */ if( 0 == PL_strncasecmp(p, little, ll) ) return (char *)p; return (char *)0; } PR_IMPLEMENT(char *) PL_strncasestr(const char *big, const char *little, PRUint32 max) { PRUint32 ll; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; ll = strlen(little); if( ll > max ) return (char *)0; max -= ll; max++; for( ; max && *big; big++, max-- ) /* obvious improvement available here */ if( 0 == PL_strncasecmp(big, little, ll) ) return (char *)big; return (char *)0; } PR_IMPLEMENT(char *) PL_strncaserstr(const char *big, const char *little, PRUint32 max) { const char *p; PRUint32 ll; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; ll = strlen(little); for( p = big; max && *p; p++, max-- ) ; p -= ll; if( p < big ) return (char *)0; for( ; p >= big; p-- ) /* obvious improvement available here */ if( 0 == PL_strncasecmp(p, little, ll) ) return (char *)p; return (char *)0; } nspr-4.11/nspr/lib/libc/src/strcat.c0000644000000000000000000000215312623070344015445 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include PR_IMPLEMENT(char *) PL_strcat(char *dest, const char *src) { if( ((char *)0 == dest) || ((const char *)0 == src) ) return dest; return strcat(dest, src); } PR_IMPLEMENT(char *) PL_strncat(char *dest, const char *src, PRUint32 max) { char *rv; if( ((char *)0 == dest) || ((const char *)0 == src) || (0 == max) ) return dest; for( rv = dest; *dest; dest++ ) ; (void)PL_strncpy(dest, src, max); return rv; } PR_IMPLEMENT(char *) PL_strcatn(char *dest, PRUint32 max, const char *src) { char *rv; PRUint32 dl; if( ((char *)0 == dest) || ((const char *)0 == src) ) return dest; for( rv = dest, dl = 0; *dest; dest++, dl++ ) ; if( max <= dl ) return rv; (void)PL_strncpyz(dest, src, max-dl); return rv; } nspr-4.11/nspr/lib/libc/src/strchr.c0000644000000000000000000000236012623070344015452 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include PR_IMPLEMENT(char *) PL_strchr(const char *s, char c) { if( (const char *)0 == s ) return (char *)0; return strchr(s, c); } PR_IMPLEMENT(char *) PL_strrchr(const char *s, char c) { if( (const char *)0 == s ) return (char *)0; return strrchr(s, c); } PR_IMPLEMENT(char *) PL_strnchr(const char *s, char c, PRUint32 n) { if( (const char *)0 == s ) return (char *)0; for( ; n && *s; s++, n-- ) if( *s == c ) return (char *)s; if( ((char)0 == c) && (n > 0) && ((char)0 == *s) ) return (char *)s; return (char *)0; } PR_IMPLEMENT(char *) PL_strnrchr(const char *s, char c, PRUint32 n) { const char *p; if( (const char *)0 == s ) return (char *)0; for( p = s; n && *p; p++, n-- ) ; if( ((char)0 == c) && (n > 0) && ((char)0 == *p) ) return (char *)p; for( p--; p >= s; p-- ) if( *p == c ) return (char *)p; return (char *)0; } nspr-4.11/nspr/lib/libc/src/strcmp.c0000644000000000000000000000133212623070344015453 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include PR_IMPLEMENT(PRIntn) PL_strcmp(const char *a, const char *b) { if( ((const char *)0 == a) || (const char *)0 == b ) return (PRIntn)(a-b); return (PRIntn)strcmp(a, b); } PR_IMPLEMENT(PRIntn) PL_strncmp(const char *a, const char *b, PRUint32 max) { if( ((const char *)0 == a) || (const char *)0 == b ) return (PRIntn)(a-b); return (PRIntn)strncmp(a, b, (size_t)max); } nspr-4.11/nspr/lib/libc/src/strcpy.c0000644000000000000000000000242212623070344015470 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include PR_IMPLEMENT(char *) PL_strcpy(char *dest, const char *src) { if( ((char *)0 == dest) || ((const char *)0 == src) ) return (char *)0; return strcpy(dest, src); } PR_IMPLEMENT(char *) PL_strncpy(char *dest, const char *src, PRUint32 max) { char *rv; if( (char *)0 == dest ) return (char *)0; if( (const char *)0 == src ) return (char *)0; for( rv = dest; max && ((*dest = *src) != 0); dest++, src++, max-- ) ; #ifdef JLRU /* XXX I (wtc) think the -- and ++ operators should be postfix. */ while( --max ) *++dest = '\0'; #endif /* JLRU */ return rv; } PR_IMPLEMENT(char *) PL_strncpyz(char *dest, const char *src, PRUint32 max) { char *rv; if( (char *)0 == dest ) return (char *)0; if( (const char *)0 == src ) return (char *)0; if( 0 == max ) return (char *)0; for( rv = dest, max--; max && ((*dest = *src) != 0); dest++, src++, max-- ) ; *dest = '\0'; return rv; } nspr-4.11/nspr/lib/libc/src/strdup.c0000644000000000000000000000170512623070344015470 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include "prmem.h" #include PR_IMPLEMENT(char *) PL_strdup(const char *s) { char *rv; size_t n; if( (const char *)0 == s ) s = ""; n = strlen(s) + 1; rv = (char *)malloc(n); if( (char *)0 == rv ) return rv; (void)memcpy(rv, s, n); return rv; } PR_IMPLEMENT(void) PL_strfree(char *s) { free(s); } PR_IMPLEMENT(char *) PL_strndup(const char *s, PRUint32 max) { char *rv; size_t l; if( (const char *)0 == s ) s = ""; l = PL_strnlen(s, max); rv = (char *)malloc(l+1); if( (char *)0 == rv ) return rv; (void)memcpy(rv, s, l); rv[l] = '\0'; return rv; } nspr-4.11/nspr/lib/libc/src/strlen.c0000644000000000000000000000202512623070344015452 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include "prtypes.h" #include "prlog.h" #include PR_IMPLEMENT(PRUint32) PL_strlen(const char *str) { size_t l; if( (const char *)0 == str ) return 0; l = strlen(str); /* error checking in case we have a 64-bit platform -- make sure * we don't have ultra long strings that overflow an int32 */ if( sizeof(PRUint32) < sizeof(size_t) ) { if( l > PR_INT32_MAX ) PR_Assert("l <= PR_INT32_MAX", __FILE__, __LINE__); } return (PRUint32)l; } PR_IMPLEMENT(PRUint32) PL_strnlen(const char *str, PRUint32 max) { register const char *s; if( (const char *)0 == str ) return 0; for( s = str; max && *s; s++, max-- ) ; return (PRUint32)(s - str); } nspr-4.11/nspr/lib/libc/src/strpbrk.c0000644000000000000000000000312212623070344015631 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include PR_IMPLEMENT(char *) PL_strpbrk(const char *s, const char *list) { if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0; return strpbrk(s, list); } PR_IMPLEMENT(char *) PL_strprbrk(const char *s, const char *list) { const char *p; const char *r; if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0; for( r = s; *r; r++ ) ; for( r--; r >= s; r-- ) for( p = list; *p; p++ ) if( *r == *p ) return (char *)r; return (char *)0; } PR_IMPLEMENT(char *) PL_strnpbrk(const char *s, const char *list, PRUint32 max) { const char *p; if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0; for( ; max && *s; s++, max-- ) for( p = list; *p; p++ ) if( *s == *p ) return (char *)s; return (char *)0; } PR_IMPLEMENT(char *) PL_strnprbrk(const char *s, const char *list, PRUint32 max) { const char *p; const char *r; if( ((const char *)0 == s) || ((const char *)0 == list) ) return (char *)0; for( r = s; max && *r; r++, max-- ) ; for( r--; r >= s; r-- ) for( p = list; *p; p++ ) if( *r == *p ) return (char *)r; return (char *)0; } nspr-4.11/nspr/lib/libc/src/strstr.c0000644000000000000000000000427712623070344015517 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include PR_IMPLEMENT(char *) PL_strstr(const char *big, const char *little) { if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; return strstr(big, little); } PR_IMPLEMENT(char *) PL_strrstr(const char *big, const char *little) { const char *p; size_t ll; size_t bl; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; ll = strlen(little); bl = strlen(big); if( bl < ll ) return (char *)0; p = &big[ bl - ll ]; for( ; p >= big; p-- ) if( *little == *p ) if( 0 == strncmp(p, little, ll) ) return (char *)p; return (char *)0; } PR_IMPLEMENT(char *) PL_strnstr(const char *big, const char *little, PRUint32 max) { size_t ll; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; ll = strlen(little); if( ll > (size_t)max ) return (char *)0; max -= (PRUint32)ll; max++; for( ; max && *big; big++, max-- ) if( *little == *big ) if( 0 == strncmp(big, little, ll) ) return (char *)big; return (char *)0; } PR_IMPLEMENT(char *) PL_strnrstr(const char *big, const char *little, PRUint32 max) { const char *p; size_t ll; if( ((const char *)0 == big) || ((const char *)0 == little) ) return (char *)0; if( ((char)0 == *big) || ((char)0 == *little) ) return (char *)0; ll = strlen(little); for( p = big; max && *p; p++, max-- ) ; p -= ll; if( p < big ) return (char *)0; for( ; p >= big; p-- ) if( *little == *p ) if( 0 == strncmp(p, little, ll) ) return (char *)p; return (char *)0; } nspr-4.11/nspr/lib/libc/src/strtok.c0000644000000000000000000000221112623070344015466 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" PR_IMPLEMENT(char *) PL_strtok_r(char *s1, const char *s2, char **lasts) { const char *sepp; int c, sc; char *tok; if( s1 == NULL ) { if( *lasts == NULL ) return NULL; s1 = *lasts; } for( ; (c = *s1) != 0; s1++ ) { for( sepp = s2 ; (sc = *sepp) != 0 ; sepp++ ) { if( c == sc ) break; } if( sc == 0 ) break; } if( c == 0 ) { *lasts = NULL; return NULL; } tok = s1++; for( ; (c = *s1) != 0; s1++ ) { for( sepp = s2; (sc = *sepp) != 0; sepp++ ) { if( c == sc ) { *s1++ = '\0'; *lasts = s1; return tok; } } } *lasts = NULL; return tok; } nspr-4.11/nspr/lib/prstreams/.cvsignore0000644000000000000000000000001112623070344016310 0ustar 00000000000000Makefile nspr-4.11/nspr/lib/prstreams/Makefile.in0000644000000000000000000000622212623070344016367 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifeq ($(OS_ARCH), IRIX) ifneq ($(OS_RELEASE),5.3) CCC_ONLY_FLAGS += -exceptions endif endif ifeq ($(OS_ARCH), BeOS) CFLAGS += -frtti -fexceptions endif INCLUDES = -I$(dist_includedir) HEADERS = $(wildcard $(srcdir)/*.h) CSRCS = \ plvrsion.c \ $(NULL) CXXSRCS = \ prstrms.cpp \ $(NULL) OBJS = $(addprefix $(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX)) $(CXXSRCS:.cpp=.$(OBJ_SUFFIX))) ifeq ($(OS_ARCH), WINNT) RES=$(OBJDIR)/prstrms.res RESNAME=prstrms.rc OS_LIBS = user32.lib else ifeq ($(OS_ARCH),OS2) OS_LIBS = -lstdcpp else ifeq ($(OS_ARCH), AIX) ifeq ($(OS_RELEASE), 4.1) ifeq ($(CLASSIC_NSPR),1) OS_LIBS += -lC -lc else OS_LIBS += -lC_r -lc_r endif else # makeC++SharedLib(_r) is in either /usr/lpp/xlC/bin # or /usr/ibmcxx/bin. ifeq ($(CLASSIC_NSPR),1) MKSHLIB = makeC++SharedLib -p 0 else MKSHLIB = makeC++SharedLib_r -p 0 endif OS_LIBS += -ldl endif endif endif endif ifeq ($(OS_ARCH),BeOS) OS_LIBS = -lstdc++.r4 endif ifeq ($(OS_ARCH), UNIXWARE) OS_LIBS += -lC endif EXTRA_LIBS = $(LIBNSPR) # On SCOOS, we can't link with extra libraries when # we build a shared library. If we do so, the linker doesn't # complain, but we would run into weird problems at run-time. # Therefore on these platforms, we link just the object files. ifeq ($(OS_ARCH),SCOOS) EXTRA_LIBS = endif ifdef RESOLVE_LINK_SYMBOLS EXTRA_LIBS += $(OS_LIBS) endif LIBRARY_NAME = prstrms LIBRARY_VERSION = $(MOD_MAJOR_VERSION) RELEASE_HEADERS = $(HEADERS) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR) RELEASE_LIBS = $(TARGETS) include $(topsrcdir)/config/rules.mk # # Version information generation (begin) # ECHO = echo TINC = $(OBJDIR)/_pl_bld.h PROD = $(notdir $(SHARED_LIBRARY)) NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now SH_DATE = $(shell date "+%Y-%m-%d %T") SH_NOW = $(shell $(NOW)) ifeq ($(OS_ARCH), WINNT) SUF = i64 else SUF = LL endif $(TINC): @$(MAKE_OBJDIR) @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC) @if test ! -z "$(SH_NOW)"; then \ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \ else \ true; \ fi @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC) $(OBJDIR)/plvrsion.$(OBJ_SUFFIX): plvrsion.c $(TINC) ifeq ($(OS_ARCH), WINNT) $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< else $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< endif # # Version information generation (end) # export:: $(TARGETS) $(HEADERS) $(INSTALL) -m 444 $(HEADERS) $(dist_includedir) $(INSTALL) -m 444 $(TARGETS) $(dist_libdir) ifeq ($(OS_ARCH),OS2) $(INSTALL) -m 444 $(TARGETS) $(dist_bindir) endif ifeq ($(OS_ARCH),HP-UX) ifdef SHARED_LIBRARY $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir) endif endif nspr-4.11/nspr/lib/prstreams/plvrsion.c0000644000000000000000000000612312623070344016342 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include "prvrsion.h" /************************************************************************/ /**************************IDENTITY AND VERSIONING***********************/ /************************************************************************/ #include "_pl_bld.h" #if !defined(_BUILD_TIME) #ifdef HAVE_LONG_LONG #define _BUILD_TIME 0 #else #define _BUILD_TIME {0, 0} #endif #endif #if !defined(_BUILD_STRING) #define _BUILD_STRING "" #endif #if !defined(_PRODUCTION) #define _PRODUCTION "" #endif #if defined(DEBUG) #define _DEBUG_STRING " (debug)" #else #define _DEBUG_STRING "" #endif /* * A trick to expand the PR_VMAJOR macro before concatenation. */ #define CONCAT(x, y) x ## y #define CONCAT2(x, y) CONCAT(x, y) #define VERSION_DESC_NAME CONCAT2(prVersionDescription_libprstrms, PR_VMAJOR) PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */ /* vMajor */ PR_VMAJOR, /* NSPR's version number */ /* vMinor */ PR_VMINOR, /* and minor version */ /* vPatch */ PR_VPATCH, /* and patch */ /* beta */ PR_BETA, /* beta build boolean */ #if defined(DEBUG) /* debug */ PR_TRUE, /* a debug build */ #else /* debug */ PR_FALSE, /* an optomized build */ #endif /* special */ PR_FALSE, /* they're all special, but ... */ /* filename */ _PRODUCTION, /* the produced library name */ /* description */ "Portable runtime", /* what we are */ /* security */ "N/A", /* not applicable here */ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved", /* comment */ "http://www.mozilla.org/MPL/", /* specialString */ "" }; #ifdef XP_UNIX /* * Version information for the 'ident' and 'what commands * * NOTE: the first component of the concatenated rcsid string * must not end in a '$' to prevent rcs keyword substitution. */ static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING " $"; static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING; #endif /* XP_UNIX */ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint() { #ifdef XP_UNIX /* * Add dummy references to rcsid and sccsid to prevent them * from being optimized away as unused variables. */ const char *dummy; dummy = rcsid; dummy = sccsid; #endif return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* plvrsion.c */ nspr-4.11/nspr/lib/prstreams/prstrms.cpp0000644000000000000000000002513712623070344016546 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Robin J. Maxwell 11-22-96 * Fredrik Roubert 2010-07-23 * Matt Austern 2010-07-23 */ #include "prstrms.h" #include #include #include #include using std::ios_base; using std::iostream; using std::istream; using std::nothrow; using std::ostream; using std::streambuf; using std::streamsize; PRfilebuf::PRfilebuf(): _fd(NULL), _opened(false), _allocated(false), _unbuffered(false), _user_buf(false), _buf_base(NULL), _buf_end(NULL) { } PRfilebuf::PRfilebuf(PRFileDesc *fd): _fd(fd), _opened(false), _allocated(false), _unbuffered(false), _user_buf(false), _buf_base(NULL), _buf_end(NULL) { } PRfilebuf::PRfilebuf(PRFileDesc *fd, char_type *ptr, streamsize len): _fd(fd), _opened(false), _allocated(false), _unbuffered(false), _user_buf(false), _buf_base(NULL), _buf_end(NULL) { setbuf(ptr, len); } PRfilebuf::~PRfilebuf() { if (_opened) { close(); } else { sync(); } if (_allocated) { delete _buf_base; } } PRfilebuf *PRfilebuf::open( const char *name, ios_base::openmode flags, PRIntn mode) { if (_fd != NULL) { return NULL; // Error if already open. } // Translate flags argument. PRIntn prflags = 0; bool ate = (flags & ios_base::ate) != 0; flags &= ~(ios_base::ate | ios_base::binary); // TODO: The flag PR_CREATE_FILE should probably be used for the cases // (out), (out|app), (out|trunc) and (in|out|trunc) as the C++ standard // specifies that these cases should open files 'as if by using fopen with // "w"'. But adding that flag here will cause the unit test to leave files // behind after running (which might or might not be an error in the unit // test) so the matter needs further investigation before any changes are // made. The old prstreams implementation used the non-standard flag // ios::nocreate to control the use of PR_CREATE_FILE. if (flags == (ios_base::out)) { prflags = PR_WRONLY | PR_TRUNCATE; } else if (flags == (ios_base::out | ios_base::app)) { prflags = PR_RDWR | PR_APPEND; } else if (flags == (ios_base::out | ios_base::trunc)) { prflags = PR_WRONLY | PR_TRUNCATE; } else if (flags == (ios_base::in)) { prflags = PR_RDONLY; } else if (flags == (ios_base::in | ios_base::out)) { prflags = PR_RDWR; } else if (flags == (ios_base::in | ios_base::out | ios_base::trunc)) { prflags = PR_RDWR | PR_TRUNCATE; } else { return NULL; // Unrecognized flag combination. } if ((_fd = PR_Open(name, prflags, mode)) == NULL) { return NULL; } _opened = true; if (ate && seekoff(0, ios_base::end, flags) == pos_type(traits_type::eof())) { close(); return NULL; } return this; } PRfilebuf *PRfilebuf::attach(PRFileDesc *fd) { if (_fd != NULL) { return NULL; // Error if already open. } _opened = false; _fd = fd; return this; } PRfilebuf *PRfilebuf::close() { if (_fd == NULL) return NULL; int status = sync(); if (PR_Close(_fd) == PR_FAILURE || traits_type::eq_int_type(status, traits_type::eof())) { return NULL; } _fd = NULL; return this; } streambuf *PRfilebuf::setbuf(char_type *ptr, streamsize len) { if (is_open() && _buf_end) { return NULL; } if (!ptr || len <= 0) { _unbuffered = true; } else { setb(ptr, ptr + len, false); } return this; } streambuf::pos_type PRfilebuf::seekoff( off_type offset, ios_base::seekdir dir, ios_base::openmode /*flags*/) { if (PR_GetDescType(_fd) != PR_DESC_FILE) { return traits_type::eof(); } PRSeekWhence whence; PRInt64 pos; switch (dir) { case ios_base::beg: whence = PR_SEEK_SET; break; case ios_base::cur: whence = PR_SEEK_CUR; break; case ios_base::end: whence = PR_SEEK_END; break; default: return traits_type::eof(); // This should never happen. } if (traits_type::eq_int_type(sync(), traits_type::eof())) { return traits_type::eof(); } if ((pos = PR_Seek64(_fd, offset, whence)) == -1) { return traits_type::eof(); } return pos; } int PRfilebuf::sync() { if (_fd == NULL) { return traits_type::eof(); } if (!_unbuffered) { // Sync write area. PRInt32 waiting; if ((waiting = pptr() - pbase()) != 0) { PRInt32 nout; if ((nout = PR_Write(_fd, pbase(), waiting)) != waiting) { if (nout > 0) { // Should set _pptr -= nout. pbump(-nout); memmove(pbase(), pbase() + nout, waiting - nout); } return traits_type::eof(); } } setp(NULL, NULL); // Empty put area. if (PR_GetDescType(_fd) == PR_DESC_FILE) { // Sockets can't seek; don't need this. PROffset64 avail; if ((avail = in_avail()) > 0) { if (PR_Seek64(_fd, -avail, PR_SEEK_CUR) != -1) { return traits_type::eof(); } } } setg(NULL, NULL, NULL); // Empty get area. } return 0; } streambuf::int_type PRfilebuf::underflow() { PRInt32 count; char_type byte; if (gptr() != NULL && gptr() < egptr()) { return traits_type::to_int_type(*gptr()); } // Make sure there is a reserve area. if (!_unbuffered && _buf_base == NULL && !allocate()) { return traits_type::eof(); } // Sync before new buffer created below. if (traits_type::eq_int_type(sync(), traits_type::eof())) { return traits_type::eof(); } if (_unbuffered) { if (PR_Read(_fd, &byte, 1) <= 0) { return traits_type::eof(); } return traits_type::to_int_type(byte); } if ((count = PR_Read(_fd, _buf_base, _buf_end - _buf_base)) <= 0) { return traits_type::eof(); // Reached EOF. } setg(_buf_base, _buf_base, _buf_base + count); return traits_type::to_int_type(*gptr()); } streambuf::int_type PRfilebuf::overflow(int_type c) { // Make sure there is a reserve area. if (!_unbuffered && _buf_base == NULL && !allocate()) { return traits_type::eof(); } // Sync before new buffer created below. if (traits_type::eq_int_type(sync(), traits_type::eof())) { return traits_type::eof(); } if (!_unbuffered) { setp(_buf_base, _buf_end); } if (!traits_type::eq_int_type(c, traits_type::eof())) { // Extract the byte to be written. // (Required on big-endian architectures.) char_type byte = traits_type::to_char_type(c); if (!_unbuffered && pptr() < epptr()) { // Guard against recursion. return sputc(byte); } else { if (PR_Write(_fd, &byte, 1) != 1) { return traits_type::eof(); } } } return traits_type::not_eof(c); } bool PRfilebuf::allocate() { char_type *buf = new(nothrow) char_type[BUFSIZ]; if (buf == NULL) { return false; } setb(buf, buf + BUFSIZ, true); return true; } void PRfilebuf::setb(char_type *buf_base, char_type *buf_end, bool user_buf) { if (_buf_base && !_user_buf) { delete[] _buf_base; } _buf_base = buf_base; _buf_end = buf_end; _user_buf = user_buf; } PRifstream::PRifstream(): istream(NULL), _filebuf() { init(&_filebuf); } PRifstream::PRifstream(PRFileDesc *fd): istream(NULL), _filebuf(fd) { init(&_filebuf); } PRifstream::PRifstream(PRFileDesc *fd, char_type *ptr, streamsize len): istream(NULL), _filebuf(fd, ptr, len) { init(&_filebuf); } PRifstream::PRifstream(const char *name, openmode flags, PRIntn mode): istream(NULL), _filebuf() { init(&_filebuf); if (!_filebuf.open(name, flags | in, mode)) { setstate(failbit); } } PRifstream::~PRifstream() { } void PRifstream::open(const char *name, openmode flags, PRIntn mode) { if (is_open() || !_filebuf.open(name, flags | in, mode)) { setstate(failbit); } } void PRifstream::attach(PRFileDesc *fd) { if (!_filebuf.attach(fd)) { setstate(failbit); } } void PRifstream::close() { if (_filebuf.close() == NULL) { setstate(failbit); } } PRofstream::PRofstream(): ostream(NULL), _filebuf() { init(&_filebuf); } PRofstream::PRofstream(PRFileDesc *fd): ostream(NULL), _filebuf(fd) { init(&_filebuf); } PRofstream::PRofstream(PRFileDesc *fd, char_type *ptr, streamsize len): ostream(NULL), _filebuf(fd, ptr, len) { init(&_filebuf); } PRofstream::PRofstream(const char *name, openmode flags, PRIntn mode): ostream(NULL), _filebuf() { init(&_filebuf); if (!_filebuf.open(name, flags | out, mode)) { setstate(failbit); } } PRofstream::~PRofstream() { } void PRofstream::open(const char *name, openmode flags, PRIntn mode) { if (is_open() || !_filebuf.open(name, flags | out, mode)) { setstate(failbit); } } void PRofstream::attach(PRFileDesc *fd) { if (!_filebuf.attach(fd)) { setstate(failbit); } } void PRofstream::close() { if (_filebuf.close() == NULL) { setstate(failbit); } } PRfstream::PRfstream(): iostream(NULL), _filebuf() { init(&_filebuf); } PRfstream::PRfstream(PRFileDesc *fd): iostream(NULL), _filebuf(fd) { init(&_filebuf); } PRfstream::PRfstream(PRFileDesc *fd, char_type *ptr, streamsize len): iostream(NULL), _filebuf(fd, ptr, len) { init(&_filebuf); } PRfstream::PRfstream(const char *name, openmode flags, PRIntn mode): iostream(NULL), _filebuf() { init(&_filebuf); if (!_filebuf.open(name, flags | in | out, mode)) { setstate(failbit); } } PRfstream::~PRfstream() { } void PRfstream::open(const char *name, openmode flags, PRIntn mode) { if (is_open() || !_filebuf.open(name, flags | in | out, mode)) { setstate(failbit); } } void PRfstream::attach(PRFileDesc *fd) { if (!_filebuf.attach(fd)) { setstate(failbit); } } void PRfstream::close() { if (_filebuf.close() == NULL) { setstate(failbit); } } nspr-4.11/nspr/lib/prstreams/prstrms.h0000644000000000000000000000730512623070344016210 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Robin J. Maxwell 11-22-96 * Fredrik Roubert 2010-07-23 * Matt Austern 2010-07-23 */ #ifndef _PRSTRMS_H #define _PRSTRMS_H #include #include #include #include #include "prio.h" #ifdef _MSC_VER // http://support.microsoft.com/kb/q168958/ class PR_IMPLEMENT(std::_Mutex); class PR_IMPLEMENT(std::ios_base); #endif class PR_IMPLEMENT(PRfilebuf): public std::streambuf { public: PRfilebuf(); PRfilebuf(PRFileDesc *fd); PRfilebuf(PRFileDesc *fd, char_type *ptr, std::streamsize len); virtual ~PRfilebuf(); bool is_open() const { return _fd != NULL; } PRfilebuf *open( const char *name, std::ios_base::openmode flags, PRIntn mode); PRfilebuf *attach(PRFileDesc *fd); PRfilebuf *close(); protected: virtual std::streambuf *setbuf(char_type *ptr, std::streamsize len); virtual pos_type seekoff( off_type offset, std::ios_base::seekdir dir, std::ios_base::openmode flags); virtual pos_type seekpos( pos_type pos, std::ios_base::openmode flags) { return seekoff(pos, std::ios_base::beg, flags); } virtual int sync(); virtual int_type underflow(); virtual int_type overflow(int_type c = traits_type::eof()); // TODO: Override pbackfail(), showmanyc(), uflow(), xsgetn(), and xsputn(). private: bool allocate(); void setb(char_type *buf_base, char_type *buf_end, bool user_buf); PRFileDesc *_fd; bool _opened; bool _allocated; bool _unbuffered; bool _user_buf; char_type *_buf_base; char_type *_buf_end; }; class PR_IMPLEMENT(PRifstream): public std::istream { public: PRifstream(); PRifstream(PRFileDesc *fd); PRifstream(PRFileDesc *fd, char_type *ptr, std::streamsize len); PRifstream(const char *name, openmode flags = in, PRIntn mode = 0); virtual ~PRifstream(); PRfilebuf *rdbuf() const { return &_filebuf; } bool is_open() const { return _filebuf.is_open(); } void open(const char *name, openmode flags = in, PRIntn mode = 0); void attach(PRFileDesc *fd); void close(); private: mutable PRfilebuf _filebuf; }; class PR_IMPLEMENT(PRofstream): public std::ostream { public: PRofstream(); PRofstream(PRFileDesc *fd); PRofstream(PRFileDesc *fd, char_type *ptr, std::streamsize len); PRofstream(const char *name, openmode flags = out, PRIntn mode = 0); virtual ~PRofstream(); PRfilebuf *rdbuf() const { return &_filebuf; } bool is_open() const { return _filebuf.is_open(); } void open(const char *name, openmode flags = out, PRIntn mode = 0); void attach(PRFileDesc *fd); void close(); private: mutable PRfilebuf _filebuf; }; class PR_IMPLEMENT(PRfstream): public std::iostream { public: PRfstream(); PRfstream(PRFileDesc *fd); PRfstream(PRFileDesc *fd, char_type *ptr, std::streamsize len); PRfstream(const char *name, openmode flags = in | out, PRIntn mode = 0); virtual ~PRfstream(); PRfilebuf *rdbuf() const { return &_filebuf; } bool is_open() const { return _filebuf.is_open(); } void open(const char *name, openmode flags = in | out, PRIntn mode = 0); void attach(PRFileDesc *fd); void close(); private: mutable PRfilebuf _filebuf; }; #endif /* _PRSTRMS_H */ nspr-4.11/nspr/lib/prstreams/prstrms.rc0000644000000000000000000000367212623070344016370 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include #define MY_LIBNAME "prstrms" #define MY_FILEDESCRIPTION "PRSTRMS Library" #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG #else #define MY_DEBUG_STR "" #define MY_FILEFLAGS_1 0x0L #endif #if PR_BETA #define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE #else #define MY_FILEFLAGS_2 MY_FILEFLAGS_1 #endif #ifdef WINNT #define MY_FILEOS VOS_NT_WINDOWS32 #define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR #else #define MY_FILEOS VOS__WINDOWS32 #define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR #endif ///////////////////////////////////////////////////////////////////////////// // // Version-information resource // VS_VERSION_INFO VERSIONINFO FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS MY_FILEFLAGS_2 FILEOS MY_FILEOS FILETYPE VFT_DLL FILESUBTYPE 0x0L // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" // Lang=US English, CharSet=Unicode BEGIN VALUE "CompanyName", "Mozilla Foundation\0" VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END nspr-4.11/nspr/lib/prstreams/tests/testprstrm/.cvsignore0000644000000000000000000000001112623070344021701 0ustar 00000000000000Makefile nspr-4.11/nspr/lib/prstreams/tests/testprstrm/Makefile.in0000644000000000000000000001006612623070344021761 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CXXSRCS = \ testprstrm.cpp \ $(NULL) OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX))) ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) PROG_SUFFIX = .exe else PROG_SUFFIX = endif PROGS = $(addprefix $(OBJDIR)/, $(CXXSRCS:.cpp=$(PROG_SUFFIX))) TARGETS = $(PROGS) $(OBJS) INCLUDES = -I$(dist_includedir) # Setting the variables LDOPTS and LIBPR. We first initialize # them to the default values, then adjust them for some platforms. LDOPTS = -L$(dist_libdir) LIBPR = -lnspr$(MOD_MAJOR_VERSION) LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION) ifeq ($(OS_ARCH), WINNT) LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO ifeq ($(OS_TARGET), WIN95) LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPRSTRMS = $(dist_libdir)/prstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) else LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPRSTRMS = $(dist_libdir)/libprstrms$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) endif endif ifeq ($(OS_ARCH),OS2) LDOPTS += -Zomf -Zlinker /PM:VIO -lstdcpp endif ifneq ($(OS_ARCH), WINNT) PWD = $(shell pwd) endif ifeq ($(OS_ARCH), IRIX) LDOPTS += -rpath $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), OSF1) LDOPTS += -rpath $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), HP-UX) LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir) endif # AIX ifeq ($(OS_ARCH),AIX) LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1) LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr LIBPRSTRMS = -lprstrms$(MOD_MAJOR_VERSION)_shr else LDOPTS += -brtl EXTRA_LIBS = -ldl endif endif # Solaris ifeq ($(OS_ARCH), SunOS) ifdef NS_USE_GCC LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir) else LDOPTS += -R $(PWD)/$(dist_libdir) # CC on SunOS 5.5.x needs to link with -lpthread even though we already # linked with this system library when we built libnspr.so. ifdef USE_PTHREADS EXTRA_LIBS = -lpthread endif # USE_PTHREADS endif # NS_USE_GCC endif # SunOS ifeq ($(OS_ARCH), SCOOS) # SCO Unix needs to link against -lsocket again even though we # already linked with these system libraries when we built libnspr.so. EXTRA_LIBS = -lsocket # This hardcodes in the executable programs the directory to find # libnspr.so etc. at program startup. Equivalent to the -R or -rpath # option for ld on other platforms. export LD_RUN_PATH = $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), UNIXWARE) export LD_RUN_PATH = $(PWD)/$(dist_libdir) endif ##################################################### # # The rules # ##################################################### include $(topsrcdir)/config/rules.mk AIX_PRE_4_2 = 0 ifeq ($(OS_ARCH),AIX) ifneq ($(OS_RELEASE),4.2) ifneq ($(USE_PTHREADS), 1) #AIX_PRE_4_2 = 1 endif endif endif ifeq ($(AIX_PRE_4_2),1) # AIX releases prior to 4.2 need a special two-step linking hack # in order to both override the system select() and be able to # get at the original system select(). # # We use a pattern rule in ns/nspr20/config/rules.mk to generate # the .$(OBJ_SUFFIX) file from the .c source file, then do the # two-step linking hack below. $(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) rm -f $@ $(AIX_TMP) $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) rm -f $(AIX_TMP) else # All platforms that are not AIX pre-4.2. $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) ifeq ($(OS_ARCH), WINNT) link $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) ws2_32.lib -out:$@ else ifeq ($(OS_ARCH),OS2) $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPR) $(LIBPRSTRMS) $(OS_LIBS) $(EXTRA_LIBS) else $(CCC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPRSTRMS) $(EXTRA_LIBS) -o $@ endif endif endif export:: $(TARGETS) clean:: rm -f $(TARGETS) testlinker: echo $(LINK) nspr-4.11/nspr/lib/prstreams/tests/testprstrm/testprstrm.cpp0000644000000000000000000001024012623070344022641 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prstrms.h" #include "prinit.h" #include "prio.h" #include "prthread.h" #include #include #ifdef XP_UNIX #include #endif using std::cout; using std::endl; using std::ios; const unsigned int MaxCnt = 1; typedef struct threadarg { const char *mytag; } threadarg; void threadwork(threadarg *arg); void threadmain(void *mytag) { threadarg arg; arg.mytag = static_cast(mytag); threadwork(&arg); } void threadwork(threadarg *arg) { unsigned int i; char fname1[256]; char fname2[256]; strcpy(fname1, arg->mytag); strcpy(fname2, arg->mytag); strcat(fname2, "2"); PR_Delete(fname1); PR_Delete(fname2); PRfilebuf *fb[MaxCnt]; PRifstream *ifs[MaxCnt]; PRofstream *ofs[MaxCnt]; int mode = 0; #ifdef XP_UNIX mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; #endif // // Allocate a bunch cout << "Testing unused filebufs ----------------" << endl; for (i=0; i < MaxCnt; i++){ fb[i] = new PRfilebuf; } // Delete them for (i=0; i < MaxCnt; i++){ delete fb[i]; } cout << "Unused filebufs complete ---------------" << endl; // // Allocate a bunch cout << "Testing unused ifstream -----------------" << endl; for (i=0; i < MaxCnt; i++){ ifs[i] = new PRifstream; } // // Delete them for (i=0; i < MaxCnt; i++){ delete ifs[i]; } cout << "Unused ifstream complete ----------------" << endl; // // Allocate a bunch cout << "Testing unused ofstream -----------------" << endl; for (i=0; i < MaxCnt; i++){ ofs[i] = new PRofstream; } for (i=0; i < MaxCnt; i++){ *(ofs[i]) << "A"; // Write a bit delete ofs[i]; // Delete it. } cout << "Unused ofstream complete ----------------" << endl; cout << "Testing use of ofstream 1 (extra filebuf allocated) ---------" << endl; PRofstream *aos = new PRofstream(fname1, ios::out|ios::ate, mode); for (i=0; i < MaxCnt; i++){ for (int j=0; j < 8192; j++) *aos << "AaBbCcDdEeFfGg" << endl; fb[i] = new PRfilebuf; // Allocate as we go to hack at the heap } // // Delete the extra foo we allocated for (i=0; i < MaxCnt; i++){ delete fb[i]; } aos->flush(); // Explicit flush delete aos; cout << "Testing use of ofstream 1 complete (extra filebuf deleted) --" << endl; cout << "Testing use of ofstream 2 (extra filebuf allocated) ---------" << endl; PRofstream *aos2 = new PRofstream(fname2, ios::out, mode); for (i=0; i < MaxCnt; i++){ *aos2 << "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; } // Force flushing in the dtor delete aos2; cout << "Testing use of ofstream 2 complete (extra filebuf deleted) --" << endl; char line[1024]; cout << "Testing use of ifstream 1 (stack allocation) -------------" << endl; PRifstream ais(fname1); for (i=0; i < MaxCnt; i++){ ais >> line; } cout << "Testing use of ifstream 1 complete -----------------------" << endl; cout << "Testing use of ifstream 2 ----------------------" << endl; PRifstream *ais2 = new PRifstream(fname2); char achar; for (i=0; i < MaxCnt*10; i++){ *ais2 >> achar; } delete ais2; cout << "Testing use of ifstream 2 complete -------------" << endl; } #define STACKSIZE 1024*1024 int main() { PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 256); threadmain(const_cast("TestFile")); PRThread *thr1 = PR_CreateThread(PR_SYSTEM_THREAD, threadmain, const_cast("TestFile1"), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, STACKSIZE); PRThread *thr2 = PR_CreateThread(PR_SYSTEM_THREAD, threadmain, const_cast("TestFile2"), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, STACKSIZE); PRThread *thr3 = PR_CreateThread(PR_SYSTEM_THREAD, threadmain, const_cast("TestFile3"), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, STACKSIZE); PR_JoinThread(thr1); PR_JoinThread(thr2); PR_JoinThread(thr3); return 0; } nspr-4.11/nspr/lib/tests/.cvsignore0000644000000000000000000000001112623070344015432 0ustar 00000000000000Makefile nspr-4.11/nspr/lib/tests/Makefile.in0000644000000000000000000001020712623070344015507 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = \ arena.c \ base64t.c \ getopt.c \ string.c ifeq (,$(filter-out WINCE WINNT OS2,$(OS_ARCH))) CSRCS += arena.c endif ifeq (,$(filter-out WINCE WINNT OS2,$(OS_ARCH))) PROG_SUFFIX = .exe else PROG_SUFFIX = endif PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX))) TARGETS = $(PROGS) $(OBJS) INCLUDES = -I$(dist_includedir) # Setting the variables LDOPTS and LIBPR. We first initialize # them to the default values, then adjust them for some platforms. LDOPTS = -L$(dist_libdir) LIBPR = -lnspr$(MOD_MAJOR_VERSION) LIBPLC = -lplc$(MOD_MAJOR_VERSION) LIBPLDS = -lplds$(MOD_MAJOR_VERSION) ifeq (,$(filter-out WINCE WINNT, $(OS_ARCH))) LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO ifeq (,$(filter-out WIN95 WINCE WINMO, $(OS_TARGET))) LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPLC= $(dist_libdir)/plc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPLDS= $(dist_libdir)/plds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) else LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPLC= $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPLDS= $(dist_libdir)/libplds$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) endif endif ifeq ($(OS_ARCH),OS2) LDOPTS += -Zomf -Zlinker /PM:VIO endif ifneq ($(OS_ARCH), WINNT) PWD = $(shell pwd) endif ifeq ($(OS_ARCH), IRIX) LDOPTS += -rpath $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), Linux) ifeq ($(OS_RELEASE), 1.2) EXTRA_LIBS = -ldl else LDOPTS += -Xlinker -rpath $(PWD)/$(dist_libdir) ifeq ($(USE_PTHREADS),1) EXTRA_LIBS = -lpthread endif endif endif ifeq (,$(filter-out OpenBSD,$(OS_ARCH))) ifeq ($(USE_PTHREADS),1) EXTRA_LIBS = -lpthread endif endif ifeq ($(OS_ARCH), OSF1) LDOPTS += -rpath $(PWD)/$(dist_libdir) -lpthread endif ifeq ($(OS_ARCH), HP-UX) LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir) endif # AIX ifeq ($(OS_ARCH),AIX) LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr LIBPLC = -lplc$(MOD_MAJOR_VERSION)_shr endif # Solaris ifeq ($(OS_ARCH), SunOS) ifdef NS_USE_GCC LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir) else LDOPTS += -R $(PWD)/$(dist_libdir) endif # SunOS 5.5 needs to link with -lpthread, even though we already # linked with this system library when we built libnspr.so. ifeq ($(OS_RELEASE), 5.5) ifdef USE_PTHREADS EXTRA_LIBS = -lpthread endif endif endif # SunOS ##################################################### # # The rules # ##################################################### include $(topsrcdir)/config/rules.mk AIX_PRE_4_2 = 0 ifeq ($(OS_ARCH),AIX) ifneq ($(OS_RELEASE),4.2) ifneq ($(USE_PTHREADS), 1) #AIX_PRE_4_2 = 1 endif endif endif ifeq ($(AIX_PRE_4_2),1) # AIX releases prior to 4.2 need a special two-step linking hack # in order to both override the system select() and be able to # get at the original system select(). # # We use a pattern rule in ns/nspr20/config/rules.mk to generate # the .$(OBJ_SUFFIX) file from the .c source file, then do the # two-step linking hack below. $(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) rm -f $@ $(AIX_TMP) $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) rm -f $(AIX_TMP) else # All platforms that are not AIX pre-4.2. $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) ifeq ($(OS_ARCH), WINNT) link $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) ws2_32.lib -out:$@ else ifeq ($(OS_ARCH), WINCE) $(LD) $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) ws2.lib -out:$@ else ifeq ($(OS_ARCH),OS2) $(LINK) $(EXEFLAGS) $(LDOPTS) $< $(LIBPLC) $(LIBPLDS) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS) else $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBPLDS) $(LIBPR) $(EXTRA_LIBS) -o $@ endif endif endif endif export:: $(TARGETS) clean:: rm -f $(TARGETS) nspr-4.11/nspr/lib/tests/arena.c0000644000000000000000000002351112623070344014676 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: arena.c ** Description: Testing arenas ** */ #include #include #include #include "nspr.h" #include "plarena.h" #include "plgetopt.h" PRLogModuleInfo *tLM; PRIntn threadCount = 0; PRMonitor *tMon; PRBool failed_already = PR_FALSE; /* Arguments from the command line with default values */ PRIntn debug_mode = 0; PRIntn poolMin = 4096; PRIntn poolMax = (100 * 4096); PRIntn arenaMin = 40; PRIntn arenaMax = (100 * 40); PRIntn stressIterations = 15; PRIntn maxAlloc = (1024 * 1024); PRIntn stressThreads = 4; void DumpAll( void ) { return; } /* ** Test Arena allocation. */ static void ArenaAllocate( void ) { PLArenaPool ap; void *ptr; PRInt32 i; PL_InitArenaPool( &ap, "AllocArena", 2048, sizeof(double)); PR_LOG( tLM, PR_LOG_DEBUG, ("AA, InitPool -- Pool: %p. first: %p, current: %p, size: %d", &ap, ap.first, ap.current, ap.arenasize )); for( i = 0; i < 150; i++ ) { PL_ARENA_ALLOCATE( ptr, &ap, 512 ); PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d", &ap, ap.first, ap.current, ap.arenasize )); PR_LOG( tLM, PR_LOG_DEBUG,( "AA -- Pool: %p. alloc: %p ", &ap, ptr )); } PL_FreeArenaPool( &ap ); for( i = 0; i < 221; i++ ) { PL_ARENA_ALLOCATE( ptr, &ap, 512 ); PR_LOG( tLM, PR_LOG_DEBUG,("AA, after alloc -- Pool: %p. first: %p, current: %p, size: %d", &ap, ap.first, ap.current, ap.arenasize )); PR_LOG( tLM, PR_LOG_DEBUG,( "AA -- Pool: %p. alloc: %p ", &ap, ptr )); } PL_FreeArenaPool( &ap ); return; } /* end ArenaGrow() */ /* ** Test Arena grow. */ static void ArenaGrow( void ) { PLArenaPool ap; void *ptr; PRInt32 i; PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double)); PL_ARENA_ALLOCATE( ptr, &ap, 512 ); PR_LOG( tLM, PR_LOG_DEBUG, ("Before growth -- Pool: %p. alloc: %p ", &ap, ptr )); for( i = 0; i < 10; i++ ) { PL_ARENA_GROW( ptr, &ap, 512, 7000 ); PR_LOG( tLM, PR_LOG_DEBUG, ("After growth -- Pool: %p. alloc: %p ", &ap, ptr )); } return; } /* end ArenaGrow() */ /* ** Test arena Mark and Release. */ static void MarkAndRelease( void ) { PLArenaPool ap; void *ptr = NULL; void *mark0, *mark1; PRIntn i; PL_InitArenaPool( &ap, "TheArena", 4096, sizeof(double)); mark0 = PL_ARENA_MARK( &ap ); PR_LOG( tLM, PR_LOG_DEBUG, ("mark0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m0: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark0 )); for( i = 0; i < 201; i++ ) { PL_ARENA_ALLOCATE( ptr, &ap, 512 ); PR_LOG( tLM, PR_LOG_DEBUG, ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); } mark1 = PL_ARENA_MARK( &ap ); PR_LOG( tLM, PR_LOG_DEBUG, ("mark1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p, m1: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr, mark1 )); for( i = 0; i < 225; i++ ) { PL_ARENA_ALLOCATE( ptr, &ap, 512 ); PR_LOG( tLM, PR_LOG_DEBUG, ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); } PL_ARENA_RELEASE( &ap, mark1 ); PR_LOG( tLM, PR_LOG_DEBUG, ("Release-1: %p -- Pool: %p. first: %p, current: %p, size: %d", mark1, &ap, ap.first, ap.current, ap.arenasize )); for( i = 0; i < 20; i++ ) { PL_ARENA_ALLOCATE( ptr, &ap, 512 ); PR_LOG( tLM, PR_LOG_DEBUG, ("mr. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); } PL_ARENA_RELEASE( &ap, mark1 ); PR_LOG( tLM, PR_LOG_DEBUG, ("Release-1. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); PL_ARENA_RELEASE( &ap, mark0 ); PR_LOG( tLM, PR_LOG_DEBUG, ("Release-0. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); PL_FreeArenaPool( &ap ); PR_LOG( tLM, PR_LOG_DEBUG, ("Free. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); PL_FinishArenaPool( &ap ); PR_LOG( tLM, PR_LOG_DEBUG, ("Finish. ap: %p, ap.f: %p, ap.c: %p, ap.siz: %d, alloc: %p", &ap, ap.first.next, ap.current, ap.arenasize, ptr )); return; } /* end MarkAndRelease() */ /* ** RandSize() returns a random number in the range ** min..max, rounded to the next doubleword ** */ static PRIntn RandSize( PRIntn min, PRIntn max ) { PRIntn sz = (rand() % (max -min)) + min + sizeof(double); sz &= ~sizeof(double)-1; return(sz); } /* ** StressThread() ** A bunch of these beat on individual arenas ** This tests the free_list protection. ** */ static void PR_CALLBACK StressThread( void *arg ) { PLArenaPool ap; PRIntn i; PRIntn sz; void *ptr; PRThread *tp = PR_GetCurrentThread(); PR_LOG( tLM, PR_LOG_DEBUG, ("Stress Thread %p started\n", PR_GetCurrentThread())); PL_InitArenaPool( &ap, "TheArena", RandSize( poolMin, poolMax), sizeof(double)); for ( i = 0; i < stressIterations; i++ ) { PRIntn allocated = 0; while ( allocated < maxAlloc ) { sz = RandSize( arenaMin, arenaMax ); PL_ARENA_ALLOCATE( ptr, &ap, sz ); if ( ptr == NULL ) { PR_LOG( tLM, PR_LOG_ERROR, ("ARENA_ALLOCATE() returned NULL\n\tAllocated: %d\n", allocated)); break; } allocated += sz; } PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished one iteration\n", tp)); PL_FreeArenaPool( &ap ); } PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p finished all iteration\n", tp)); PL_FinishArenaPool( &ap ); PR_LOG( tLM, PR_LOG_DEBUG, ("Stress thread %p after FinishArenaPool()\n", tp)); /* That's all folks! let's quit */ PR_EnterMonitor(tMon); threadCount--; PR_Notify(tMon); PR_ExitMonitor(tMon); return; } /* ** Stress() ** Flog the hell out of arenas multi-threaded. ** Do NOT pass an individual arena to another thread. ** */ static void Stress( void ) { PRThread *tt; PRIntn i; tMon = PR_NewMonitor(); for ( i = 0 ; i < stressThreads ; i++ ) { PR_EnterMonitor(tMon); tt = PR_CreateThread(PR_USER_THREAD, StressThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); threadCount++; PR_ExitMonitor(tMon); } /* Wait for all threads to exit */ PR_EnterMonitor(tMon); while ( threadCount != 0 ) { PR_Wait(tMon, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(tMon); PR_DestroyMonitor(tMon); return; } /* end Stress() */ /* ** EvaluateResults() ** uses failed_already to display results and set program ** exit code. */ static PRIntn EvaluateResults(void) { PRIntn rc = 0; if ( failed_already == PR_TRUE ) { PR_LOG( tLM, PR_LOG_DEBUG, ("FAIL\n")); rc =1; } else { PR_LOG( tLM, PR_LOG_DEBUG, ("PASS\n")); } return(rc); } /* EvaluateResults() */ void Help( void ) { printf("arena [options]\n"); printf("where options are:\n"); printf("-p minimum size of an arena pool. Default(%d)\n", poolMin); printf("-P maximum size of an arena pool. Default(%d)\n", poolMax); printf("-a minimum size of an arena allocation. Default(%d)\n", arenaMin); printf("-A maximum size of an arena allocation. Default(%d)\n", arenaMax); printf("-i number of iterations in a stress thread. Default(%d)\n", stressIterations); printf("-s maximum allocation for a single stress thread. Default(%d)\n", maxAlloc); printf("-t number of stress threads. Default(%d)\n", stressThreads ); printf("-d enable debug mode\n"); printf("\n"); exit(1); } PRIntn main(PRIntn argc, char *argv[]) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dhp:P:a:A:i:s:t:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'a': /* arena Min size */ arenaMin = atol( opt->value ); break; case 'A': /* arena Max size */ arenaMax = atol( opt->value ); break; case 'p': /* pool Min size */ poolMin = atol( opt->value ); break; case 'P': /* pool Max size */ poolMax = atol( opt->value ); break; case 'i': /* Iterations in stress tests */ stressIterations = atol( opt->value ); break; case 's': /* storage to get per iteration */ maxAlloc = atol( opt->value ); break; case 't': /* Number of stress threads to create */ stressThreads = atol( opt->value ); break; case 'd': /* debug mode */ debug_mode = 1; break; case 'h': /* help */ default: Help(); } /* end switch() */ } /* end while() */ PL_DestroyOptState(opt); srand( (unsigned)time( NULL ) ); /* seed random number generator */ tLM = PR_NewLogModule("testcase"); #if 0 ArenaAllocate(); ArenaGrow(); #endif MarkAndRelease(); Stress(); return(EvaluateResults()); } /* end main() */ /* arena.c */ nspr-4.11/nspr/lib/tests/base64t.c0000644000000000000000000036737412623070344015102 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plbase64.h" #include "plstr.h" #include "nspr.h" #include static unsigned char *base = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* PL_Base64Encode, single characters */ PRBool test_001(void) { PRUint32 a, b; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 001 (PL_Base64Encode, single characters) ..."); fflush(stdout); plain[1] = plain[2] = plain[3] = (unsigned char)0; cypher[2] = cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (unsigned char)(a * 4 + b); cypher[1] = base[(b * 16)]; rv = PL_Base64Encode((char *)plain, 1, result); if( rv != result ) { printf("FAIL\n\t(%d, %d): return value\n", a, b); return PR_FALSE; } if( 0 != PL_strncmp((char *)cypher, result, 4) ) { printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.4s.\"\n", a, b, cypher, result); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, double characters */ PRBool test_002(void) { PRUint32 a, b, c, d; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 002 (PL_Base64Encode, double characters) ..."); fflush(stdout); plain[2] = plain[3] = (unsigned char)0; cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; cypher[2] = base[d*4]; rv = PL_Base64Encode((char *)plain, 2, result); if( rv != result ) { printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d); return PR_FALSE; } if( 0 != PL_strncmp((char *)cypher, result, 4) ) { printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n", a, b, c, d, cypher, result); return PR_FALSE; } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, triple characters */ PRBool test_003(void) { PRUint32 a, b, c, d, e, f; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 003 (PL_Base64Encode, triple characters) ..."); fflush(stdout); cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; for( e = 0; e < 4; e++ ) { cypher[2] = base[d*4 + e]; for( f = 0; f < 64; f++ ) { plain[2] = e * 64 + f; cypher[3] = base[f]; rv = PL_Base64Encode((char *)plain, 3, result); if( rv != result ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): return value\n", a, b, c, d, e, f); return PR_FALSE; } if( 0 != PL_strncmp((char *)cypher, result, 4) ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n", a, b, c, d, e, f, cypher, result); return PR_FALSE; } } } } } } } printf("PASS\n"); return PR_TRUE; } static struct { const char *plaintext; const char *cyphertext; } array[] = { /* Cyphertexts generated with uuenview 0.5.13 */ { " ", "IA==" }, { ".", "Lg==" }, { "/", "Lw==" }, { "C", "Qw==" }, { "H", "SA==" }, { "S", "Uw==" }, { "^", "Xg==" }, { "a", "YQ==" }, { "o", "bw==" }, { "t", "dA==" }, { "AB", "QUI=" }, { "AH", "QUg=" }, { "AQ", "QVE=" }, { "BD", "QkQ=" }, { "CR", "Q1I=" }, { "CS", "Q1M=" }, { "DB", "REI=" }, { "DC", "REM=" }, { "EK", "RUs=" }, { "ET", "RVQ=" }, { "IM", "SU0=" }, { "JR", "SlI=" }, { "LO", "TE8=" }, { "LW", "TFc=" }, { "ML", "TUw=" }, { "SB", "U0I=" }, { "TO", "VE8=" }, { "VS", "VlM=" }, { "WP", "V1A=" }, /* legitimate two-letter words */ { "ad", "YWQ=" }, { "ah", "YWg=" }, { "am", "YW0=" }, { "an", "YW4=" }, { "as", "YXM=" }, { "at", "YXQ=" }, { "ax", "YXg=" }, { "be", "YmU=" }, { "by", "Ynk=" }, { "do", "ZG8=" }, { "go", "Z28=" }, { "he", "aGU=" }, { "hi", "aGk=" }, { "if", "aWY=" }, { "in", "aW4=" }, { "is", "aXM=" }, { "it", "aXQ=" }, { "me", "bWU=" }, { "my", "bXk=" }, { "no", "bm8=" }, { "of", "b2Y=" }, { "on", "b24=" }, { "or", "b3I=" }, { "ox", "b3g=" }, { "so", "c28=" }, { "to", "dG8=" }, { "up", "dXA=" }, { "us", "dXM=" }, { "we", "d2U=" }, /* all three-letter entries in /usr/dict/words */ { "1st", "MXN0" }, { "2nd", "Mm5k" }, { "3rd", "M3Jk" }, { "4th", "NHRo" }, { "5th", "NXRo" }, { "6th", "NnRo" }, { "7th", "N3Ro" }, { "8th", "OHRo" }, { "9th", "OXRo" }, { "AAA", "QUFB" }, { "AAU", "QUFV" }, { "ABA", "QUJB" }, { "abc", "YWJj" }, { "Abe", "QWJl" }, { "Abo", "QWJv" }, { "ace", "YWNl" }, { "ACM", "QUNN" }, { "ACS", "QUNT" }, { "act", "YWN0" }, { "Ada", "QWRh" }, { "add", "YWRk" }, { "ado", "YWRv" }, { "aft", "YWZ0" }, { "age", "YWdl" }, { "ago", "YWdv" }, { "aid", "YWlk" }, { "ail", "YWls" }, { "aim", "YWlt" }, { "air", "YWly" }, { "ala", "YWxh" }, { "alb", "YWxi" }, { "ale", "YWxl" }, { "Ali", "QWxp" }, { "all", "YWxs" }, { "alp", "YWxw" }, { "A&M", "QSZN" }, { "AMA", "QU1B" }, { "ami", "YW1p" }, { "amp", "YW1w" }, { "Amy", "QW15" }, { "amy", "YW15" }, { "ana", "YW5h" }, { "and", "YW5k" }, { "ani", "YW5p" }, { "Ann", "QW5u" }, { "ant", "YW50" }, { "any", "YW55" }, { "A&P", "QSZQ" }, { "ape", "YXBl" }, { "Apr", "QXBy" }, { "APS", "QVBT" }, { "apt", "YXB0" }, { "arc", "YXJj" }, { "are", "YXJl" }, { "ark", "YXJr" }, { "arm", "YXJt" }, { "art", "YXJ0" }, { "a's", "YSdz" }, { "ash", "YXNo" }, { "ask", "YXNr" }, { "ass", "YXNz" }, { "ate", "YXRl" }, { "Aug", "QXVn" }, { "auk", "YXVr" }, { "Ave", "QXZl" }, { "awe", "YXdl" }, { "awl", "YXds" }, { "awn", "YXdu" }, { "axe", "YXhl" }, { "aye", "YXll" }, { "bad", "YmFk" }, { "bag", "YmFn" }, { "bah", "YmFo" }, { "bam", "YmFt" }, { "ban", "YmFu" }, { "bar", "YmFy" }, { "bat", "YmF0" }, { "bay", "YmF5" }, { "bed", "YmVk" }, { "bee", "YmVl" }, { "beg", "YmVn" }, { "bel", "YmVs" }, { "Ben", "QmVu" }, { "bet", "YmV0" }, { "bey", "YmV5" }, { "bib", "Ymli" }, { "bid", "Ymlk" }, { "big", "Ymln" }, { "bin", "Ymlu" }, { "bit", "Yml0" }, { "biz", "Yml6" }, { "BMW", "Qk1X" }, { "boa", "Ym9h" }, { "bob", "Ym9i" }, { "bog", "Ym9n" }, { "bon", "Ym9u" }, { "boo", "Ym9v" }, { "bop", "Ym9w" }, { "bow", "Ym93" }, { "box", "Ym94" }, { "boy", "Ym95" }, { "b's", "Yidz" }, { "BTL", "QlRM" }, { "BTU", "QlRV" }, { "bub", "YnVi" }, { "bud", "YnVk" }, { "bug", "YnVn" }, { "bum", "YnVt" }, { "bun", "YnVu" }, { "bus", "YnVz" }, { "but", "YnV0" }, { "buy", "YnV5" }, { "bye", "Ynll" }, { "cab", "Y2Fi" }, { "Cal", "Q2Fs" }, { "cam", "Y2Ft" }, { "can", "Y2Fu" }, { "cap", "Y2Fw" }, { "car", "Y2Fy" }, { "cat", "Y2F0" }, { "caw", "Y2F3" }, { "CBS", "Q0JT" }, { "CDC", "Q0RD" }, { "CEQ", "Q0VR" }, { "chi", "Y2hp" }, { "CIA", "Q0lB" }, { "cit", "Y2l0" }, { "cod", "Y29k" }, { "cog", "Y29n" }, { "col", "Y29s" }, { "con", "Y29u" }, { "coo", "Y29v" }, { "cop", "Y29w" }, { "cos", "Y29z" }, { "cot", "Y290" }, { "cow", "Y293" }, { "cox", "Y294" }, { "coy", "Y295" }, { "CPA", "Q1BB" }, { "cpu", "Y3B1" }, { "CRT", "Q1JU" }, { "cry", "Y3J5" }, { "c's", "Yydz" }, { "cub", "Y3Vi" }, { "cud", "Y3Vk" }, { "cue", "Y3Vl" }, { "cup", "Y3Vw" }, { "cur", "Y3Vy" }, { "cut", "Y3V0" }, { "dab", "ZGFi" }, { "dad", "ZGFk" }, { "dam", "ZGFt" }, { "Dan", "RGFu" }, { "Dar", "RGFy" }, { "day", "ZGF5" }, { "Dec", "RGVj" }, { "Dee", "RGVl" }, { "Del", "RGVs" }, { "den", "ZGVu" }, { "Des", "RGVz" }, { "dew", "ZGV3" }, { "dey", "ZGV5" }, { "did", "ZGlk" }, { "die", "ZGll" }, { "dig", "ZGln" }, { "dim", "ZGlt" }, { "din", "ZGlu" }, { "dip", "ZGlw" }, { "Dis", "RGlz" }, { "DNA", "RE5B" }, { "DOD", "RE9E" }, { "doe", "ZG9l" }, { "dog", "ZG9n" }, { "don", "ZG9u" }, { "dot", "ZG90" }, { "Dow", "RG93" }, { "dry", "ZHJ5" }, { "d's", "ZCdz" }, { "dub", "ZHVi" }, { "dud", "ZHVk" }, { "due", "ZHVl" }, { "dug", "ZHVn" }, { "dun", "ZHVu" }, { "dye", "ZHll" }, { "ear", "ZWFy" }, { "eat", "ZWF0" }, { "ebb", "ZWJi" }, { "EDT", "RURU" }, { "eel", "ZWVs" }, { "eft", "ZWZ0" }, { "e.g", "ZS5n" }, { "egg", "ZWdn" }, { "ego", "ZWdv" }, { "eke", "ZWtl" }, { "Eli", "RWxp" }, { "elk", "ZWxr" }, { "ell", "ZWxs" }, { "elm", "ZWxt" }, { "Ely", "RWx5" }, { "end", "ZW5k" }, { "Eng", "RW5n" }, { "EPA", "RVBB" }, { "era", "ZXJh" }, { "ere", "ZXJl" }, { "erg", "ZXJn" }, { "err", "ZXJy" }, { "e's", "ZSdz" }, { "EST", "RVNU" }, { "eta", "ZXRh" }, { "etc", "ZXRj" }, { "Eva", "RXZh" }, { "eve", "ZXZl" }, { "ewe", "ZXdl" }, { "eye", "ZXll" }, { "FAA", "RkFB" }, { "fad", "ZmFk" }, { "fag", "ZmFn" }, { "fan", "ZmFu" }, { "far", "ZmFy" }, { "fat", "ZmF0" }, { "fay", "ZmF5" }, { "FBI", "RkJJ" }, { "FCC", "RkND" }, { "FDA", "RkRB" }, { "Feb", "RmVi" }, { "fed", "ZmVk" }, { "fee", "ZmVl" }, { "few", "ZmV3" }, { "fib", "Zmli" }, { "fig", "Zmln" }, { "fin", "Zmlu" }, { "fir", "Zmly" }, { "fit", "Zml0" }, { "fix", "Zml4" }, { "Flo", "Rmxv" }, { "flu", "Zmx1" }, { "fly", "Zmx5" }, { "FMC", "Rk1D" }, { "fob", "Zm9i" }, { "foe", "Zm9l" }, { "fog", "Zm9n" }, { "fop", "Zm9w" }, { "for", "Zm9y" }, { "fox", "Zm94" }, { "FPC", "RlBD" }, { "fro", "ZnJv" }, { "fry", "ZnJ5" }, { "f's", "Zidz" }, { "FTC", "RlRD" }, { "fum", "ZnVt" }, { "fun", "ZnVu" }, { "fur", "ZnVy" }, { "gab", "Z2Fi" }, { "gad", "Z2Fk" }, { "gag", "Z2Fn" }, { "gal", "Z2Fs" }, { "gam", "Z2Ft" }, { "GAO", "R0FP" }, { "gap", "Z2Fw" }, { "gar", "Z2Fy" }, { "gas", "Z2Fz" }, { "gay", "Z2F5" }, { "gee", "Z2Vl" }, { "gel", "Z2Vs" }, { "gem", "Z2Vt" }, { "get", "Z2V0" }, { "gig", "Z2ln" }, { "Gil", "R2ls" }, { "gin", "Z2lu" }, { "GMT", "R01U" }, { "GNP", "R05Q" }, { "gnu", "Z251" }, { "Goa", "R29h" }, { "gob", "Z29i" }, { "god", "Z29k" }, { "gog", "Z29n" }, { "GOP", "R09Q" }, { "got", "Z290" }, { "GPO", "R1BP" }, { "g's", "Zydz" }, { "GSA", "R1NB" }, { "gum", "Z3Vt" }, { "gun", "Z3Vu" }, { "Gus", "R3Vz" }, { "gut", "Z3V0" }, { "guy", "Z3V5" }, { "gym", "Z3lt" }, { "gyp", "Z3lw" }, { "had", "aGFk" }, { "Hal", "SGFs" }, { "ham", "aGFt" }, { "Han", "SGFu" }, { "hap", "aGFw" }, { "hat", "aGF0" }, { "haw", "aGF3" }, { "hay", "aGF5" }, { "hem", "aGVt" }, { "hen", "aGVu" }, { "her", "aGVy" }, { "hew", "aGV3" }, { "hex", "aGV4" }, { "hey", "aGV5" }, { "hid", "aGlk" }, { "him", "aGlt" }, { "hip", "aGlw" }, { "his", "aGlz" }, { "hit", "aGl0" }, { "hob", "aG9i" }, { "hoc", "aG9j" }, { "hoe", "aG9l" }, { "hog", "aG9n" }, { "hoi", "aG9p" }, { "Hom", "SG9t" }, { "hop", "aG9w" }, { "hot", "aG90" }, { "how", "aG93" }, { "hoy", "aG95" }, { "h's", "aCdz" }, { "hub", "aHVi" }, { "hue", "aHVl" }, { "hug", "aHVn" }, { "huh", "aHVo" }, { "hum", "aHVt" }, { "Hun", "SHVu" }, { "hut", "aHV0" }, { "Ian", "SWFu" }, { "IBM", "SUJN" }, { "Ibn", "SWJu" }, { "ICC", "SUND" }, { "ice", "aWNl" }, { "icy", "aWN5" }, { "I'd", "SSdk" }, { "Ida", "SWRh" }, { "i.e", "aS5l" }, { "iii", "aWlp" }, { "Ike", "SWtl" }, { "ill", "aWxs" }, { "I'm", "SSdt" }, { "imp", "aW1w" }, { "Inc", "SW5j" }, { "ink", "aW5r" }, { "inn", "aW5u" }, { "ion", "aW9u" }, { "Ira", "SXJh" }, { "ire", "aXJl" }, { "irk", "aXJr" }, { "IRS", "SVJT" }, { "i's", "aSdz" }, { "Ito", "SXRv" }, { "ITT", "SVRU" }, { "ivy", "aXZ5" }, { "jab", "amFi" }, { "jag", "amFn" }, { "jam", "amFt" }, { "Jan", "SmFu" }, { "jar", "amFy" }, { "jaw", "amF3" }, { "jay", "amF5" }, { "Jed", "SmVk" }, { "jet", "amV0" }, { "Jew", "SmV3" }, { "jig", "amln" }, { "Jim", "Smlt" }, { "job", "am9i" }, { "Joe", "Sm9l" }, { "jog", "am9n" }, { "Jon", "Sm9u" }, { "jot", "am90" }, { "joy", "am95" }, { "j's", "aidz" }, { "jug", "anVn" }, { "jut", "anV0" }, { "Kay", "S2F5" }, { "keg", "a2Vn" }, { "ken", "a2Vu" }, { "key", "a2V5" }, { "kid", "a2lk" }, { "Kim", "S2lt" }, { "kin", "a2lu" }, { "kit", "a2l0" }, { "k's", "aydz" }, { "lab", "bGFi" }, { "lac", "bGFj" }, { "lad", "bGFk" }, { "lag", "bGFn" }, { "lam", "bGFt" }, { "Lao", "TGFv" }, { "lap", "bGFw" }, { "law", "bGF3" }, { "lax", "bGF4" }, { "lay", "bGF5" }, { "lea", "bGVh" }, { "led", "bGVk" }, { "lee", "bGVl" }, { "leg", "bGVn" }, { "Len", "TGVu" }, { "Leo", "TGVv" }, { "let", "bGV0" }, { "Lev", "TGV2" }, { "Lew", "TGV3" }, { "lew", "bGV3" }, { "lid", "bGlk" }, { "lie", "bGll" }, { "lim", "bGlt" }, { "Lin", "TGlu" }, { "lip", "bGlw" }, { "lit", "bGl0" }, { "Liz", "TGl6" }, { "lob", "bG9i" }, { "log", "bG9n" }, { "lop", "bG9w" }, { "Los", "TG9z" }, { "lot", "bG90" }, { "Lou", "TG91" }, { "low", "bG93" }, { "loy", "bG95" }, { "l's", "bCdz" }, { "LSI", "TFNJ" }, { "Ltd", "THRk" }, { "LTV", "TFRW" }, { "lug", "bHVn" }, { "lux", "bHV4" }, { "lye", "bHll" }, { "Mac", "TWFj" }, { "mad", "bWFk" }, { "Mae", "TWFl" }, { "man", "bWFu" }, { "Mao", "TWFv" }, { "map", "bWFw" }, { "mar", "bWFy" }, { "mat", "bWF0" }, { "maw", "bWF3" }, { "Max", "TWF4" }, { "max", "bWF4" }, { "may", "bWF5" }, { "MBA", "TUJB" }, { "Meg", "TWVn" }, { "Mel", "TWVs" }, { "men", "bWVu" }, { "met", "bWV0" }, { "mew", "bWV3" }, { "mid", "bWlk" }, { "mig", "bWln" }, { "min", "bWlu" }, { "MIT", "TUlU" }, { "mix", "bWl4" }, { "mob", "bW9i" }, { "Moe", "TW9l" }, { "moo", "bW9v" }, { "mop", "bW9w" }, { "mot", "bW90" }, { "mow", "bW93" }, { "MPH", "TVBI" }, { "Mrs", "TXJz" }, { "m's", "bSdz" }, { "mud", "bXVk" }, { "mug", "bXVn" }, { "mum", "bXVt" }, { "nab", "bmFi" }, { "nag", "bmFn" }, { "Nan", "TmFu" }, { "nap", "bmFw" }, { "Nat", "TmF0" }, { "nay", "bmF5" }, { "NBC", "TkJD" }, { "NBS", "TkJT" }, { "NCO", "TkNP" }, { "NCR", "TkNS" }, { "Ned", "TmVk" }, { "nee", "bmVl" }, { "net", "bmV0" }, { "new", "bmV3" }, { "nib", "bmli" }, { "NIH", "TklI" }, { "nil", "bmls" }, { "nip", "bmlw" }, { "nit", "bml0" }, { "NNE", "Tk5F" }, { "NNW", "Tk5X" }, { "nob", "bm9i" }, { "nod", "bm9k" }, { "non", "bm9u" }, { "nor", "bm9y" }, { "not", "bm90" }, { "Nov", "Tm92" }, { "now", "bm93" }, { "NRC", "TlJD" }, { "n's", "bidz" }, { "NSF", "TlNG" }, { "nun", "bnVu" }, { "nut", "bnV0" }, { "NYC", "TllD" }, { "NYU", "TllV" }, { "oaf", "b2Fm" }, { "oak", "b2Fr" }, { "oar", "b2Fy" }, { "oat", "b2F0" }, { "Oct", "T2N0" }, { "odd", "b2Rk" }, { "ode", "b2Rl" }, { "off", "b2Zm" }, { "oft", "b2Z0" }, { "ohm", "b2ht" }, { "oil", "b2ls" }, { "old", "b2xk" }, { "one", "b25l" }, { "opt", "b3B0" }, { "orb", "b3Ji" }, { "ore", "b3Jl" }, { "Orr", "T3Jy" }, { "o's", "bydz" }, { "Ott", "T3R0" }, { "our", "b3Vy" }, { "out", "b3V0" }, { "ova", "b3Zh" }, { "owe", "b3dl" }, { "owl", "b3ds" }, { "own", "b3du" }, { "pad", "cGFk" }, { "pal", "cGFs" }, { "Pam", "UGFt" }, { "pan", "cGFu" }, { "pap", "cGFw" }, { "par", "cGFy" }, { "pat", "cGF0" }, { "paw", "cGF3" }, { "pax", "cGF4" }, { "pay", "cGF5" }, { "Paz", "UGF6" }, { "PBS", "UEJT" }, { "PDP", "UERQ" }, { "pea", "cGVh" }, { "pee", "cGVl" }, { "peg", "cGVn" }, { "pen", "cGVu" }, { "pep", "cGVw" }, { "per", "cGVy" }, { "pet", "cGV0" }, { "pew", "cGV3" }, { "PhD", "UGhE" }, { "phi", "cGhp" }, { "pie", "cGll" }, { "pig", "cGln" }, { "pin", "cGlu" }, { "pip", "cGlw" }, { "pit", "cGl0" }, { "ply", "cGx5" }, { "pod", "cG9k" }, { "Poe", "UG9l" }, { "poi", "cG9p" }, { "pol", "cG9s" }, { "pop", "cG9w" }, { "pot", "cG90" }, { "pow", "cG93" }, { "ppm", "cHBt" }, { "pro", "cHJv" }, { "pry", "cHJ5" }, { "p's", "cCdz" }, { "psi", "cHNp" }, { "PTA", "UFRB" }, { "pub", "cHVi" }, { "PUC", "UFVD" }, { "pug", "cHVn" }, { "pun", "cHVu" }, { "pup", "cHVw" }, { "pus", "cHVz" }, { "put", "cHV0" }, { "PVC", "UFZD" }, { "QED", "UUVE" }, { "q's", "cSdz" }, { "qua", "cXVh" }, { "quo", "cXVv" }, { "Rae", "UmFl" }, { "rag", "cmFn" }, { "raj", "cmFq" }, { "ram", "cmFt" }, { "ran", "cmFu" }, { "rap", "cmFw" }, { "rat", "cmF0" }, { "raw", "cmF3" }, { "ray", "cmF5" }, { "RCA", "UkNB" }, { "R&D", "UiZE" }, { "reb", "cmVi" }, { "red", "cmVk" }, { "rep", "cmVw" }, { "ret", "cmV0" }, { "rev", "cmV2" }, { "Rex", "UmV4" }, { "rho", "cmhv" }, { "rib", "cmli" }, { "rid", "cmlk" }, { "rig", "cmln" }, { "rim", "cmlt" }, { "Rio", "Umlv" }, { "rip", "cmlw" }, { "RNA", "Uk5B" }, { "rob", "cm9i" }, { "rod", "cm9k" }, { "roe", "cm9l" }, { "Ron", "Um9u" }, { "rot", "cm90" }, { "row", "cm93" }, { "Roy", "Um95" }, { "RPM", "UlBN" }, { "r's", "cidz" }, { "rub", "cnVi" }, { "rue", "cnVl" }, { "rug", "cnVn" }, { "rum", "cnVt" }, { "run", "cnVu" }, { "rut", "cnV0" }, { "rye", "cnll" }, { "sac", "c2Fj" }, { "sad", "c2Fk" }, { "sag", "c2Fn" }, { "Sal", "U2Fs" }, { "Sam", "U2Ft" }, { "San", "U2Fu" }, { "Sao", "U2Fv" }, { "sap", "c2Fw" }, { "sat", "c2F0" }, { "saw", "c2F3" }, { "sax", "c2F4" }, { "say", "c2F5" }, { "Sci", "U2Np" }, { "SCM", "U0NN" }, { "sea", "c2Vh" }, { "sec", "c2Vj" }, { "see", "c2Vl" }, { "sen", "c2Vu" }, { "seq", "c2Vx" }, { "set", "c2V0" }, { "sew", "c2V3" }, { "sex", "c2V4" }, { "she", "c2hl" }, { "Shu", "U2h1" }, { "shy", "c2h5" }, { "sib", "c2li" }, { "sic", "c2lj" }, { "sin", "c2lu" }, { "sip", "c2lw" }, { "sir", "c2ly" }, { "sis", "c2lz" }, { "sit", "c2l0" }, { "six", "c2l4" }, { "ski", "c2tp" }, { "sky", "c2t5" }, { "sly", "c2x5" }, { "sob", "c29i" }, { "Soc", "U29j" }, { "sod", "c29k" }, { "Sol", "U29s" }, { "son", "c29u" }, { "sop", "c29w" }, { "sou", "c291" }, { "sow", "c293" }, { "soy", "c295" }, { "spa", "c3Bh" }, { "spy", "c3B5" }, { "Sri", "U3Jp" }, { "s's", "cydz" }, { "SSE", "U1NF" }, { "SST", "U1NU" }, { "SSW", "U1NX" }, { "Stu", "U3R1" }, { "sub", "c3Vi" }, { "sud", "c3Vk" }, { "sue", "c3Vl" }, { "sum", "c3Vt" }, { "sun", "c3Vu" }, { "sup", "c3Vw" }, { "Sus", "U3Vz" }, { "tab", "dGFi" }, { "tad", "dGFk" }, { "tag", "dGFn" }, { "tam", "dGFt" }, { "tan", "dGFu" }, { "tao", "dGFv" }, { "tap", "dGFw" }, { "tar", "dGFy" }, { "tat", "dGF0" }, { "tau", "dGF1" }, { "tax", "dGF4" }, { "tea", "dGVh" }, { "Ted", "VGVk" }, { "ted", "dGVk" }, { "tee", "dGVl" }, { "Tel", "VGVs" }, { "ten", "dGVu" }, { "the", "dGhl" }, { "thy", "dGh5" }, { "tic", "dGlj" }, { "tid", "dGlk" }, { "tie", "dGll" }, { "til", "dGls" }, { "Tim", "VGlt" }, { "tin", "dGlu" }, { "tip", "dGlw" }, { "tit", "dGl0" }, { "TNT", "VE5U" }, { "toe", "dG9l" }, { "tog", "dG9n" }, { "Tom", "VG9t" }, { "ton", "dG9u" }, { "too", "dG9v" }, { "top", "dG9w" }, { "tor", "dG9y" }, { "tot", "dG90" }, { "tow", "dG93" }, { "toy", "dG95" }, { "TRW", "VFJX" }, { "try", "dHJ5" }, { "t's", "dCdz" }, { "TTL", "VFRM" }, { "TTY", "VFRZ" }, { "tub", "dHVi" }, { "tug", "dHVn" }, { "tum", "dHVt" }, { "tun", "dHVu" }, { "TVA", "VFZB" }, { "TWA", "VFdB" }, { "two", "dHdv" }, { "TWX", "VFdY" }, { "ugh", "dWdo" }, { "UHF", "VUhG" }, { "Uri", "VXJp" }, { "urn", "dXJu" }, { "U.S", "VS5T" }, { "u's", "dSdz" }, { "USA", "VVNB" }, { "USC", "VVND" }, { "use", "dXNl" }, { "USN", "VVNO" }, { "van", "dmFu" }, { "vat", "dmF0" }, { "vee", "dmVl" }, { "vet", "dmV0" }, { "vex", "dmV4" }, { "VHF", "VkhG" }, { "via", "dmlh" }, { "vie", "dmll" }, { "vii", "dmlp" }, { "vis", "dmlz" }, { "viz", "dml6" }, { "von", "dm9u" }, { "vow", "dm93" }, { "v's", "didz" }, { "WAC", "V0FD" }, { "wad", "d2Fk" }, { "wag", "d2Fn" }, { "wah", "d2Fo" }, { "wan", "d2Fu" }, { "war", "d2Fy" }, { "was", "d2Fz" }, { "wax", "d2F4" }, { "way", "d2F5" }, { "web", "d2Vi" }, { "wed", "d2Vk" }, { "wee", "d2Vl" }, { "Wei", "V2Vp" }, { "wet", "d2V0" }, { "who", "d2hv" }, { "why", "d2h5" }, { "wig", "d2ln" }, { "win", "d2lu" }, { "wit", "d2l0" }, { "woe", "d29l" }, { "wok", "d29r" }, { "won", "d29u" }, { "woo", "d29v" }, { "wop", "d29w" }, { "wow", "d293" }, { "wry", "d3J5" }, { "w's", "dydz" }, { "x's", "eCdz" }, { "yah", "eWFo" }, { "yak", "eWFr" }, { "yam", "eWFt" }, { "yap", "eWFw" }, { "yaw", "eWF3" }, { "yea", "eWVh" }, { "yen", "eWVu" }, { "yet", "eWV0" }, { "yin", "eWlu" }, { "yip", "eWlw" }, { "yon", "eW9u" }, { "you", "eW91" }, { "yow", "eW93" }, { "y's", "eSdz" }, { "yuh", "eXVo" }, { "zag", "emFn" }, { "Zan", "WmFu" }, { "zap", "emFw" }, { "Zen", "WmVu" }, { "zig", "emln" }, { "zip", "emlw" }, { "Zoe", "Wm9l" }, { "zoo", "em9v" }, { "z's", "eidz" }, /* the false rumors file */ { "\"So when I die, the first thing I will see in heaven is a score list?\"", "IlNvIHdoZW4gSSBkaWUsIHRoZSBmaXJzdCB0aGluZyBJIHdpbGwgc2VlIGluIGhlYXZlbiBpcyBhIHNjb3JlIGxpc3Q/Ig==" }, { "1st Law of Hacking: leaving is much more difficult than entering.", "MXN0IExhdyBvZiBIYWNraW5nOiBsZWF2aW5nIGlzIG11Y2ggbW9yZSBkaWZmaWN1bHQgdGhhbiBlbnRlcmluZy4=" }, { "2nd Law of Hacking: first in, first out.", "Mm5kIExhdyBvZiBIYWNraW5nOiBmaXJzdCBpbiwgZmlyc3Qgb3V0Lg==" }, { "3rd Law of Hacking: the last blow counts most.", "M3JkIExhdyBvZiBIYWNraW5nOiB0aGUgbGFzdCBibG93IGNvdW50cyBtb3N0Lg==" }, { "4th Law of Hacking: you will find the exit at the entrance.", "NHRoIExhdyBvZiBIYWNraW5nOiB5b3Ugd2lsbCBmaW5kIHRoZSBleGl0IGF0IHRoZSBlbnRyYW5jZS4=" }, { "A chameleon imitating a mail daemon often delivers scrolls of fire.", "QSBjaGFtZWxlb24gaW1pdGF0aW5nIGEgbWFpbCBkYWVtb24gb2Z0ZW4gZGVsaXZlcnMgc2Nyb2xscyBvZiBmaXJlLg==" }, { "A cockatrice corpse is guaranteed to be untainted!", "QSBjb2NrYXRyaWNlIGNvcnBzZSBpcyBndWFyYW50ZWVkIHRvIGJlIHVudGFpbnRlZCE=" }, { "A dead cockatrice is just a dead lizard.", "QSBkZWFkIGNvY2thdHJpY2UgaXMganVzdCBhIGRlYWQgbGl6YXJkLg==" }, { "A dragon is just a snake that ate a scroll of fire.", "QSBkcmFnb24gaXMganVzdCBhIHNuYWtlIHRoYXQgYXRlIGEgc2Nyb2xsIG9mIGZpcmUu" }, { "A fading corridor enlightens your insight.", "QSBmYWRpbmcgY29ycmlkb3IgZW5saWdodGVucyB5b3VyIGluc2lnaHQu" }, { "A glowing potion is too hot to drink.", "QSBnbG93aW5nIHBvdGlvbiBpcyB0b28gaG90IHRvIGRyaW5rLg==" }, { "A good amulet may protect you against guards.", "QSBnb29kIGFtdWxldCBtYXkgcHJvdGVjdCB5b3UgYWdhaW5zdCBndWFyZHMu" }, { "A lizard corpse is a good thing to turn undead.", "QSBsaXphcmQgY29ycHNlIGlzIGEgZ29vZCB0aGluZyB0byB0dXJuIHVuZGVhZC4=" }, { "A long worm can be defined recursively. So how should you attack it?", "QSBsb25nIHdvcm0gY2FuIGJlIGRlZmluZWQgcmVjdXJzaXZlbHkuIFNvIGhvdyBzaG91bGQgeW91IGF0dGFjayBpdD8=" }, { "A monstrous mind is a toy forever.", "QSBtb25zdHJvdXMgbWluZCBpcyBhIHRveSBmb3JldmVyLg==" }, { "A nymph will be very pleased if you call her by her real name: Lorelei.", "QSBueW1waCB3aWxsIGJlIHZlcnkgcGxlYXNlZCBpZiB5b3UgY2FsbCBoZXIgYnkgaGVyIHJlYWwgbmFtZTogTG9yZWxlaS4=" }, { "A ring of dungeon master control is a great find.", "QSByaW5nIG9mIGR1bmdlb24gbWFzdGVyIGNvbnRyb2wgaXMgYSBncmVhdCBmaW5kLg==" }, { "A ring of extra ring finger is useless if not enchanted.", "QSByaW5nIG9mIGV4dHJhIHJpbmcgZmluZ2VyIGlzIHVzZWxlc3MgaWYgbm90IGVuY2hhbnRlZC4=" }, { "A rope may form a trail in a maze.", "QSByb3BlIG1heSBmb3JtIGEgdHJhaWwgaW4gYSBtYXplLg==" }, { "A staff may recharge if you drop it for awhile.", "QSBzdGFmZiBtYXkgcmVjaGFyZ2UgaWYgeW91IGRyb3AgaXQgZm9yIGF3aGlsZS4=" }, { "A visit to the Zoo is very educational; you meet interesting animals.", "QSB2aXNpdCB0byB0aGUgWm9vIGlzIHZlcnkgZWR1Y2F0aW9uYWw7IHlvdSBtZWV0IGludGVyZXN0aW5nIGFuaW1hbHMu" }, { "A wand of deaf is a more dangerous weapon than a wand of sheep.", "QSB3YW5kIG9mIGRlYWYgaXMgYSBtb3JlIGRhbmdlcm91cyB3ZWFwb24gdGhhbiBhIHdhbmQgb2Ygc2hlZXAu" }, { "A wand of vibration might bring the whole cave crashing about your ears.", "QSB3YW5kIG9mIHZpYnJhdGlvbiBtaWdodCBicmluZyB0aGUgd2hvbGUgY2F2ZSBjcmFzaGluZyBhYm91dCB5b3VyIGVhcnMu" }, { "A winner never quits. A quitter never wins.", "QSB3aW5uZXIgbmV2ZXIgcXVpdHMuIEEgcXVpdHRlciBuZXZlciB3aW5zLg==" }, { "A wish? Okay, make me a fortune cookie!", "QSB3aXNoPyBPa2F5LCBtYWtlIG1lIGEgZm9ydHVuZSBjb29raWUh" }, { "Afraid of mimics? Try to wear a ring of true seeing.", "QWZyYWlkIG9mIG1pbWljcz8gVHJ5IHRvIHdlYXIgYSByaW5nIG9mIHRydWUgc2VlaW5nLg==" }, { "All monsters are created evil, but some are more evil than others.", "QWxsIG1vbnN0ZXJzIGFyZSBjcmVhdGVkIGV2aWwsIGJ1dCBzb21lIGFyZSBtb3JlIGV2aWwgdGhhbiBvdGhlcnMu" }, { "Always attack a floating eye from behind!", "QWx3YXlzIGF0dGFjayBhIGZsb2F0aW5nIGV5ZSBmcm9tIGJlaGluZCE=" }, { "An elven cloak is always the height of fashion.", "QW4gZWx2ZW4gY2xvYWsgaXMgYWx3YXlzIHRoZSBoZWlnaHQgb2YgZmFzaGlvbi4=" }, { "Any small object that is accidentally dropped will hide under a larger object.", "QW55IHNtYWxsIG9iamVjdCB0aGF0IGlzIGFjY2lkZW50YWxseSBkcm9wcGVkIHdpbGwgaGlkZSB1bmRlciBhIGxhcmdlciBvYmplY3Qu" }, { "Balrogs do not appear above level 20.", "QmFscm9ncyBkbyBub3QgYXBwZWFyIGFib3ZlIGxldmVsIDIwLg==" }, { "Banana peels work especially well against Keystone Kops.", "QmFuYW5hIHBlZWxzIHdvcmsgZXNwZWNpYWxseSB3ZWxsIGFnYWluc3QgS2V5c3RvbmUgS29wcy4=" }, { "Be careful when eating bananas. Monsters might slip on the peels.", "QmUgY2FyZWZ1bCB3aGVuIGVhdGluZyBiYW5hbmFzLiBNb25zdGVycyBtaWdodCBzbGlwIG9uIHRoZSBwZWVscy4=" }, { "Better leave the dungeon; otherwise you might get hurt badly.", "QmV0dGVyIGxlYXZlIHRoZSBkdW5nZW9uOyBvdGhlcndpc2UgeW91IG1pZ2h0IGdldCBodXJ0IGJhZGx5Lg==" }, { "Beware of the potion of nitroglycerin -- it's not for the weak of heart.", "QmV3YXJlIG9mIHRoZSBwb3Rpb24gb2Ygbml0cm9nbHljZXJpbiAtLSBpdCdzIG5vdCBmb3IgdGhlIHdlYWsgb2YgaGVhcnQu" }, { "Beware: there's always a chance that your wand explodes as you try to zap it!", "QmV3YXJlOiB0aGVyZSdzIGFsd2F5cyBhIGNoYW5jZSB0aGF0IHlvdXIgd2FuZCBleHBsb2RlcyBhcyB5b3UgdHJ5IHRvIHphcCBpdCE=" }, { "Beyond the 23rd level lies a happy retirement in a room of your own.", "QmV5b25kIHRoZSAyM3JkIGxldmVsIGxpZXMgYSBoYXBweSByZXRpcmVtZW50IGluIGEgcm9vbSBvZiB5b3VyIG93bi4=" }, { "Changing your suit without dropping your sword? You must be kidding!", "Q2hhbmdpbmcgeW91ciBzdWl0IHdpdGhvdXQgZHJvcHBpbmcgeW91ciBzd29yZD8gWW91IG11c3QgYmUga2lkZGluZyE=" }, { "Cockatrices might turn themselves to stone faced with a mirror.", "Q29ja2F0cmljZXMgbWlnaHQgdHVybiB0aGVtc2VsdmVzIHRvIHN0b25lIGZhY2VkIHdpdGggYSBtaXJyb3Iu" }, { "Consumption of home-made food is strictly forbidden in this dungeon.", "Q29uc3VtcHRpb24gb2YgaG9tZS1tYWRlIGZvb2QgaXMgc3RyaWN0bHkgZm9yYmlkZGVuIGluIHRoaXMgZHVuZ2Vvbi4=" }, { "Dark room? Your chance to develop your photographs!", "RGFyayByb29tPyBZb3VyIGNoYW5jZSB0byBkZXZlbG9wIHlvdXIgcGhvdG9ncmFwaHMh" }, { "Dark rooms are not *completely* dark: just wait and let your eyes adjust...", "RGFyayByb29tcyBhcmUgbm90ICpjb21wbGV0ZWx5KiBkYXJrOiBqdXN0IHdhaXQgYW5kIGxldCB5b3VyIGV5ZXMgYWRqdXN0Li4u" }, { "David London sez, \"Hey guys, *WIELD* a lizard corpse against a cockatrice!\"", "RGF2aWQgTG9uZG9uIHNleiwgIkhleSBndXlzLCAqV0lFTEQqIGEgbGl6YXJkIGNvcnBzZSBhZ2FpbnN0IGEgY29ja2F0cmljZSEi" }, { "Death is just life's way of telling you you've been fired.", "RGVhdGggaXMganVzdCBsaWZlJ3Mgd2F5IG9mIHRlbGxpbmcgeW91IHlvdSd2ZSBiZWVuIGZpcmVkLg==" }, { "Demi-gods don't need any help from the gods.", "RGVtaS1nb2RzIGRvbid0IG5lZWQgYW55IGhlbHAgZnJvbSB0aGUgZ29kcy4=" }, { "Demons *HATE* Priests and Priestesses.", "RGVtb25zICpIQVRFKiBQcmllc3RzIGFuZCBQcmllc3Rlc3Nlcy4=" }, { "Didn't you forget to pay?", "RGlkbid0IHlvdSBmb3JnZXQgdG8gcGF5Pw==" }, { "Didn't your mother tell you not to eat food off the floor?", "RGlkbid0IHlvdXIgbW90aGVyIHRlbGwgeW91IG5vdCB0byBlYXQgZm9vZCBvZmYgdGhlIGZsb29yPw==" }, { "Direct a direct hit on your direct opponent, directing in the right direction.", "RGlyZWN0IGEgZGlyZWN0IGhpdCBvbiB5b3VyIGRpcmVjdCBvcHBvbmVudCwgZGlyZWN0aW5nIGluIHRoZSByaWdodCBkaXJlY3Rpb24u" }, { "Do you want to make more money? Sure, we all do! Join the Fort Ludios guard!", "RG8geW91IHdhbnQgdG8gbWFrZSBtb3JlIG1vbmV5PyBTdXJlLCB3ZSBhbGwgZG8hIEpvaW4gdGhlIEZvcnQgTHVkaW9zIGd1YXJkIQ==" }, { "Don't eat too much: you might start hiccoughing!", "RG9uJ3QgZWF0IHRvbyBtdWNoOiB5b3UgbWlnaHQgc3RhcnQgaGljY291Z2hpbmch" }, { "Don't play hack at your work; your boss might hit you!", "RG9uJ3QgcGxheSBoYWNrIGF0IHlvdXIgd29yazsgeW91ciBib3NzIG1pZ2h0IGhpdCB5b3Uh" }, { "Don't tell a soul you found a secret door, otherwise it isn't a secret anymore.", "RG9uJ3QgdGVsbCBhIHNvdWwgeW91IGZvdW5kIGEgc2VjcmV0IGRvb3IsIG90aGVyd2lzZSBpdCBpc24ndCBhIHNlY3JldCBhbnltb3JlLg==" }, { "Drinking potions of booze may land you in jail if you are under 21.", "RHJpbmtpbmcgcG90aW9ucyBvZiBib296ZSBtYXkgbGFuZCB5b3UgaW4gamFpbCBpZiB5b3UgYXJlIHVuZGVyIDIxLg==" }, { "Drop your vanity and get rid of your jewels! Pickpockets about!", "RHJvcCB5b3VyIHZhbml0eSBhbmQgZ2V0IHJpZCBvZiB5b3VyIGpld2VscyEgUGlja3BvY2tldHMgYWJvdXQh" }, { "Eat 10 cloves of garlic and keep all humans at a two-square distance.", "RWF0IDEwIGNsb3ZlcyBvZiBnYXJsaWMgYW5kIGtlZXAgYWxsIGh1bWFucyBhdCBhIHR3by1zcXVhcmUgZGlzdGFuY2Uu" }, { "Eels hide under mud. Use a unicorn to clear the water and make them visible.", "RWVscyBoaWRlIHVuZGVyIG11ZC4gVXNlIGEgdW5pY29ybiB0byBjbGVhciB0aGUgd2F0ZXIgYW5kIG1ha2UgdGhlbSB2aXNpYmxlLg==" }, { "Engrave your wishes with a wand of wishing.", "RW5ncmF2ZSB5b3VyIHdpc2hlcyB3aXRoIGEgd2FuZCBvZiB3aXNoaW5nLg==" }, { "Eventually you will come to admire the swift elegance of a retreating nymph.", "RXZlbnR1YWxseSB5b3Ugd2lsbCBjb21lIHRvIGFkbWlyZSB0aGUgc3dpZnQgZWxlZ2FuY2Ugb2YgYSByZXRyZWF0aW5nIG55bXBoLg==" }, { "Ever heard hissing outside? I *knew* you hadn't!", "RXZlciBoZWFyZCBoaXNzaW5nIG91dHNpZGU/IEkgKmtuZXcqIHlvdSBoYWRuJ3Qh" }, { "Ever lifted a dragon corpse?", "RXZlciBsaWZ0ZWQgYSBkcmFnb24gY29ycHNlPw==" }, { "Ever seen a leocrotta dancing the tengu?", "RXZlciBzZWVuIGEgbGVvY3JvdHRhIGRhbmNpbmcgdGhlIHRlbmd1Pw==" }, { "Ever seen your weapon glow plaid?", "RXZlciBzZWVuIHlvdXIgd2VhcG9uIGdsb3cgcGxhaWQ/" }, { "Ever tamed a shopkeeper?", "RXZlciB0YW1lZCBhIHNob3BrZWVwZXI/" }, { "Ever tried digging through a Vault Guard?", "RXZlciB0cmllZCBkaWdnaW5nIHRocm91Z2ggYSBWYXVsdCBHdWFyZD8=" }, { "Ever tried enchanting a rope?", "RXZlciB0cmllZCBlbmNoYW50aW5nIGEgcm9wZT8=" }, { "Floating eyes can't stand Hawaiian shirts.", "RmxvYXRpbmcgZXllcyBjYW4ndCBzdGFuZCBIYXdhaWlhbiBzaGlydHMu" }, { "For any remedy there is a misery.", "Rm9yIGFueSByZW1lZHkgdGhlcmUgaXMgYSBtaXNlcnku" }, { "Giant bats turn into giant vampires.", "R2lhbnQgYmF0cyB0dXJuIGludG8gZ2lhbnQgdmFtcGlyZXMu" }, { "Good day for overcoming obstacles. Try a steeplechase.", "R29vZCBkYXkgZm9yIG92ZXJjb21pbmcgb2JzdGFjbGVzLiBUcnkgYSBzdGVlcGxlY2hhc2Uu" }, { "Half Moon tonight. (At least it's better than no Moon at all.)", "SGFsZiBNb29uIHRvbmlnaHQuIChBdCBsZWFzdCBpdCdzIGJldHRlciB0aGFuIG5vIE1vb24gYXQgYWxsLik=" }, { "Help! I'm being held prisoner in a fortune cookie factory!", "SGVscCEgSSdtIGJlaW5nIGhlbGQgcHJpc29uZXIgaW4gYSBmb3J0dW5lIGNvb2tpZSBmYWN0b3J5IQ==" }, { "Housecats have nine lives, kittens only one.", "SG91c2VjYXRzIGhhdmUgbmluZSBsaXZlcywga2l0dGVucyBvbmx5IG9uZS4=" }, { "How long can you tread water?", "SG93IGxvbmcgY2FuIHlvdSB0cmVhZCB3YXRlcj8=" }, { "Hungry? There is an abundance of food on the next level.", "SHVuZ3J5PyBUaGVyZSBpcyBhbiBhYnVuZGFuY2Ugb2YgZm9vZCBvbiB0aGUgbmV4dCBsZXZlbC4=" }, { "I guess you've never hit a mail daemon with the Amulet of Yendor...", "SSBndWVzcyB5b3UndmUgbmV2ZXIgaGl0IGEgbWFpbCBkYWVtb24gd2l0aCB0aGUgQW11bGV0IG9mIFllbmRvci4uLg==" }, { "If you are the shopkeeper, you can take things for free.", "SWYgeW91IGFyZSB0aGUgc2hvcGtlZXBlciwgeW91IGNhbiB0YWtlIHRoaW5ncyBmb3IgZnJlZS4=" }, { "If you can't learn to do it well, learn to enjoy doing it badly.", "SWYgeW91IGNhbid0IGxlYXJuIHRvIGRvIGl0IHdlbGwsIGxlYXJuIHRvIGVuam95IGRvaW5nIGl0IGJhZGx5Lg==" }, { "If you thought the Wizard was bad, just wait till you meet the Warlord!", "SWYgeW91IHRob3VnaHQgdGhlIFdpemFyZCB3YXMgYmFkLCBqdXN0IHdhaXQgdGlsbCB5b3UgbWVldCB0aGUgV2FybG9yZCE=" }, { "If you turn blind, don't expect your dog to be turned into a seeing-eye dog.", "SWYgeW91IHR1cm4gYmxpbmQsIGRvbid0IGV4cGVjdCB5b3VyIGRvZyB0byBiZSB0dXJuZWQgaW50byBhIHNlZWluZy1leWUgZG9nLg==" }, { "If you want to feel great, you must eat something real big.", "SWYgeW91IHdhbnQgdG8gZmVlbCBncmVhdCwgeW91IG11c3QgZWF0IHNvbWV0aGluZyByZWFsIGJpZy4=" }, { "If you want to float, you'd better eat a floating eye.", "SWYgeW91IHdhbnQgdG8gZmxvYXQsIHlvdSdkIGJldHRlciBlYXQgYSBmbG9hdGluZyBleWUu" }, { "If your ghost kills a player, it increases your score.", "SWYgeW91ciBnaG9zdCBraWxscyBhIHBsYXllciwgaXQgaW5jcmVhc2VzIHlvdXIgc2NvcmUu" }, { "Increase mindpower: Tame your own ghost!", "SW5jcmVhc2UgbWluZHBvd2VyOiBUYW1lIHlvdXIgb3duIGdob3N0IQ==" }, { "It furthers one to see the great man.", "SXQgZnVydGhlcnMgb25lIHRvIHNlZSB0aGUgZ3JlYXQgbWFuLg==" }, { "It's easy to overlook a monster in a wood.", "SXQncyBlYXN5IHRvIG92ZXJsb29rIGEgbW9uc3RlciBpbiBhIHdvb2Qu" }, { "Just below any trapdoor there may be another one. Just keep falling!", "SnVzdCBiZWxvdyBhbnkgdHJhcGRvb3IgdGhlcmUgbWF5IGJlIGFub3RoZXIgb25lLiBKdXN0IGtlZXAgZmFsbGluZyE=" }, { "Katanas are very sharp; watch you don't cut yourself.", "S2F0YW5hcyBhcmUgdmVyeSBzaGFycDsgd2F0Y2ggeW91IGRvbid0IGN1dCB5b3Vyc2VsZi4=" }, { "Keep a clear mind: quaff clear potions.", "S2VlcCBhIGNsZWFyIG1pbmQ6IHF1YWZmIGNsZWFyIHBvdGlvbnMu" }, { "Kicking the terminal doesn't hurt the monsters.", "S2lja2luZyB0aGUgdGVybWluYWwgZG9lc24ndCBodXJ0IHRoZSBtb25zdGVycy4=" }, { "Killer bees keep appearing till you kill their queen.", "S2lsbGVyIGJlZXMga2VlcCBhcHBlYXJpbmcgdGlsbCB5b3Uga2lsbCB0aGVpciBxdWVlbi4=" }, { "Killer bunnies can be tamed with carrots only.", "S2lsbGVyIGJ1bm5pZXMgY2FuIGJlIHRhbWVkIHdpdGggY2Fycm90cyBvbmx5Lg==" }, { "Latest news? Put `rec.games.roguelike.nethack' in your .newsrc!", "TGF0ZXN0IG5ld3M/IFB1dCBgcmVjLmdhbWVzLnJvZ3VlbGlrZS5uZXRoYWNrJyBpbiB5b3VyIC5uZXdzcmMh" }, { "Learn how to spell. Play NetHack!", "TGVhcm4gaG93IHRvIHNwZWxsLiBQbGF5IE5ldEhhY2sh" }, { "Leprechauns hide their gold in a secret room.", "TGVwcmVjaGF1bnMgaGlkZSB0aGVpciBnb2xkIGluIGEgc2VjcmV0IHJvb20u" }, { "Let your fingers do the walking on the yulkjhnb keys.", "TGV0IHlvdXIgZmluZ2VycyBkbyB0aGUgd2Fsa2luZyBvbiB0aGUgeXVsa2pobmIga2V5cy4=" }, { "Let's face it: this time you're not going to win.", "TGV0J3MgZmFjZSBpdDogdGhpcyB0aW1lIHlvdSdyZSBub3QgZ29pbmcgdG8gd2luLg==" }, { "Let's have a party, drink a lot of booze.", "TGV0J3MgaGF2ZSBhIHBhcnR5LCBkcmluayBhIGxvdCBvZiBib296ZS4=" }, { "Liquor sellers do not drink; they hate to see you twice.", "TGlxdW9yIHNlbGxlcnMgZG8gbm90IGRyaW5rOyB0aGV5IGhhdGUgdG8gc2VlIHlvdSB0d2ljZS4=" }, { "Lunar eclipse tonight. May as well quit now!", "THVuYXIgZWNsaXBzZSB0b25pZ2h0LiBNYXkgYXMgd2VsbCBxdWl0IG5vdyE=" }, { "Meeting your own ghost decreases your luck considerably!", "TWVldGluZyB5b3VyIG93biBnaG9zdCBkZWNyZWFzZXMgeW91ciBsdWNrIGNvbnNpZGVyYWJseSE=" }, { "Money to invest? Take it to the local branch of the Magic Memory Vault!", "TW9uZXkgdG8gaW52ZXN0PyBUYWtlIGl0IHRvIHRoZSBsb2NhbCBicmFuY2ggb2YgdGhlIE1hZ2ljIE1lbW9yeSBWYXVsdCE=" }, { "Monsters come from nowhere to hit you everywhere.", "TW9uc3RlcnMgY29tZSBmcm9tIG5vd2hlcmUgdG8gaGl0IHlvdSBldmVyeXdoZXJlLg==" }, { "Monsters sleep because you are boring, not because they ever get tired.", "TW9uc3RlcnMgc2xlZXAgYmVjYXVzZSB5b3UgYXJlIGJvcmluZywgbm90IGJlY2F1c2UgdGhleSBldmVyIGdldCB0aXJlZC4=" }, { "Most monsters prefer minced meat. That's why they are hitting you!", "TW9zdCBtb25zdGVycyBwcmVmZXIgbWluY2VkIG1lYXQuIFRoYXQncyB3aHkgdGhleSBhcmUgaGl0dGluZyB5b3Uh" }, { "Most of the bugs in NetHack are on the floor.", "TW9zdCBvZiB0aGUgYnVncyBpbiBOZXRIYWNrIGFyZSBvbiB0aGUgZmxvb3Iu" }, { "Much ado Nothing Happens.", "TXVjaCBhZG8gTm90aGluZyBIYXBwZW5zLg==" }, { "Multi-player NetHack is a myth.", "TXVsdGktcGxheWVyIE5ldEhhY2sgaXMgYSBteXRoLg==" }, { "NetHack is addictive. Too late, you're already hooked.", "TmV0SGFjayBpcyBhZGRpY3RpdmUuIFRvbyBsYXRlLCB5b3UncmUgYWxyZWFkeSBob29rZWQu" }, { "Never ask a shopkeeper for a price list.", "TmV2ZXIgYXNrIGEgc2hvcGtlZXBlciBmb3IgYSBwcmljZSBsaXN0Lg==" }, { "Never burn a tree, unless you like getting whacked with a +5 shovel.", "TmV2ZXIgYnVybiBhIHRyZWUsIHVubGVzcyB5b3UgbGlrZSBnZXR0aW5nIHdoYWNrZWQgd2l0aCBhICs1IHNob3ZlbC4=" }, { "Never eat with glowing hands!", "TmV2ZXIgZWF0IHdpdGggZ2xvd2luZyBoYW5kcyE=" }, { "Never mind the monsters hitting you: they just replace the charwomen.", "TmV2ZXIgbWluZCB0aGUgbW9uc3RlcnMgaGl0dGluZyB5b3U6IHRoZXkganVzdCByZXBsYWNlIHRoZSBjaGFyd29tZW4u" }, { "Never play leapfrog with a unicorn.", "TmV2ZXIgcGxheSBsZWFwZnJvZyB3aXRoIGEgdW5pY29ybi4=" }, { "Never step on a cursed engraving.", "TmV2ZXIgc3RlcCBvbiBhIGN1cnNlZCBlbmdyYXZpbmcu" }, { "Never swim with a camera: there's nothing to take pictures of.", "TmV2ZXIgc3dpbSB3aXRoIGEgY2FtZXJhOiB0aGVyZSdzIG5vdGhpbmcgdG8gdGFrZSBwaWN0dXJlcyBvZi4=" }, { "Never teach your pet rust monster to fetch.", "TmV2ZXIgdGVhY2ggeW91ciBwZXQgcnVzdCBtb25zdGVyIHRvIGZldGNoLg==" }, { "Never trust a random generator in magic fields.", "TmV2ZXIgdHJ1c3QgYSByYW5kb20gZ2VuZXJhdG9yIGluIG1hZ2ljIGZpZWxkcy4=" }, { "Never use a wand of death.", "TmV2ZXIgdXNlIGEgd2FuZCBvZiBkZWF0aC4=" }, { "No level contains two shops. The maze is no level. So...", "Tm8gbGV2ZWwgY29udGFpbnMgdHdvIHNob3BzLiBUaGUgbWF6ZSBpcyBubyBsZXZlbC4gU28uLi4=" }, { "No part of this fortune may be reproduced, stored in a retrieval system, ...", "Tm8gcGFydCBvZiB0aGlzIGZvcnR1bmUgbWF5IGJlIHJlcHJvZHVjZWQsIHN0b3JlZCBpbiBhIHJldHJpZXZhbCBzeXN0ZW0sIC4uLg==" }, { "Not all rumors are as misleading as this one.", "Tm90IGFsbCBydW1vcnMgYXJlIGFzIG1pc2xlYWRpbmcgYXMgdGhpcyBvbmUu" }, { "Nymphs and nurses like beautiful rings.", "TnltcGhzIGFuZCBudXJzZXMgbGlrZSBiZWF1dGlmdWwgcmluZ3Mu" }, { "Nymphs are blondes. Are you a gentleman?", "TnltcGhzIGFyZSBibG9uZGVzLiBBcmUgeW91IGEgZ2VudGxlbWFuPw==" }, { "Offering a unicorn a worthless piece of glass might prove to be fatal!", "T2ZmZXJpbmcgYSB1bmljb3JuIGEgd29ydGhsZXNzIHBpZWNlIG9mIGdsYXNzIG1pZ2h0IHByb3ZlIHRvIGJlIGZhdGFsIQ==" }, { "Old hackers never die: young ones do.", "T2xkIGhhY2tlcnMgbmV2ZXIgZGllOiB5b3VuZyBvbmVzIGRvLg==" }, { "One has to leave shops before closing time.", "T25lIGhhcyB0byBsZWF2ZSBzaG9wcyBiZWZvcmUgY2xvc2luZyB0aW1lLg==" }, { "One homunculus a day keeps the doctor away.", "T25lIGhvbXVuY3VsdXMgYSBkYXkga2VlcHMgdGhlIGRvY3RvciBhd2F5Lg==" }, { "One level further down somebody is getting killed, right now.", "T25lIGxldmVsIGZ1cnRoZXIgZG93biBzb21lYm9keSBpcyBnZXR0aW5nIGtpbGxlZCwgcmlnaHQgbm93Lg==" }, { "Only a wizard can use a magic whistle.", "T25seSBhIHdpemFyZCBjYW4gdXNlIGEgbWFnaWMgd2hpc3RsZS4=" }, { "Only adventurers of evil alignment think of killing their dog.", "T25seSBhZHZlbnR1cmVycyBvZiBldmlsIGFsaWdubWVudCB0aGluayBvZiBraWxsaW5nIHRoZWlyIGRvZy4=" }, { "Only chaotic evils kill sleeping monsters.", "T25seSBjaGFvdGljIGV2aWxzIGtpbGwgc2xlZXBpbmcgbW9uc3RlcnMu" }, { "Only real trappers escape traps.", "T25seSByZWFsIHRyYXBwZXJzIGVzY2FwZSB0cmFwcy4=" }, { "Only real wizards can write scrolls.", "T25seSByZWFsIHdpemFyZHMgY2FuIHdyaXRlIHNjcm9sbHMu" }, { "Operation OVERKILL has started now.", "T3BlcmF0aW9uIE9WRVJLSUxMIGhhcyBzdGFydGVkIG5vdy4=" }, { "PLEASE ignore previous rumor.", "UExFQVNFIGlnbm9yZSBwcmV2aW91cyBydW1vci4=" }, { "Polymorph into an ettin; meet your opponents face to face to face.", "UG9seW1vcnBoIGludG8gYW4gZXR0aW47IG1lZXQgeW91ciBvcHBvbmVudHMgZmFjZSB0byBmYWNlIHRvIGZhY2Uu" }, { "Praying will frighten demons.", "UHJheWluZyB3aWxsIGZyaWdodGVuIGRlbW9ucy4=" }, { "Row (3x) that boat gently down the stream, Charon (4x), death is but a dream.", "Um93ICgzeCkgdGhhdCBib2F0IGdlbnRseSBkb3duIHRoZSBzdHJlYW0sIENoYXJvbiAoNHgpLCBkZWF0aCBpcyBidXQgYSBkcmVhbS4=" }, { "Running is good for your legs.", "UnVubmluZyBpcyBnb29kIGZvciB5b3VyIGxlZ3Mu" }, { "Screw up your courage! You've screwed up everything else.", "U2NyZXcgdXAgeW91ciBjb3VyYWdlISBZb3UndmUgc2NyZXdlZCB1cCBldmVyeXRoaW5nIGVsc2Uu" }, { "Seepage? Leaky pipes? Rising damp? Summon the plumber!", "U2VlcGFnZT8gTGVha3kgcGlwZXM/IFJpc2luZyBkYW1wPyBTdW1tb24gdGhlIHBsdW1iZXIh" }, { "Segmentation fault (core dumped).", "U2VnbWVudGF0aW9uIGZhdWx0IChjb3JlIGR1bXBlZCku" }, { "Shopkeepers sometimes die from old age.", "U2hvcGtlZXBlcnMgc29tZXRpbWVzIGRpZSBmcm9tIG9sZCBhZ2Uu" }, { "Some mazes (especially small ones) have no solutions, says man 6 maze.", "U29tZSBtYXplcyAoZXNwZWNpYWxseSBzbWFsbCBvbmVzKSBoYXZlIG5vIHNvbHV0aW9ucywgc2F5cyBtYW4gNiBtYXplLg==" }, { "Some questions the Sphynx asks just *don't* have any answers.", "U29tZSBxdWVzdGlvbnMgdGhlIFNwaHlueCBhc2tzIGp1c3QgKmRvbid0KiBoYXZlIGFueSBhbnN3ZXJzLg==" }, { "Sometimes \"mu\" is the answer.", "U29tZXRpbWVzICJtdSIgaXMgdGhlIGFuc3dlci4=" }, { "Sorry, no fortune this time. Better luck next cookie!", "U29ycnksIG5vIGZvcnR1bmUgdGhpcyB0aW1lLiBCZXR0ZXIgbHVjayBuZXh0IGNvb2tpZSE=" }, { "Spare your scrolls of make-edible until it's really necessary!", "U3BhcmUgeW91ciBzY3JvbGxzIG9mIG1ha2UtZWRpYmxlIHVudGlsIGl0J3MgcmVhbGx5IG5lY2Vzc2FyeSE=" }, { "Suddenly, the dungeon will collapse...", "U3VkZGVubHksIHRoZSBkdW5nZW9uIHdpbGwgY29sbGFwc2UuLi4=" }, { "Taming a mail daemon may cause a system security violation.", "VGFtaW5nIGEgbWFpbCBkYWVtb24gbWF5IGNhdXNlIGEgc3lzdGVtIHNlY3VyaXR5IHZpb2xhdGlvbi4=" }, { "The crowd was so tough, the Stooges won't play the Dungeon anymore, nyuk nyuk.", "VGhlIGNyb3dkIHdhcyBzbyB0b3VnaCwgdGhlIFN0b29nZXMgd29uJ3QgcGxheSB0aGUgRHVuZ2VvbiBhbnltb3JlLCBueXVrIG55dWsu" }, { "The leprechauns hide their treasure in a small hidden room.", "VGhlIGxlcHJlY2hhdW5zIGhpZGUgdGhlaXIgdHJlYXN1cmUgaW4gYSBzbWFsbCBoaWRkZW4gcm9vbS4=" }, { "The longer the wand the better.", "VGhlIGxvbmdlciB0aGUgd2FuZCB0aGUgYmV0dGVyLg==" }, { "The magic word is \"XYZZY\".", "VGhlIG1hZ2ljIHdvcmQgaXMgIlhZWlpZIi4=" }, { "The meek shall inherit your bones files.", "VGhlIG1lZWsgc2hhbGwgaW5oZXJpdCB5b3VyIGJvbmVzIGZpbGVzLg==" }, { "The mines are dark and deep, and I have levels to go before I sleep.", "VGhlIG1pbmVzIGFyZSBkYXJrIGFuZCBkZWVwLCBhbmQgSSBoYXZlIGxldmVscyB0byBnbyBiZWZvcmUgSSBzbGVlcC4=" }, { "The use of dynamite is dangerous.", "VGhlIHVzZSBvZiBkeW5hbWl0ZSBpcyBkYW5nZXJvdXMu" }, { "There are no worms in the UNIX version.", "VGhlcmUgYXJlIG5vIHdvcm1zIGluIHRoZSBVTklYIHZlcnNpb24u" }, { "There is a trap on this level!", "VGhlcmUgaXMgYSB0cmFwIG9uIHRoaXMgbGV2ZWwh" }, { "They say that Demogorgon, Asmodeus, Orcus, Yeenoghu & Juiblex is no law firm.", "VGhleSBzYXkgdGhhdCBEZW1vZ29yZ29uLCBBc21vZGV1cywgT3JjdXMsIFllZW5vZ2h1ICYgSnVpYmxleCBpcyBubyBsYXcgZmlybS4=" }, { "They say that Geryon has an evil twin, beware!", "VGhleSBzYXkgdGhhdCBHZXJ5b24gaGFzIGFuIGV2aWwgdHdpbiwgYmV3YXJlIQ==" }, { "They say that Medusa would make a terrible pet.", "VGhleSBzYXkgdGhhdCBNZWR1c2Egd291bGQgbWFrZSBhIHRlcnJpYmxlIHBldC4=" }, { "They say that NetHack bugs are Seldon planned.", "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGJ1Z3MgYXJlIFNlbGRvbiBwbGFubmVkLg==" }, { "They say that NetHack comes in 256 flavors.", "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGNvbWVzIGluIDI1NiBmbGF2b3JzLg==" }, { "They say that NetHack is just a computer game.", "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIGp1c3QgYSBjb21wdXRlciBnYW1lLg==" }, { "They say that NetHack is more than just a computer game.", "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIG1vcmUgdGhhbiBqdXN0IGEgY29tcHV0ZXIgZ2FtZS4=" }, { "They say that NetHack is never what it used to be.", "VGhleSBzYXkgdGhhdCBOZXRIYWNrIGlzIG5ldmVyIHdoYXQgaXQgdXNlZCB0byBiZS4=" }, { "They say that a baby dragon is too small to hurt or help you.", "VGhleSBzYXkgdGhhdCBhIGJhYnkgZHJhZ29uIGlzIHRvbyBzbWFsbCB0byBodXJ0IG9yIGhlbHAgeW91Lg==" }, { "They say that a black pudding is simply a brown pudding gone bad.", "VGhleSBzYXkgdGhhdCBhIGJsYWNrIHB1ZGRpbmcgaXMgc2ltcGx5IGEgYnJvd24gcHVkZGluZyBnb25lIGJhZC4=" }, { "They say that a black sheep has 3 bags full of wool.", "VGhleSBzYXkgdGhhdCBhIGJsYWNrIHNoZWVwIGhhcyAzIGJhZ3MgZnVsbCBvZiB3b29sLg==" }, { "They say that a blank scroll is like a blank check.", "VGhleSBzYXkgdGhhdCBhIGJsYW5rIHNjcm9sbCBpcyBsaWtlIGEgYmxhbmsgY2hlY2su" }, { "They say that a cat named Morris has nine lives.", "VGhleSBzYXkgdGhhdCBhIGNhdCBuYW1lZCBNb3JyaXMgaGFzIG5pbmUgbGl2ZXMu" }, { "They say that a desperate shopper might pay any price in a shop.", "VGhleSBzYXkgdGhhdCBhIGRlc3BlcmF0ZSBzaG9wcGVyIG1pZ2h0IHBheSBhbnkgcHJpY2UgaW4gYSBzaG9wLg==" }, { "They say that a diamond dog is everybody's best friend.", "VGhleSBzYXkgdGhhdCBhIGRpYW1vbmQgZG9nIGlzIGV2ZXJ5Ym9keSdzIGJlc3QgZnJpZW5kLg==" }, { "They say that a dwarf lord can carry a pick-axe because his armor is light.", "VGhleSBzYXkgdGhhdCBhIGR3YXJmIGxvcmQgY2FuIGNhcnJ5IGEgcGljay1heGUgYmVjYXVzZSBoaXMgYXJtb3IgaXMgbGlnaHQu" }, { "They say that a floating eye can defeat Medusa.", "VGhleSBzYXkgdGhhdCBhIGZsb2F0aW5nIGV5ZSBjYW4gZGVmZWF0IE1lZHVzYS4=" }, { "They say that a fortune only has 1 line and you can't read between it.", "VGhleSBzYXkgdGhhdCBhIGZvcnR1bmUgb25seSBoYXMgMSBsaW5lIGFuZCB5b3UgY2FuJ3QgcmVhZCBiZXR3ZWVuIGl0Lg==" }, { "They say that a fortune only has 1 line, but you can read between it.", "VGhleSBzYXkgdGhhdCBhIGZvcnR1bmUgb25seSBoYXMgMSBsaW5lLCBidXQgeW91IGNhbiByZWFkIGJldHdlZW4gaXQu" }, { "They say that a fountain looks nothing like a regularly erupting geyser.", "VGhleSBzYXkgdGhhdCBhIGZvdW50YWluIGxvb2tzIG5vdGhpbmcgbGlrZSBhIHJlZ3VsYXJseSBlcnVwdGluZyBnZXlzZXIu" }, { "They say that a gold doubloon is worth more than its weight in gold.", "VGhleSBzYXkgdGhhdCBhIGdvbGQgZG91Ymxvb24gaXMgd29ydGggbW9yZSB0aGFuIGl0cyB3ZWlnaHQgaW4gZ29sZC4=" }, { "They say that a grid bug won't pay a shopkeeper for zapping you in a shop.", "VGhleSBzYXkgdGhhdCBhIGdyaWQgYnVnIHdvbid0IHBheSBhIHNob3BrZWVwZXIgZm9yIHphcHBpbmcgeW91IGluIGEgc2hvcC4=" }, { "They say that a gypsy could tell your fortune for a price.", "VGhleSBzYXkgdGhhdCBhIGd5cHN5IGNvdWxkIHRlbGwgeW91ciBmb3J0dW5lIGZvciBhIHByaWNlLg==" }, { "They say that a hacker named Alice once level teleported by using a mirror.", "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBBbGljZSBvbmNlIGxldmVsIHRlbGVwb3J0ZWQgYnkgdXNpbmcgYSBtaXJyb3Iu" }, { "They say that a hacker named David once slew a giant with a sling and a rock.", "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBEYXZpZCBvbmNlIHNsZXcgYSBnaWFudCB3aXRoIGEgc2xpbmcgYW5kIGEgcm9jay4=" }, { "They say that a hacker named Dorothy once rode a fog cloud to Oz.", "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBEb3JvdGh5IG9uY2Ugcm9kZSBhIGZvZyBjbG91ZCB0byBPei4=" }, { "They say that a hacker named Mary once lost a white sheep in the mazes.", "VGhleSBzYXkgdGhhdCBhIGhhY2tlciBuYW1lZCBNYXJ5IG9uY2UgbG9zdCBhIHdoaXRlIHNoZWVwIGluIHRoZSBtYXplcy4=" }, { "They say that a helm of brilliance is not to be taken lightly.", "VGhleSBzYXkgdGhhdCBhIGhlbG0gb2YgYnJpbGxpYW5jZSBpcyBub3QgdG8gYmUgdGFrZW4gbGlnaHRseS4=" }, { "They say that a hot dog and a hell hound are the same thing.", "VGhleSBzYXkgdGhhdCBhIGhvdCBkb2cgYW5kIGEgaGVsbCBob3VuZCBhcmUgdGhlIHNhbWUgdGhpbmcu" }, { "They say that a lamp named Aladdin's Lamp contains a djinni with 3 wishes.", "VGhleSBzYXkgdGhhdCBhIGxhbXAgbmFtZWQgQWxhZGRpbidzIExhbXAgY29udGFpbnMgYSBkamlubmkgd2l0aCAzIHdpc2hlcy4=" }, { "They say that a large dog named Lassie will lead you to the amulet.", "VGhleSBzYXkgdGhhdCBhIGxhcmdlIGRvZyBuYW1lZCBMYXNzaWUgd2lsbCBsZWFkIHlvdSB0byB0aGUgYW11bGV0Lg==" }, { "They say that a long sword is not a light sword.", "VGhleSBzYXkgdGhhdCBhIGxvbmcgc3dvcmQgaXMgbm90IGEgbGlnaHQgc3dvcmQu" }, { "They say that a manes won't mince words with you.", "VGhleSBzYXkgdGhhdCBhIG1hbmVzIHdvbid0IG1pbmNlIHdvcmRzIHdpdGggeW91Lg==" }, { "They say that a mind is a terrible thing to waste.", "VGhleSBzYXkgdGhhdCBhIG1pbmQgaXMgYSB0ZXJyaWJsZSB0aGluZyB0byB3YXN0ZS4=" }, { "They say that a plain nymph will only wear a wire ring in one ear.", "VGhleSBzYXkgdGhhdCBhIHBsYWluIG55bXBoIHdpbGwgb25seSB3ZWFyIGEgd2lyZSByaW5nIGluIG9uZSBlYXIu" }, { "They say that a plumed hat could be a previously used crested helmet.", "VGhleSBzYXkgdGhhdCBhIHBsdW1lZCBoYXQgY291bGQgYmUgYSBwcmV2aW91c2x5IHVzZWQgY3Jlc3RlZCBoZWxtZXQu" }, { "They say that a potion of oil is difficult to grasp.", "VGhleSBzYXkgdGhhdCBhIHBvdGlvbiBvZiBvaWwgaXMgZGlmZmljdWx0IHRvIGdyYXNwLg==" }, { "They say that a potion of yogurt is a cancelled potion of sickness.", "VGhleSBzYXkgdGhhdCBhIHBvdGlvbiBvZiB5b2d1cnQgaXMgYSBjYW5jZWxsZWQgcG90aW9uIG9mIHNpY2tuZXNzLg==" }, { "They say that a purple worm is not a baby purple dragon.", "VGhleSBzYXkgdGhhdCBhIHB1cnBsZSB3b3JtIGlzIG5vdCBhIGJhYnkgcHVycGxlIGRyYWdvbi4=" }, { "They say that a quivering blob tastes different than a gelatinous cube.", "VGhleSBzYXkgdGhhdCBhIHF1aXZlcmluZyBibG9iIHRhc3RlcyBkaWZmZXJlbnQgdGhhbiBhIGdlbGF0aW5vdXMgY3ViZS4=" }, { "They say that a runed broadsword named Stormbringer attracts vortices.", "VGhleSBzYXkgdGhhdCBhIHJ1bmVkIGJyb2Fkc3dvcmQgbmFtZWQgU3Rvcm1icmluZ2VyIGF0dHJhY3RzIHZvcnRpY2VzLg==" }, { "They say that a scroll of summoning has other names.", "VGhleSBzYXkgdGhhdCBhIHNjcm9sbCBvZiBzdW1tb25pbmcgaGFzIG90aGVyIG5hbWVzLg==" }, { "They say that a shaman can bestow blessings but usually doesn't.", "VGhleSBzYXkgdGhhdCBhIHNoYW1hbiBjYW4gYmVzdG93IGJsZXNzaW5ncyBidXQgdXN1YWxseSBkb2Vzbid0Lg==" }, { "They say that a shaman will bless you for an eye of newt and wing of bat.", "VGhleSBzYXkgdGhhdCBhIHNoYW1hbiB3aWxsIGJsZXNzIHlvdSBmb3IgYW4gZXllIG9mIG5ld3QgYW5kIHdpbmcgb2YgYmF0Lg==" }, { "They say that a shimmering gold shield is not a polished silver shield.", "VGhleSBzYXkgdGhhdCBhIHNoaW1tZXJpbmcgZ29sZCBzaGllbGQgaXMgbm90IGEgcG9saXNoZWQgc2lsdmVyIHNoaWVsZC4=" }, { "They say that a spear will hit a neo-otyugh. (Do YOU know what that is?)", "VGhleSBzYXkgdGhhdCBhIHNwZWFyIHdpbGwgaGl0IGEgbmVvLW90eXVnaC4gKERvIFlPVSBrbm93IHdoYXQgdGhhdCBpcz8p" }, { "They say that a spotted dragon is the ultimate shape changer.", "VGhleSBzYXkgdGhhdCBhIHNwb3R0ZWQgZHJhZ29uIGlzIHRoZSB1bHRpbWF0ZSBzaGFwZSBjaGFuZ2VyLg==" }, { "They say that a stethoscope is no good if you can only hear your heartbeat.", "VGhleSBzYXkgdGhhdCBhIHN0ZXRob3Njb3BlIGlzIG5vIGdvb2QgaWYgeW91IGNhbiBvbmx5IGhlYXIgeW91ciBoZWFydGJlYXQu" }, { "They say that a succubus named Suzy will sometimes warn you of danger.", "VGhleSBzYXkgdGhhdCBhIHN1Y2N1YnVzIG5hbWVkIFN1enkgd2lsbCBzb21ldGltZXMgd2FybiB5b3Ugb2YgZGFuZ2VyLg==" }, { "They say that a wand of cancellation is not like a wand of polymorph.", "VGhleSBzYXkgdGhhdCBhIHdhbmQgb2YgY2FuY2VsbGF0aW9uIGlzIG5vdCBsaWtlIGEgd2FuZCBvZiBwb2x5bW9ycGgu" }, { "They say that a wood golem named Pinocchio would be easy to control.", "VGhleSBzYXkgdGhhdCBhIHdvb2QgZ29sZW0gbmFtZWQgUGlub2NjaGlvIHdvdWxkIGJlIGVhc3kgdG8gY29udHJvbC4=" }, { "They say that after killing a dragon it's time for a change of scenery.", "VGhleSBzYXkgdGhhdCBhZnRlciBraWxsaW5nIGEgZHJhZ29uIGl0J3MgdGltZSBmb3IgYSBjaGFuZ2Ugb2Ygc2NlbmVyeS4=" }, { "They say that an amulet of strangulation is worse than ring around the collar.", "VGhleSBzYXkgdGhhdCBhbiBhbXVsZXQgb2Ygc3RyYW5ndWxhdGlvbiBpcyB3b3JzZSB0aGFuIHJpbmcgYXJvdW5kIHRoZSBjb2xsYXIu" }, { "They say that an attic is the best place to hide your toys.", "VGhleSBzYXkgdGhhdCBhbiBhdHRpYyBpcyB0aGUgYmVzdCBwbGFjZSB0byBoaWRlIHlvdXIgdG95cy4=" }, { "They say that an axe named Cleaver once belonged to a hacker named Beaver.", "VGhleSBzYXkgdGhhdCBhbiBheGUgbmFtZWQgQ2xlYXZlciBvbmNlIGJlbG9uZ2VkIHRvIGEgaGFja2VyIG5hbWVkIEJlYXZlci4=" }, { "They say that an eye of newt and a wing of bat are double the trouble.", "VGhleSBzYXkgdGhhdCBhbiBleWUgb2YgbmV3dCBhbmQgYSB3aW5nIG9mIGJhdCBhcmUgZG91YmxlIHRoZSB0cm91YmxlLg==" }, { "They say that an incubus named Izzy sometimes makes women feel sensitive.", "VGhleSBzYXkgdGhhdCBhbiBpbmN1YnVzIG5hbWVkIEl6enkgc29tZXRpbWVzIG1ha2VzIHdvbWVuIGZlZWwgc2Vuc2l0aXZlLg==" }, { "They say that an opulent throne room is rarely a place to wish you'd be in.", "VGhleSBzYXkgdGhhdCBhbiBvcHVsZW50IHRocm9uZSByb29tIGlzIHJhcmVseSBhIHBsYWNlIHRvIHdpc2ggeW91J2QgYmUgaW4u" }, { "They say that an unlucky hacker once had a nose bleed at an altar and died.", "VGhleSBzYXkgdGhhdCBhbiB1bmx1Y2t5IGhhY2tlciBvbmNlIGhhZCBhIG5vc2UgYmxlZWQgYXQgYW4gYWx0YXIgYW5kIGRpZWQu" }, { "They say that and they say this but they never say never, never!", "VGhleSBzYXkgdGhhdCBhbmQgdGhleSBzYXkgdGhpcyBidXQgdGhleSBuZXZlciBzYXkgbmV2ZXIsIG5ldmVyIQ==" }, { "They say that any quantum mechanic knows that speed kills.", "VGhleSBzYXkgdGhhdCBhbnkgcXVhbnR1bSBtZWNoYW5pYyBrbm93cyB0aGF0IHNwZWVkIGtpbGxzLg==" }, { "They say that applying a unicorn horn means you've missed the point.", "VGhleSBzYXkgdGhhdCBhcHBseWluZyBhIHVuaWNvcm4gaG9ybiBtZWFucyB5b3UndmUgbWlzc2VkIHRoZSBwb2ludC4=" }, { "They say that blue stones are radioactive, beware.", "VGhleSBzYXkgdGhhdCBibHVlIHN0b25lcyBhcmUgcmFkaW9hY3RpdmUsIGJld2FyZS4=" }, { "They say that building a dungeon is a team effort.", "VGhleSBzYXkgdGhhdCBidWlsZGluZyBhIGR1bmdlb24gaXMgYSB0ZWFtIGVmZm9ydC4=" }, { "They say that chaotic characters never get a kick out of altars.", "VGhleSBzYXkgdGhhdCBjaGFvdGljIGNoYXJhY3RlcnMgbmV2ZXIgZ2V0IGEga2ljayBvdXQgb2YgYWx0YXJzLg==" }, { "They say that collapsing a dungeon often creates a panic.", "VGhleSBzYXkgdGhhdCBjb2xsYXBzaW5nIGEgZHVuZ2VvbiBvZnRlbiBjcmVhdGVzIGEgcGFuaWMu" }, { "They say that counting your eggs before they hatch shows that you care.", "VGhleSBzYXkgdGhhdCBjb3VudGluZyB5b3VyIGVnZ3MgYmVmb3JlIHRoZXkgaGF0Y2ggc2hvd3MgdGhhdCB5b3UgY2FyZS4=" }, { "They say that dipping a bag of tricks in a fountain won't make it an icebox.", "VGhleSBzYXkgdGhhdCBkaXBwaW5nIGEgYmFnIG9mIHRyaWNrcyBpbiBhIGZvdW50YWluIHdvbid0IG1ha2UgaXQgYW4gaWNlYm94Lg==" }, { "They say that dipping an eel and brown mold in hot water makes bouillabaisse.", "VGhleSBzYXkgdGhhdCBkaXBwaW5nIGFuIGVlbCBhbmQgYnJvd24gbW9sZCBpbiBob3Qgd2F0ZXIgbWFrZXMgYm91aWxsYWJhaXNzZS4=" }, { "They say that donating a doubloon is extremely pious charity.", "VGhleSBzYXkgdGhhdCBkb25hdGluZyBhIGRvdWJsb29uIGlzIGV4dHJlbWVseSBwaW91cyBjaGFyaXR5Lg==" }, { "They say that eating royal jelly attracts grizzly owlbears.", "VGhleSBzYXkgdGhhdCBlYXRpbmcgcm95YWwgamVsbHkgYXR0cmFjdHMgZ3JpenpseSBvd2xiZWFycy4=" }, { "They say that eggs, pancakes and juice are just a mundane breakfast.", "VGhleSBzYXkgdGhhdCBlZ2dzLCBwYW5jYWtlcyBhbmQganVpY2UgYXJlIGp1c3QgYSBtdW5kYW5lIGJyZWFrZmFzdC4=" }, { "They say that everyone knows why Medusa stands alone in the dark.", "VGhleSBzYXkgdGhhdCBldmVyeW9uZSBrbm93cyB3aHkgTWVkdXNhIHN0YW5kcyBhbG9uZSBpbiB0aGUgZGFyay4=" }, { "They say that everyone wanted rec.games.hack to undergo a name change.", "VGhleSBzYXkgdGhhdCBldmVyeW9uZSB3YW50ZWQgcmVjLmdhbWVzLmhhY2sgdG8gdW5kZXJnbyBhIG5hbWUgY2hhbmdlLg==" }, { "They say that finding a winning strategy is a deliberate move on your part.", "VGhleSBzYXkgdGhhdCBmaW5kaW5nIGEgd2lubmluZyBzdHJhdGVneSBpcyBhIGRlbGliZXJhdGUgbW92ZSBvbiB5b3VyIHBhcnQu" }, { "They say that finding worthless glass is worth something.", "VGhleSBzYXkgdGhhdCBmaW5kaW5nIHdvcnRobGVzcyBnbGFzcyBpcyB3b3J0aCBzb21ldGhpbmcu" }, { "They say that fortune cookies are food for thought.", "VGhleSBzYXkgdGhhdCBmb3J0dW5lIGNvb2tpZXMgYXJlIGZvb2QgZm9yIHRob3VnaHQu" }, { "They say that gold is only wasted on a pet dragon.", "VGhleSBzYXkgdGhhdCBnb2xkIGlzIG9ubHkgd2FzdGVkIG9uIGEgcGV0IGRyYWdvbi4=" }, { "They say that good things come to those that wait.", "VGhleSBzYXkgdGhhdCBnb29kIHRoaW5ncyBjb21lIHRvIHRob3NlIHRoYXQgd2FpdC4=" }, { "They say that greased objects will slip out of monsters' hands.", "VGhleSBzYXkgdGhhdCBncmVhc2VkIG9iamVjdHMgd2lsbCBzbGlwIG91dCBvZiBtb25zdGVycycgaGFuZHMu" }, { "They say that if you can't spell then you'll wish you had a spell book.", "VGhleSBzYXkgdGhhdCBpZiB5b3UgY2FuJ3Qgc3BlbGwgdGhlbiB5b3UnbGwgd2lzaCB5b3UgaGFkIGEgc3BlbGwgYm9vay4=" }, { "They say that if you live by the sword, you'll die by the sword.", "VGhleSBzYXkgdGhhdCBpZiB5b3UgbGl2ZSBieSB0aGUgc3dvcmQsIHlvdSdsbCBkaWUgYnkgdGhlIHN3b3JkLg==" }, { "They say that if you play like a monster you'll have a better game.", "VGhleSBzYXkgdGhhdCBpZiB5b3UgcGxheSBsaWtlIGEgbW9uc3RlciB5b3UnbGwgaGF2ZSBhIGJldHRlciBnYW1lLg==" }, { "They say that if you sleep with a demon you might awake with a headache.", "VGhleSBzYXkgdGhhdCBpZiB5b3Ugc2xlZXAgd2l0aCBhIGRlbW9uIHlvdSBtaWdodCBhd2FrZSB3aXRoIGEgaGVhZGFjaGUu" }, { "They say that if you step on a crack you could break your mother's back.", "VGhleSBzYXkgdGhhdCBpZiB5b3Ugc3RlcCBvbiBhIGNyYWNrIHlvdSBjb3VsZCBicmVhayB5b3VyIG1vdGhlcidzIGJhY2su" }, { "They say that if you're invisible you can still be heard!", "VGhleSBzYXkgdGhhdCBpZiB5b3UncmUgaW52aXNpYmxlIHlvdSBjYW4gc3RpbGwgYmUgaGVhcmQh" }, { "They say that if you're lucky you can feel the runes on a scroll.", "VGhleSBzYXkgdGhhdCBpZiB5b3UncmUgbHVja3kgeW91IGNhbiBmZWVsIHRoZSBydW5lcyBvbiBhIHNjcm9sbC4=" }, { "They say that in the big picture gold is only small change.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgYmlnIHBpY3R1cmUgZ29sZCBpcyBvbmx5IHNtYWxsIGNoYW5nZS4=" }, { "They say that in the dungeon it's not what you know that really matters.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiBpdCdzIG5vdCB3aGF0IHlvdSBrbm93IHRoYXQgcmVhbGx5IG1hdHRlcnMu" }, { "They say that in the dungeon moon rocks are really dilithium crystals.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiBtb29uIHJvY2tzIGFyZSByZWFsbHkgZGlsaXRoaXVtIGNyeXN0YWxzLg==" }, { "They say that in the dungeon the boorish customer is never right.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB0aGUgYm9vcmlzaCBjdXN0b21lciBpcyBuZXZlciByaWdodC4=" }, { "They say that in the dungeon you don't need a watch to tell time.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3UgZG9uJ3QgbmVlZCBhIHdhdGNoIHRvIHRlbGwgdGltZS4=" }, { "They say that in the dungeon you need something old, new, burrowed and blue.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3UgbmVlZCBzb21ldGhpbmcgb2xkLCBuZXcsIGJ1cnJvd2VkIGFuZCBibHVlLg==" }, { "They say that in the dungeon you should always count your blessings.", "VGhleSBzYXkgdGhhdCBpbiB0aGUgZHVuZ2VvbiB5b3Ugc2hvdWxkIGFsd2F5cyBjb3VudCB5b3VyIGJsZXNzaW5ncy4=" }, { "They say that iron golem plate mail isn't worth wishing for.", "VGhleSBzYXkgdGhhdCBpcm9uIGdvbGVtIHBsYXRlIG1haWwgaXNuJ3Qgd29ydGggd2lzaGluZyBmb3Iu" }, { "They say that it takes four quarterstaffs to make one staff.", "VGhleSBzYXkgdGhhdCBpdCB0YWtlcyBmb3VyIHF1YXJ0ZXJzdGFmZnMgdG8gbWFrZSBvbmUgc3RhZmYu" }, { "They say that it's not over till the fat ladies sing.", "VGhleSBzYXkgdGhhdCBpdCdzIG5vdCBvdmVyIHRpbGwgdGhlIGZhdCBsYWRpZXMgc2luZy4=" }, { "They say that it's not over till the fat lady shouts `Off with its head'.", "VGhleSBzYXkgdGhhdCBpdCdzIG5vdCBvdmVyIHRpbGwgdGhlIGZhdCBsYWR5IHNob3V0cyBgT2ZmIHdpdGggaXRzIGhlYWQnLg==" }, { "They say that kicking a heavy statue is really a dumb move.", "VGhleSBzYXkgdGhhdCBraWNraW5nIGEgaGVhdnkgc3RhdHVlIGlzIHJlYWxseSBhIGR1bWIgbW92ZS4=" }, { "They say that kicking a valuable gem doesn't seem to make sense.", "VGhleSBzYXkgdGhhdCBraWNraW5nIGEgdmFsdWFibGUgZ2VtIGRvZXNuJ3Qgc2VlbSB0byBtYWtlIHNlbnNlLg==" }, { "They say that leprechauns know Latin and you should too.", "VGhleSBzYXkgdGhhdCBsZXByZWNoYXVucyBrbm93IExhdGluIGFuZCB5b3Ugc2hvdWxkIHRvby4=" }, { "They say that minotaurs get lost outside of the mazes.", "VGhleSBzYXkgdGhhdCBtaW5vdGF1cnMgZ2V0IGxvc3Qgb3V0c2lkZSBvZiB0aGUgbWF6ZXMu" }, { "They say that most trolls are born again.", "VGhleSBzYXkgdGhhdCBtb3N0IHRyb2xscyBhcmUgYm9ybiBhZ2Fpbi4=" }, { "They say that naming your cat Garfield will make you more attractive.", "VGhleSBzYXkgdGhhdCBuYW1pbmcgeW91ciBjYXQgR2FyZmllbGQgd2lsbCBtYWtlIHlvdSBtb3JlIGF0dHJhY3RpdmUu" }, { "They say that no one knows everything about everything in the dungeon.", "VGhleSBzYXkgdGhhdCBubyBvbmUga25vd3MgZXZlcnl0aGluZyBhYm91dCBldmVyeXRoaW5nIGluIHRoZSBkdW5nZW9uLg==" }, { "They say that no one plays NetHack just for the fun of it.", "VGhleSBzYXkgdGhhdCBubyBvbmUgcGxheXMgTmV0SGFjayBqdXN0IGZvciB0aGUgZnVuIG9mIGl0Lg==" }, { "They say that no one really subscribes to rec.games.roguelike.nethack.", "VGhleSBzYXkgdGhhdCBubyBvbmUgcmVhbGx5IHN1YnNjcmliZXMgdG8gcmVjLmdhbWVzLnJvZ3VlbGlrZS5uZXRoYWNrLg==" }, { "They say that no one will admit to starting a rumor.", "VGhleSBzYXkgdGhhdCBubyBvbmUgd2lsbCBhZG1pdCB0byBzdGFydGluZyBhIHJ1bW9yLg==" }, { "They say that nurses sometimes carry scalpels and never use them.", "VGhleSBzYXkgdGhhdCBudXJzZXMgc29tZXRpbWVzIGNhcnJ5IHNjYWxwZWxzIGFuZCBuZXZlciB1c2UgdGhlbS4=" }, { "They say that once you've met one wizard you've met them all.", "VGhleSBzYXkgdGhhdCBvbmNlIHlvdSd2ZSBtZXQgb25lIHdpemFyZCB5b3UndmUgbWV0IHRoZW0gYWxsLg==" }, { "They say that one troll is worth 10,000 newts.", "VGhleSBzYXkgdGhhdCBvbmUgdHJvbGwgaXMgd29ydGggMTAsMDAwIG5ld3RzLg==" }, { "They say that only David can find the zoo!", "VGhleSBzYXkgdGhhdCBvbmx5IERhdmlkIGNhbiBmaW5kIHRoZSB6b28h" }, { "They say that only angels play their harps for their pets.", "VGhleSBzYXkgdGhhdCBvbmx5IGFuZ2VscyBwbGF5IHRoZWlyIGhhcnBzIGZvciB0aGVpciBwZXRzLg==" }, { "They say that only big spenders carry gold.", "VGhleSBzYXkgdGhhdCBvbmx5IGJpZyBzcGVuZGVycyBjYXJyeSBnb2xkLg==" }, { "They say that orc shamans are healthy, wealthy and wise.", "VGhleSBzYXkgdGhhdCBvcmMgc2hhbWFucyBhcmUgaGVhbHRoeSwgd2VhbHRoeSBhbmQgd2lzZS4=" }, { "They say that playing NetHack is like walking into a death trap.", "VGhleSBzYXkgdGhhdCBwbGF5aW5nIE5ldEhhY2sgaXMgbGlrZSB3YWxraW5nIGludG8gYSBkZWF0aCB0cmFwLg==" }, { "They say that problem breathing is best treated by a proper diet.", "VGhleSBzYXkgdGhhdCBwcm9ibGVtIGJyZWF0aGluZyBpcyBiZXN0IHRyZWF0ZWQgYnkgYSBwcm9wZXIgZGlldC4=" }, { "They say that quaffing many potions of levitation can give you a headache.", "VGhleSBzYXkgdGhhdCBxdWFmZmluZyBtYW55IHBvdGlvbnMgb2YgbGV2aXRhdGlvbiBjYW4gZ2l2ZSB5b3UgYSBoZWFkYWNoZS4=" }, { "They say that queen bees get that way by eating royal jelly.", "VGhleSBzYXkgdGhhdCBxdWVlbiBiZWVzIGdldCB0aGF0IHdheSBieSBlYXRpbmcgcm95YWwgamVsbHku" }, { "They say that reading a scare monster scroll is the same as saying Elbereth.", "VGhleSBzYXkgdGhhdCByZWFkaW5nIGEgc2NhcmUgbW9uc3RlciBzY3JvbGwgaXMgdGhlIHNhbWUgYXMgc2F5aW5nIEVsYmVyZXRoLg==" }, { "They say that real hackers always are controlled.", "VGhleSBzYXkgdGhhdCByZWFsIGhhY2tlcnMgYWx3YXlzIGFyZSBjb250cm9sbGVkLg==" }, { "They say that real hackers never sleep.", "VGhleSBzYXkgdGhhdCByZWFsIGhhY2tlcnMgbmV2ZXIgc2xlZXAu" }, { "They say that shopkeepers are insured by Croesus himself!", "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBhcmUgaW5zdXJlZCBieSBDcm9lc3VzIGhpbXNlbGYh" }, { "They say that shopkeepers never carry more than 20 gold pieces, at night.", "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBuZXZlciBjYXJyeSBtb3JlIHRoYW4gMjAgZ29sZCBwaWVjZXMsIGF0IG5pZ2h0Lg==" }, { "They say that shopkeepers never sell blessed potions of invisibility.", "VGhleSBzYXkgdGhhdCBzaG9wa2VlcGVycyBuZXZlciBzZWxsIGJsZXNzZWQgcG90aW9ucyBvZiBpbnZpc2liaWxpdHku" }, { "They say that soldiers wear kid gloves and silly helmets.", "VGhleSBzYXkgdGhhdCBzb2xkaWVycyB3ZWFyIGtpZCBnbG92ZXMgYW5kIHNpbGx5IGhlbG1ldHMu" }, { "They say that some Kops are on the take.", "VGhleSBzYXkgdGhhdCBzb21lIEtvcHMgYXJlIG9uIHRoZSB0YWtlLg==" }, { "They say that some guards' palms can be greased.", "VGhleSBzYXkgdGhhdCBzb21lIGd1YXJkcycgcGFsbXMgY2FuIGJlIGdyZWFzZWQu" }, { "They say that some monsters may kiss your boots to stop your drum playing.", "VGhleSBzYXkgdGhhdCBzb21lIG1vbnN0ZXJzIG1heSBraXNzIHlvdXIgYm9vdHMgdG8gc3RvcCB5b3VyIGRydW0gcGxheWluZy4=" }, { "They say that sometimes you can be the hit of the party when playing a horn.", "VGhleSBzYXkgdGhhdCBzb21ldGltZXMgeW91IGNhbiBiZSB0aGUgaGl0IG9mIHRoZSBwYXJ0eSB3aGVuIHBsYXlpbmcgYSBob3JuLg==" }, { "They say that the NetHack gods generally welcome your sacrifices.", "VGhleSBzYXkgdGhhdCB0aGUgTmV0SGFjayBnb2RzIGdlbmVyYWxseSB3ZWxjb21lIHlvdXIgc2FjcmlmaWNlcy4=" }, { "They say that the Three Rings are named Vilya, Nenya and Narya.", "VGhleSBzYXkgdGhhdCB0aGUgVGhyZWUgUmluZ3MgYXJlIG5hbWVkIFZpbHlhLCBOZW55YSBhbmQgTmFyeWEu" }, { "They say that the Wizard of Yendor has a death wish.", "VGhleSBzYXkgdGhhdCB0aGUgV2l6YXJkIG9mIFllbmRvciBoYXMgYSBkZWF0aCB3aXNoLg==" }, { "They say that the `hair of the dog' is sometimes an effective remedy.", "VGhleSBzYXkgdGhhdCB0aGUgYGhhaXIgb2YgdGhlIGRvZycgaXMgc29tZXRpbWVzIGFuIGVmZmVjdGl2ZSByZW1lZHku" }, { "They say that the best time to save your game is now before its too late.", "VGhleSBzYXkgdGhhdCB0aGUgYmVzdCB0aW1lIHRvIHNhdmUgeW91ciBnYW1lIGlzIG5vdyBiZWZvcmUgaXRzIHRvbyBsYXRlLg==" }, { "They say that the biggest obstacle in NetHack is your mind.", "VGhleSBzYXkgdGhhdCB0aGUgYmlnZ2VzdCBvYnN0YWNsZSBpbiBOZXRIYWNrIGlzIHlvdXIgbWluZC4=" }, { "They say that the gods are angry when they hit you with objects.", "VGhleSBzYXkgdGhhdCB0aGUgZ29kcyBhcmUgYW5ncnkgd2hlbiB0aGV5IGhpdCB5b3Ugd2l0aCBvYmplY3RzLg==" }, { "They say that the priesthood are specially favored by the gods.", "VGhleSBzYXkgdGhhdCB0aGUgcHJpZXN0aG9vZCBhcmUgc3BlY2lhbGx5IGZhdm9yZWQgYnkgdGhlIGdvZHMu" }, { "They say that the way to make a unicorn happy is to give it what it wants.", "VGhleSBzYXkgdGhhdCB0aGUgd2F5IHRvIG1ha2UgYSB1bmljb3JuIGhhcHB5IGlzIHRvIGdpdmUgaXQgd2hhdCBpdCB3YW50cy4=" }, { "They say that there are no black or white stones, only gray.", "VGhleSBzYXkgdGhhdCB0aGVyZSBhcmUgbm8gYmxhY2sgb3Igd2hpdGUgc3RvbmVzLCBvbmx5IGdyYXku" }, { "They say that there are no skeletons hence there are no skeleton keys.", "VGhleSBzYXkgdGhhdCB0aGVyZSBhcmUgbm8gc2tlbGV0b25zIGhlbmNlIHRoZXJlIGFyZSBubyBza2VsZXRvbiBrZXlzLg==" }, { "They say that there is a clever rogue in every hacker just dying to escape.", "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBhIGNsZXZlciByb2d1ZSBpbiBldmVyeSBoYWNrZXIganVzdCBkeWluZyB0byBlc2NhcGUu" }, { "They say that there is no such thing as free advice.", "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBubyBzdWNoIHRoaW5nIGFzIGZyZWUgYWR2aWNlLg==" }, { "They say that there is only one way to win at NetHack.", "VGhleSBzYXkgdGhhdCB0aGVyZSBpcyBvbmx5IG9uZSB3YXkgdG8gd2luIGF0IE5ldEhhY2su" }, { "They say that there once was a fearsome chaotic samurai named Luk No.", "VGhleSBzYXkgdGhhdCB0aGVyZSBvbmNlIHdhcyBhIGZlYXJzb21lIGNoYW90aWMgc2FtdXJhaSBuYW1lZCBMdWsgTm8u" }, { "They say that there was a time when cursed holy water wasn't water.", "VGhleSBzYXkgdGhhdCB0aGVyZSB3YXMgYSB0aW1lIHdoZW4gY3Vyc2VkIGhvbHkgd2F0ZXIgd2Fzbid0IHdhdGVyLg==" }, { "They say that there's no point in crying over a gray ooze.", "VGhleSBzYXkgdGhhdCB0aGVyZSdzIG5vIHBvaW50IGluIGNyeWluZyBvdmVyIGEgZ3JheSBvb3plLg==" }, { "They say that there's only hope left after you've opened Pandora's box.", "VGhleSBzYXkgdGhhdCB0aGVyZSdzIG9ubHkgaG9wZSBsZWZ0IGFmdGVyIHlvdSd2ZSBvcGVuZWQgUGFuZG9yYSdzIGJveC4=" }, { "They say that trapdoors should always be marked `Caution: Trap Door'.", "VGhleSBzYXkgdGhhdCB0cmFwZG9vcnMgc2hvdWxkIGFsd2F5cyBiZSBtYXJrZWQgYENhdXRpb246IFRyYXAgRG9vcicu" }, { "They say that using an amulet of change isn't a difficult operation.", "VGhleSBzYXkgdGhhdCB1c2luZyBhbiBhbXVsZXQgb2YgY2hhbmdlIGlzbid0IGEgZGlmZmljdWx0IG9wZXJhdGlvbi4=" }, { "They say that water walking boots are better if you are fast like Hermes.", "VGhleSBzYXkgdGhhdCB3YXRlciB3YWxraW5nIGJvb3RzIGFyZSBiZXR0ZXIgaWYgeW91IGFyZSBmYXN0IGxpa2UgSGVybWVzLg==" }, { "They say that when you wear a circular amulet you might resemble a troll.", "VGhleSBzYXkgdGhhdCB3aGVuIHlvdSB3ZWFyIGEgY2lyY3VsYXIgYW11bGV0IHlvdSBtaWdodCByZXNlbWJsZSBhIHRyb2xsLg==" }, { "They say that when you're hungry you can get a pizza in 30 moves or it's free.", "VGhleSBzYXkgdGhhdCB3aGVuIHlvdSdyZSBodW5ncnkgeW91IGNhbiBnZXQgYSBwaXp6YSBpbiAzMCBtb3ZlcyBvciBpdCdzIGZyZWUu" }, { "They say that when your god is angry you should try another one.", "VGhleSBzYXkgdGhhdCB3aGVuIHlvdXIgZ29kIGlzIGFuZ3J5IHlvdSBzaG91bGQgdHJ5IGFub3RoZXIgb25lLg==" }, { "They say that wielding a unicorn horn takes strength.", "VGhleSBzYXkgdGhhdCB3aWVsZGluZyBhIHVuaWNvcm4gaG9ybiB0YWtlcyBzdHJlbmd0aC4=" }, { "They say that with speed boots you never worry about hit and run accidents.", "VGhleSBzYXkgdGhhdCB3aXRoIHNwZWVkIGJvb3RzIHlvdSBuZXZlciB3b3JyeSBhYm91dCBoaXQgYW5kIHJ1biBhY2NpZGVudHMu" }, { "They say that you can defeat a killer bee with a unicorn horn.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIGRlZmVhdCBhIGtpbGxlciBiZWUgd2l0aCBhIHVuaWNvcm4gaG9ybi4=" }, { "They say that you can only cross the River Styx in Charon's boat.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkgY3Jvc3MgdGhlIFJpdmVyIFN0eXggaW4gQ2hhcm9uJ3MgYm9hdC4=" }, { "They say that you can only kill a lich once and then you'd better be careful.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkga2lsbCBhIGxpY2ggb25jZSBhbmQgdGhlbiB5b3UnZCBiZXR0ZXIgYmUgY2FyZWZ1bC4=" }, { "They say that you can only wish for things you've already had.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIG9ubHkgd2lzaCBmb3IgdGhpbmdzIHlvdSd2ZSBhbHJlYWR5IGhhZC4=" }, { "They say that you can train a cat by talking gently to it.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRyYWluIGEgY2F0IGJ5IHRhbGtpbmcgZ2VudGx5IHRvIGl0Lg==" }, { "They say that you can train a dog by talking firmly to it.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRyYWluIGEgZG9nIGJ5IHRhbGtpbmcgZmlybWx5IHRvIGl0Lg==" }, { "They say that you can trust your gold with the king.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuIHRydXN0IHlvdXIgZ29sZCB3aXRoIHRoZSBraW5nLg==" }, { "They say that you can't wipe your greasy bare hands on a blank scroll.", "VGhleSBzYXkgdGhhdCB5b3UgY2FuJ3Qgd2lwZSB5b3VyIGdyZWFzeSBiYXJlIGhhbmRzIG9uIGEgYmxhbmsgc2Nyb2xsLg==" }, { "They say that you cannot trust scrolls of rumor.", "VGhleSBzYXkgdGhhdCB5b3UgY2Fubm90IHRydXN0IHNjcm9sbHMgb2YgcnVtb3Iu" }, { "They say that you could fall head over heels for an energy vortex.", "VGhleSBzYXkgdGhhdCB5b3UgY291bGQgZmFsbCBoZWFkIG92ZXIgaGVlbHMgZm9yIGFuIGVuZXJneSB2b3J0ZXgu" }, { "They say that you need a key in order to open locked doors.", "VGhleSBzYXkgdGhhdCB5b3UgbmVlZCBhIGtleSBpbiBvcmRlciB0byBvcGVuIGxvY2tlZCBkb29ycy4=" }, { "They say that you need a mirror to notice a mimic in an antique shop.", "VGhleSBzYXkgdGhhdCB5b3UgbmVlZCBhIG1pcnJvciB0byBub3RpY2UgYSBtaW1pYyBpbiBhbiBhbnRpcXVlIHNob3Au" }, { "They say that you really can use a pick-axe unless you really can't.", "VGhleSBzYXkgdGhhdCB5b3UgcmVhbGx5IGNhbiB1c2UgYSBwaWNrLWF4ZSB1bmxlc3MgeW91IHJlYWxseSBjYW4ndC4=" }, { "They say that you should always store your tools in the cellar.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGFsd2F5cyBzdG9yZSB5b3VyIHRvb2xzIGluIHRoZSBjZWxsYXIu" }, { "They say that you should be careful while climbing the ladder to success.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGJlIGNhcmVmdWwgd2hpbGUgY2xpbWJpbmcgdGhlIGxhZGRlciB0byBzdWNjZXNzLg==" }, { "They say that you should call your armor `rustproof'.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIGNhbGwgeW91ciBhcm1vciBgcnVzdHByb29mJy4=" }, { "They say that you should name your dog Spuds to have a cool pet.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5hbWUgeW91ciBkb2cgU3B1ZHMgdG8gaGF2ZSBhIGNvb2wgcGV0Lg==" }, { "They say that you should name your weapon after your first monster kill.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5hbWUgeW91ciB3ZWFwb24gYWZ0ZXIgeW91ciBmaXJzdCBtb25zdGVyIGtpbGwu" }, { "They say that you should never introduce a rope golem to a succubus.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIGludHJvZHVjZSBhIHJvcGUgZ29sZW0gdG8gYSBzdWNjdWJ1cy4=" }, { "They say that you should never sleep near invisible ring wraiths.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIHNsZWVwIG5lYXIgaW52aXNpYmxlIHJpbmcgd3JhaXRocy4=" }, { "They say that you should never try to leave the dungeon with a bag of gems.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIG5ldmVyIHRyeSB0byBsZWF2ZSB0aGUgZHVuZ2VvbiB3aXRoIGEgYmFnIG9mIGdlbXMu" }, { "They say that you should remove your armor before sitting on a throne.", "VGhleSBzYXkgdGhhdCB5b3Ugc2hvdWxkIHJlbW92ZSB5b3VyIGFybW9yIGJlZm9yZSBzaXR0aW5nIG9uIGEgdGhyb25lLg==" }, { "This fortune cookie is copy protected.", "VGhpcyBmb3J0dW5lIGNvb2tpZSBpcyBjb3B5IHByb3RlY3RlZC4=" }, { "This fortune cookie is the property of Fortune Cookies, Inc.", "VGhpcyBmb3J0dW5lIGNvb2tpZSBpcyB0aGUgcHJvcGVydHkgb2YgRm9ydHVuZSBDb29raWVzLCBJbmMu" }, { "Tired? Try a scroll of charging on yourself.", "VGlyZWQ/IFRyeSBhIHNjcm9sbCBvZiBjaGFyZ2luZyBvbiB5b3Vyc2VsZi4=" }, { "To achieve the next higher rating, you need 3 more points.", "VG8gYWNoaWV2ZSB0aGUgbmV4dCBoaWdoZXIgcmF0aW5nLCB5b3UgbmVlZCAzIG1vcmUgcG9pbnRzLg==" }, { "To reach heaven, escape the dungeon while wearing a ring of levitation.", "VG8gcmVhY2ggaGVhdmVuLCBlc2NhcGUgdGhlIGR1bmdlb24gd2hpbGUgd2VhcmluZyBhIHJpbmcgb2YgbGV2aXRhdGlvbi4=" }, { "Tourists wear shirts loud enough to wake the dead.", "VG91cmlzdHMgd2VhciBzaGlydHMgbG91ZCBlbm91Z2ggdG8gd2FrZSB0aGUgZGVhZC4=" }, { "Try calling your katana Moulinette.", "VHJ5IGNhbGxpbmcgeW91ciBrYXRhbmEgTW91bGluZXR0ZS4=" }, { "Ulch! That meat was painted!", "VWxjaCEgVGhhdCBtZWF0IHdhcyBwYWludGVkIQ==" }, { "Unfortunately, this message was left intentionally blank.", "VW5mb3J0dW5hdGVseSwgdGhpcyBtZXNzYWdlIHdhcyBsZWZ0IGludGVudGlvbmFsbHkgYmxhbmsu" }, { "Using a morning star in the evening has no effect.", "VXNpbmcgYSBtb3JuaW5nIHN0YXIgaW4gdGhlIGV2ZW5pbmcgaGFzIG5vIGVmZmVjdC4=" }, { "Want a hint? Zap a wand of make invisible on your weapon!", "V2FudCBhIGhpbnQ/IFphcCBhIHdhbmQgb2YgbWFrZSBpbnZpc2libGUgb24geW91ciB3ZWFwb24h" }, { "Want to ascend in a hurry? Apply at Gizmonic Institute.", "V2FudCB0byBhc2NlbmQgaW4gYSBodXJyeT8gQXBwbHkgYXQgR2l6bW9uaWMgSW5zdGl0dXRlLg==" }, { "Wanted: shopkeepers. Send a scroll of mail to Mage of Yendor/Level 35/Dungeon.", "V2FudGVkOiBzaG9wa2VlcGVycy4gU2VuZCBhIHNjcm9sbCBvZiBtYWlsIHRvIE1hZ2Ugb2YgWWVuZG9yL0xldmVsIDM1L0R1bmdlb24u" }, { "Warning: fortune reading can be hazardous to your health.", "V2FybmluZzogZm9ydHVuZSByZWFkaW5nIGNhbiBiZSBoYXphcmRvdXMgdG8geW91ciBoZWFsdGgu" }, { "We have new ways of detecting treachery...", "V2UgaGF2ZSBuZXcgd2F5cyBvZiBkZXRlY3RpbmcgdHJlYWNoZXJ5Li4u" }, { "Wet towels make great weapons!", "V2V0IHRvd2VscyBtYWtlIGdyZWF0IHdlYXBvbnMh" }, { "What a pity, you cannot read it!", "V2hhdCBhIHBpdHksIHlvdSBjYW5ub3QgcmVhZCBpdCE=" }, { "When a piercer drops in on you, you will be tempted to hit the ceiling!", "V2hlbiBhIHBpZXJjZXIgZHJvcHMgaW4gb24geW91LCB5b3Ugd2lsbCBiZSB0ZW1wdGVkIHRvIGhpdCB0aGUgY2VpbGluZyE=" }, { "When in a maze follow the right wall and you will never get lost.", "V2hlbiBpbiBhIG1hemUgZm9sbG93IHRoZSByaWdodCB3YWxsIGFuZCB5b3Ugd2lsbCBuZXZlciBnZXQgbG9zdC4=" }, { "When you have a key, you don't have to wait for the guard.", "V2hlbiB5b3UgaGF2ZSBhIGtleSwgeW91IGRvbid0IGhhdmUgdG8gd2FpdCBmb3IgdGhlIGd1YXJkLg==" }, { "Why are you wasting time reading fortunes?", "V2h5IGFyZSB5b3Ugd2FzdGluZyB0aW1lIHJlYWRpbmcgZm9ydHVuZXM/" }, { "Wish for a master key and open the Magic Memory Vault!", "V2lzaCBmb3IgYSBtYXN0ZXIga2V5IGFuZCBvcGVuIHRoZSBNYWdpYyBNZW1vcnkgVmF1bHQh" }, { "Wizard expects every monster to do its duty.", "V2l6YXJkIGV4cGVjdHMgZXZlcnkgbW9uc3RlciB0byBkbyBpdHMgZHV0eS4=" }, { "Wow! You could've had a potion of fruit juice!", "V293ISBZb3UgY291bGQndmUgaGFkIGEgcG90aW9uIG9mIGZydWl0IGp1aWNlIQ==" }, { "Yet Another Silly Message (YASM).", "WWV0IEFub3RoZXIgU2lsbHkgTWVzc2FnZSAoWUFTTSku" }, { "You are destined to be misled by a fortune.", "WW91IGFyZSBkZXN0aW5lZCB0byBiZSBtaXNsZWQgYnkgYSBmb3J0dW5lLg==" }, { "You can get a genuine Amulet of Yendor by doing the following: --More--", "WW91IGNhbiBnZXQgYSBnZW51aW5lIEFtdWxldCBvZiBZZW5kb3IgYnkgZG9pbmcgdGhlIGZvbGxvd2luZzogLS1Nb3JlLS0=" }, { "You can protect yourself from black dragons by doing the following: --More--", "WW91IGNhbiBwcm90ZWN0IHlvdXJzZWxmIGZyb20gYmxhY2sgZHJhZ29ucyBieSBkb2luZyB0aGUgZm9sbG93aW5nOiAtLU1vcmUtLQ==" }, { "You can't get by the snake.", "WW91IGNhbid0IGdldCBieSB0aGUgc25ha2Uu" }, { "You feel like someone is pulling your leg.", "WW91IGZlZWwgbGlrZSBzb21lb25lIGlzIHB1bGxpbmcgeW91ciBsZWcu" }, { "You have to outwit the Sphynx or pay her.", "WW91IGhhdmUgdG8gb3V0d2l0IHRoZSBTcGh5bnggb3IgcGF5IGhlci4=" }, { "You hear the fortune cookie's hissing!", "WW91IGhlYXIgdGhlIGZvcnR1bmUgY29va2llJ3MgaGlzc2luZyE=" }, { "You may get rich selling letters, but beware of being blackmailed!", "WW91IG1heSBnZXQgcmljaCBzZWxsaW5nIGxldHRlcnMsIGJ1dCBiZXdhcmUgb2YgYmVpbmcgYmxhY2ttYWlsZWQh" }, { "You offend Shai-Hulud by sheathing your crysknife without having drawn blood.", "WW91IG9mZmVuZCBTaGFpLUh1bHVkIGJ5IHNoZWF0aGluZyB5b3VyIGNyeXNrbmlmZSB3aXRob3V0IGhhdmluZyBkcmF3biBibG9vZC4=" }, { "You swallowed the fortune!", "WW91IHN3YWxsb3dlZCB0aGUgZm9ydHVuZSE=" }, { "You want to regain strength? Two levels ahead is a guesthouse!", "WW91IHdhbnQgdG8gcmVnYWluIHN0cmVuZ3RoPyBUd28gbGV2ZWxzIGFoZWFkIGlzIGEgZ3Vlc3Rob3VzZSE=" }, { "You will encounter a tall, dark, and gruesome creature...", "WW91IHdpbGwgZW5jb3VudGVyIGEgdGFsbCwgZGFyaywgYW5kIGdydWVzb21lIGNyZWF0dXJlLi4u" }, { "The End", "VGhlIEVuZA==" } }; /* PL_Base64Encode, random strings */ PRBool test_004(void) { int i; char result[ 4096 ]; printf("Test 004 (PL_Base64Encode, random strings) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 plen = PL_strlen(array[i].plaintext); PRUint32 clen = ((plen + 2)/3)*4; char *rv = PL_Base64Encode(array[i].plaintext, plen, result); if( rv != result ) { printf("FAIL\n\t(%d): return value\n", i); return PR_FALSE; } if( 0 != PL_strncmp(result, array[i].cyphertext, clen) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n", i, array[i].plaintext, array[i].cyphertext, clen, result); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, single characters, malloc */ PRBool test_005(void) { PRUint32 a, b; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 005 (PL_Base64Encode, single characters, malloc) ..."); fflush(stdout); plain[1] = plain[2] = plain[3] = (unsigned char)0; cypher[2] = cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (unsigned char)(a * 4 + b); cypher[1] = base[(b * 16)]; rv = PL_Base64Encode((char *)plain, 1, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d): no return value\n", a, b); return PR_FALSE; } if( 0 != PL_strcmp((char *)cypher, rv) ) { printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n", a, b, cypher, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, double characters, malloc */ PRBool test_006(void) { PRUint32 a, b, c, d; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 006 (PL_Base64Encode, double characters, malloc) ..."); fflush(stdout); plain[2] = plain[3] = (unsigned char)0; cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; cypher[2] = base[d*4]; rv = PL_Base64Encode((char *)plain, 2, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d); return PR_FALSE; } if( 0 != PL_strcmp((char *)cypher, rv) ) { printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n", a, b, c, d, cypher, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, triple characters, malloc */ PRBool test_007(void) { PRUint32 a, b, c, d, e, f; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 007 (PL_Base64Encode, triple characters, malloc) ..."); fflush(stdout); cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; for( e = 0; e < 4; e++ ) { cypher[2] = base[d*4 + e]; for( f = 0; f < 64; f++ ) { plain[2] = e * 64 + f; cypher[3] = base[f]; rv = PL_Base64Encode((char *)plain, 3, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): no return value\n", a, b, c, d, e, f); return PR_FALSE; } if( 0 != PL_strcmp((char *)cypher, rv) ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.4s.\"\n", a, b, c, d, e, f, cypher, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, random strings, malloc */ PRBool test_008(void) { int i; printf("Test 008 (PL_Base64Encode, random strings, malloc) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 plen = PL_strlen(array[i].plaintext); PRUint32 clen = ((plen + 2)/3)*4; char *rv = PL_Base64Encode(array[i].plaintext, plen, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d): no return value\n", i); return PR_FALSE; } if( 0 != PL_strcmp(rv, array[i].cyphertext) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n", i, array[i].plaintext, array[i].cyphertext, rv); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, single characters */ PRBool test_009(void) { PRUint32 a, b; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 009 (PL_Base64Decode, single characters, equals) ..."); fflush(stdout); plain[1] = plain[2] = plain[3] = (unsigned char)0; cypher[2] = cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (unsigned char)(a * 4 + b); cypher[1] = base[(b * 16)]; rv = PL_Base64Decode((char *)cypher, 4, result); if( rv != result ) { printf("FAIL\n\t(%d, %d): return value\n", a, b); return PR_FALSE; } if( 0 != PL_strncmp((char *)plain, result, 1) ) { printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.1s.\"\n", a, b, plain, result); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, single characters */ PRBool test_010(void) { PRUint32 a, b; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 010 (PL_Base64Decode, single characters, no equals) ..."); fflush(stdout); plain[1] = plain[2] = plain[3] = (unsigned char)0; cypher[2] = cypher[3] = (unsigned char)0; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (unsigned char)(a * 4 + b); cypher[1] = base[(b * 16)]; rv = PL_Base64Decode((char *)cypher, 2, result); if( rv != result ) { printf("FAIL\n\t(%d, %d): return value\n", a, b); return PR_FALSE; } if( 0 != PL_strncmp((char *)plain, result, 1) ) { printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%.1s.\"\n", a, b, plain, result); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, double characters */ PRBool test_011(void) { PRUint32 a, b, c, d; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 011 (PL_Base64Decode, double characters, equals) ..."); fflush(stdout); plain[2] = plain[3] = (unsigned char)0; cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; cypher[2] = base[d*4]; rv = PL_Base64Decode((char *)cypher, 4, result); if( rv != result ) { printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d); return PR_FALSE; } if( 0 != PL_strncmp((char *)plain, result, 2) ) { printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.2s.\"\n", a, b, c, d, plain, result); return PR_FALSE; } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, double characters */ PRBool test_012(void) { PRUint32 a, b, c, d; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 012 (PL_Base64Decode, double characters, no equals) ..."); fflush(stdout); plain[2] = plain[3] = (unsigned char)0; cypher[3] = (unsigned char)0; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; cypher[2] = base[d*4]; rv = PL_Base64Decode((char *)cypher, 3, result); if( rv != result ) { printf("FAIL\n\t(%d, %d, %d, %d): return value\n", a, b, c, d); return PR_FALSE; } if( 0 != PL_strncmp((char *)plain, result, 2) ) { printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%.2s.\"\n", a, b, c, d, cypher, result); return PR_FALSE; } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, triple characters */ PRBool test_013(void) { PRUint32 a, b, c, d, e, f; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char result[ 8 ]; char *rv; printf("Test 013 (PL_Base64Decode, triple characters) ..."); fflush(stdout); cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; for( e = 0; e < 4; e++ ) { cypher[2] = base[d*4 + e]; for( f = 0; f < 64; f++ ) { plain[2] = e * 64 + f; cypher[3] = base[f]; rv = PL_Base64Decode((char *)cypher, 4, result); if( rv != result ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): return value\n", a, b, c, d, e, f); return PR_FALSE; } if( 0 != PL_strncmp((char *)plain, result, 3) ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.3s.\"\n", a, b, c, d, e, f, plain, result); return PR_FALSE; } } } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, random strings */ PRBool test_014(void) { int i; char result[ 4096 ]; printf("Test 014 (PL_Base64Decode, random strings, equals) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen = PL_strlen(array[i].cyphertext); PRUint32 plen = (clen * 3) / 4; char *rv = PL_Base64Decode(array[i].cyphertext, clen, result); if( rv != result ) { printf("FAIL\n\t(%d): return value\n", i); return PR_FALSE; } if( 0 == (clen & 3) ) { if( '=' == array[i].cyphertext[clen-1] ) { if( '=' == array[i].cyphertext[clen-2] ) { plen -= 2; } else { plen -= 1; } } } if( 0 != PL_strncmp(result, array[i].plaintext, plen) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n", i, array[i].cyphertext, array[i].plaintext, plen, result); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, random strings */ PRBool test_015(void) { int i; char buffer[ 4096 ]; char result[ 4096 ]; char *rv; printf("Test 015 (PL_Base64Decode, random strings, no equals) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen, plen; PL_strcpy(buffer, array[i].cyphertext); clen = PL_strlen(buffer); if( 0 == (clen & 3) ) { if( '=' == buffer[clen-1] ) { if( '=' == buffer[clen-2] ) { buffer[clen-2] = buffer[clen-1] = (char)0; clen -= 2; } else { buffer[clen-1] = (char)0; clen -= 1; } } } plen = (clen * 3) / 4; rv = PL_Base64Decode(buffer, clen, result); if( rv != result ) { printf("FAIL\n\t(%d): return value\n", i); return PR_FALSE; } if( 0 != PL_strncmp(result, array[i].plaintext, plen) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n", i, array[i].cyphertext, array[i].plaintext, plen, result); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, single characters, malloc */ PRBool test_016(void) { PRUint32 a, b; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 016 (PL_Base64Decode, single characters, equals, malloc) ..."); fflush(stdout); plain[1] = plain[2] = plain[3] = (unsigned char)0; cypher[2] = cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (unsigned char)(a * 4 + b); cypher[1] = base[(b * 16)]; rv = PL_Base64Decode((char *)cypher, 4, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d): no return value\n", a, b); return PR_FALSE; } if( 0 != PL_strcmp((char *)plain, rv) ) { printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n", a, b, plain, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, single characters, malloc */ PRBool test_017(void) { PRUint32 a, b; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 017 (PL_Base64Decode, single characters, no equals, malloc) ..."); fflush(stdout); plain[1] = plain[2] = plain[3] = (unsigned char)0; cypher[2] = cypher[3] = (unsigned char)0; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (unsigned char)(a * 4 + b); cypher[1] = base[(b * 16)]; rv = PL_Base64Decode((char *)cypher, 2, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d): no return value\n", a, b); return PR_FALSE; } if( 0 != PL_strcmp((char *)plain, rv) ) { printf("FAIL\n\t(%d, %d): expected \"%s,\" got \"%s.\"\n", a, b, plain, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, double characters, malloc */ PRBool test_018(void) { PRUint32 a, b, c, d; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 018 (PL_Base64Decode, double characters, equals, malloc) ..."); fflush(stdout); plain[2] = plain[3] = (unsigned char)0; cypher[3] = (unsigned char)'='; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; cypher[2] = base[d*4]; rv = PL_Base64Decode((char *)cypher, 4, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d); return PR_FALSE; } if( 0 != PL_strcmp((char *)plain, rv) ) { printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n", a, b, c, d, plain, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, double characters, malloc */ PRBool test_019(void) { PRUint32 a, b, c, d; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 019 (PL_Base64Decode, double characters, no equals, malloc) ..."); fflush(stdout); plain[2] = plain[3] = (unsigned char)0; cypher[3] = (unsigned char)0; cypher[4] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; cypher[2] = base[d*4]; rv = PL_Base64Decode((char *)cypher, 3, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d, %d, %d): no return value\n", a, b, c, d); return PR_FALSE; } if( 0 != PL_strcmp((char *)plain, rv) ) { printf("FAIL\n\t(%d, %d, %d, %d): expected \"%s,\" got \"%s.\"\n", a, b, c, d, cypher, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, triple characters, malloc */ PRBool test_020(void) { PRUint32 a, b, c, d, e, f; unsigned char plain[ 4 ]; unsigned char cypher[ 5 ]; char *rv; printf("Test 020 (PL_Base64Decode, triple characters, malloc) ..."); fflush(stdout); cypher[4] = (unsigned char)0; plain[3] = (unsigned char)0; for( a = 0; a < 64; a++ ) { cypher[0] = base[a]; for( b = 0; b < 4; b++ ) { plain[0] = (a*4) + b; for( c = 0; c < 16; c++ ) { cypher[1] = base[b*16 + c]; for( d = 0; d < 16; d++ ) { plain[1] = c*16 + d; for( e = 0; e < 4; e++ ) { cypher[2] = base[d*4 + e]; for( f = 0; f < 64; f++ ) { plain[2] = e * 64 + f; cypher[3] = base[f]; rv = PL_Base64Decode((char *)cypher, 4, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): no return value\n", a, b, c, d, e, f); return PR_FALSE; } if( 0 != PL_strcmp((char *)plain, rv) ) { printf("FAIL\n\t(%d, %d, %d, %d, %d, %d): expected \"%s,\" got \"%.3s.\"\n", a, b, c, d, e, f, plain, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, random strings, malloc */ PRBool test_021(void) { int i; printf("Test 021 (PL_Base64Decode, random strings, equals, malloc) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen = PL_strlen(array[i].cyphertext); char *rv = PL_Base64Decode(array[i].cyphertext, clen, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d): no return value\n", i); return PR_FALSE; } if( 0 != PL_strcmp(rv, array[i].plaintext) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n", i, array[i].cyphertext, array[i].plaintext, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, random strings, malloc */ PRBool test_022(void) { int i; char buffer[ 4096 ]; char *rv; printf("Test 022 (PL_Base64Decode, random strings, no equals, malloc) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen; PL_strcpy(buffer, array[i].cyphertext); clen = PL_strlen(buffer); if( 0 == (clen & 3) ) { if( '=' == buffer[clen-1] ) { if( '=' == buffer[clen-2] ) { buffer[clen-2] = buffer[clen-1] = (char)0; clen -= 2; } else { buffer[clen-1] = (char)0; clen -= 1; } } } rv = PL_Base64Decode(buffer, clen, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d): no return value\n", i); return PR_FALSE; } if( 0 != PL_strcmp(rv, array[i].plaintext) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n", i, array[i].cyphertext, array[i].plaintext, rv); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, random strings */ PRBool test_023(void) { int i; char result[ 4096 ]; printf("Test 023 (PL_Base64Encode, random strings, strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 plen = PL_strlen(array[i].plaintext); PRUint32 clen = ((plen + 2)/3)*4; char *rv = PL_Base64Encode(array[i].plaintext, 0, result); if( rv != result ) { printf("FAIL\n\t(%d): return value\n", i); return PR_FALSE; } if( 0 != PL_strncmp(result, array[i].cyphertext, clen) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n", i, array[i].plaintext, array[i].cyphertext, clen, result); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, random strings, malloc */ PRBool test_024(void) { int i; printf("Test 024 (PL_Base64Encode, random strings, malloc, strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 plen = PL_strlen(array[i].plaintext); PRUint32 clen = ((plen + 2)/3)*4; char *rv = PL_Base64Encode(array[i].plaintext, 0, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d): no return value\n", i); return PR_FALSE; } if( 0 != PL_strcmp(rv, array[i].cyphertext) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n", i, array[i].plaintext, array[i].cyphertext, rv); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, random strings */ PRBool test_025(void) { int i; char result[ 4096 ]; printf("Test 025 (PL_Base64Decode, random strings, equals, strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen = PL_strlen(array[i].cyphertext); PRUint32 plen = (clen * 3) / 4; char *rv = PL_Base64Decode(array[i].cyphertext, 0, result); if( rv != result ) { printf("FAIL\n\t(%d): return value\n", i); return PR_FALSE; } if( 0 == (clen & 3) ) { if( '=' == array[i].cyphertext[clen-1] ) { if( '=' == array[i].cyphertext[clen-2] ) { plen -= 2; } else { plen -= 1; } } } if( 0 != PL_strncmp(result, array[i].plaintext, plen) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n", i, array[i].cyphertext, array[i].plaintext, plen, result); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, random strings */ PRBool test_026(void) { int i; char buffer[ 4096 ]; char result[ 4096 ]; char *rv; printf("Test 026 (PL_Base64Decode, random strings, no equals, strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen, plen; PL_strcpy(buffer, array[i].cyphertext); clen = PL_strlen(buffer); if( 0 == (clen & 3) ) { if( '=' == buffer[clen-1] ) { if( '=' == buffer[clen-2] ) { buffer[clen-2] = buffer[clen-1] = (char)0; clen -= 2; } else { buffer[clen-1] = (char)0; clen -= 1; } } } plen = (clen * 3) / 4; rv = PL_Base64Decode(buffer, 0, result); if( rv != result ) { printf("FAIL\n\t(%d): return value\n", i); return PR_FALSE; } if( 0 != PL_strncmp(result, array[i].plaintext, plen) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%.*s.\"\n", i, array[i].cyphertext, array[i].plaintext, plen, result); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Decode, random strings, malloc */ PRBool test_027(void) { int i; printf("Test 027 (PL_Base64Decode, random strings, equals, malloc, strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen = PL_strlen(array[i].cyphertext); char *rv = PL_Base64Decode(array[i].cyphertext, 0, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d): no return value\n", i); return PR_FALSE; } if( 0 != PL_strcmp(rv, array[i].plaintext) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n", i, array[i].cyphertext, array[i].plaintext, rv); PR_DELETE(rv); return PR_FALSE; } PR_DELETE(rv); } printf("PASS\n"); return PR_TRUE; } /* PL_Base64Encode, random strings, malloc */ PRBool test_028(void) { int i; char buffer[ 4096 ]; char *rv; printf("Test 028 (PL_Base64Decode, random strings, no equals, malloc, strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRUint32 clen; PL_strcpy(buffer, array[i].cyphertext); clen = PL_strlen(buffer); if( 0 == (clen & 3) ) { if( '=' == buffer[clen-1] ) { if( '=' == buffer[clen-2] ) { buffer[clen-2] = buffer[clen-1] = (char)0; clen -= 2; } else { buffer[clen-1] = (char)0; clen -= 1; } } } rv = PL_Base64Decode(buffer, 0, (char *)0); if( (char *)0 == rv ) { printf("FAIL\n\t(%d): no return value\n", i); return PR_FALSE; } if( 0 != PL_strcmp(rv, array[i].plaintext) ) { printf("FAIL\n\t(%d, \"%s\"): expected \n\"%s,\" got \n\"%s.\"\n", i, array[i].cyphertext, array[i].plaintext, rv); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } int main ( int argc, char *argv[] ) { printf("Testing the Portable Library base64 functions:\n"); printf("(warning: the \"triple characters\" tests are slow)\n"); if( 1 && test_001() && test_002() && test_003() && test_004() && test_005() && test_006() && test_007() && test_008() && test_009() && test_010() && test_011() && test_012() && test_013() && test_014() && test_015() && test_016() && test_017() && test_018() && test_019() && test_020() && test_021() && test_022() && test_023() && test_024() && test_025() && test_026() && test_027() && test_028() ) { printf("Suite passed.\n"); return 0; } else { printf("Suite failed.\n"); return 1; } /*NOTREACHED*/ } nspr-4.11/nspr/lib/tests/getopt.c0000644000000000000000000000232512623070344015112 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include "nspr.h" #include "plgetopt.h" static const PLLongOpt optArray[] = { { "longa", 'a' , PR_TRUE }, { "longb", 'b' , PR_TRUE }, { "longc", 'c' , PR_FALSE }, { "longd", 'd' | 0x100, PR_TRUE }, { "longe", 'e' | 0x100, PR_FALSE }, { NULL, } }; int main(int argc, char **argv) { PLOptState *opt; PLOptStatus ostat; opt = PL_CreateLongOptState(argc, argv, "a:b:c", optArray); while (PL_OPT_OK == (ostat = PL_GetNextOpt(opt))) { if (opt->option == 0 && opt->longOptIndex < 0) printf("Positional parameter: \"%s\"\n", opt->value); else printf("%s option: %x (\'%c\', index %d), argument: \"%s\"\n", (ostat == PL_OPT_BAD) ? "BAD" : "GOOD", opt->longOption, opt->option ? opt->option : ' ', opt->longOptIndex, opt->value); } printf("last result was %s\n", (ostat == PL_OPT_BAD) ? "BAD" : "EOL"); PL_DestroyOptState(opt); return 0; } nspr-4.11/nspr/lib/tests/string.c0000644000000000000000000031743712623070344015133 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plstr.h" #include "nspr.h" #include /* PL_strlen */ PRBool test_001(void) { static struct { const char *str; PRUint32 len; } array[] = { { (const char *)0, 0 }, { "", 0 }, { "a", 1 }, { "abcdefg", 7 }, { "abcdefg\0hijk", 7 } }; int i; printf("Test 001 (PL_strlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { if( PL_strlen(array[i].str) != array[i].len ) { printf("FAIL (%d: %s->%d, %d)\n", i, array[i].str ? array[i].str : "(null)", PL_strlen(array[i].str), array[i].len); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_strnlen */ PRBool test_002(void) { static struct { const char *str; PRUint32 max; PRUint32 len; } array[] = { { (const char *)0, 0, 0 }, { (const char *)0, 12, 0 }, { "", 0, 0 }, { "", 12, 0 }, { "a", 0, 0 }, { "a", 1, 1 }, { "a", 12, 1 }, { "abcdefg", 0, 0 }, { "abcdefg", 1, 1 }, { "abcdefg", 7, 7 }, { "abcdefg", 12, 7 }, { "abcdefg\0hijk", 0, 0 }, { "abcdefg\0hijk", 1, 1 }, { "abcdefg\0hijk", 7, 7 }, { "abcdefg\0hijk", 12, 7 }, }; int i; printf("Test 002 (PL_strnlen) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { if( PL_strnlen(array[i].str, array[i].max) != array[i].len ) { printf("FAIL (%d: %s,%d->%d, %d)\n", i, array[i].str ? array[i].str : "(null)", array[i].max, PL_strnlen(array[i].str, array[i].max), array[i].len); return PR_FALSE; } } printf("PASS\n"); return PR_TRUE; } /* PL_strcpy */ PRBool test_003(void) { static char buffer[ 1024 ]; static struct { const char *str; char *dest; char *rv; PRBool comp; } array[] = { { (const char *)0, (char *)0, (char *)0, PR_FALSE }, { (const char *)0, buffer, (char *)0, PR_FALSE }, { "", (char *)0, (char *)0, PR_FALSE }, { "", buffer, buffer, PR_TRUE }, { "a", (char *)0, (char *)0, PR_FALSE }, { "a", buffer, buffer, PR_TRUE }, { "abcdefg", (char *)0, (char *)0, PR_FALSE }, { "abcdefg", buffer, buffer, PR_TRUE }, { "wxyz\0abcdefg", (char *)0, (char *)0, PR_FALSE }, { "wxyz\0abcdefg", buffer, buffer, PR_TRUE } }; int i; printf("Test 003 (PL_strcpy) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv; const char *a = array[i].str; const char *b = (const char *)array[i].dest; rv = PL_strcpy(array[i].dest, array[i].str); if( array[i].rv != rv ) { printf("FAIL %d: (0x%x, %s)->0x%x\n", i, array[i].dest, array[i].str ? array[i].str : "(null)", rv); return PR_FALSE; } if( array[i].comp ) { while( 1 ) { if( *a != *b ) { printf("FAIL %d: %s->%.32s\n", i, array[i].str ? array[i].str : "(null)", array[i].dest ? array[i].dest : "(null)"); return PR_FALSE; } if( (char)0 == *a ) break; a++; b++; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strncpy */ PRBool test_004(void) { static char buffer[ 1024 ]; static struct { const char *str; PRUint32 len; char *dest; char *rv; PRBool comp; const char *result; PRBool nulled; } array[] = { { (const char *)0, 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { (const char *)0, 0, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { (const char *)0, 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { (const char *)0, 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { (const char *)0, 1, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { (const char *)0, 7, buffer, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "", 1, buffer, buffer, PR_TRUE, "", PR_TRUE }, { "", 7, buffer, buffer, PR_TRUE, "", PR_TRUE }, { "a", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "a", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "a", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "a", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "b", 1, buffer, buffer, PR_TRUE, "b", PR_FALSE }, { "c", 7, buffer, buffer, PR_TRUE, "c", PR_TRUE }, { "de", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "de", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "de", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "de", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "fg", 1, buffer, buffer, PR_TRUE, "f", PR_FALSE }, { "hi", 7, buffer, buffer, PR_TRUE, "hi", PR_TRUE }, { "jklmnopq", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "jklmnopq", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "jklmnopq", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "jklmnopq", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "rstuvwxy", 1, buffer, buffer, PR_TRUE, "r", PR_FALSE }, { "zABCDEFG", 7, buffer, buffer, PR_TRUE, "zABCDEF", PR_FALSE }, { "a\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "a\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "a\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "a\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "b\0XXX", 1, buffer, buffer, PR_TRUE, "b", PR_FALSE }, { "c\0XXX", 7, buffer, buffer, PR_TRUE, "c", PR_TRUE }, { "de\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "de\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "de\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "de\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "fg\0XXX", 1, buffer, buffer, PR_TRUE, "f", PR_FALSE }, { "hi\0XXX", 7, buffer, buffer, PR_TRUE, "hi", PR_TRUE }, { "jklmnopq\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "jklmnopq\0XXX", 0, buffer, buffer, PR_FALSE, (const char *)0, PR_FALSE }, { "jklmnopq\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "jklmnopq\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0, PR_FALSE }, { "rstuvwxy\0XXX", 1, buffer, buffer, PR_TRUE, "r", PR_FALSE }, { "zABCDEFG\0XXX", 7, buffer, buffer, PR_TRUE, "zABCDEF", PR_FALSE }, }; int i; printf("Test 004 (PL_strncpy) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv; int j; for( j = 0; j < sizeof(buffer); j++ ) buffer[j] = '-'; rv = PL_strncpy(array[i].dest, array[i].str, array[i].len); if( array[i].rv != rv ) { printf("FAIL %d: (0x%x, %s, %lu)->0x%x\n", i, array[i].dest, array[i].str ? array[i].str : "(null)", array[i].len, rv); return PR_FALSE; } if( array[i].comp ) { const char *a = array[i].result; const char *b = array[i].dest; while( *a ) { if( *a != *b ) { printf("FAIL %d: %s != %.32s\n", i, array[i].result, array[i].dest); return PR_FALSE; } a++; b++; } if( array[i].nulled ) { if( *b != '\0' ) { printf("FAIL %d: not terminated\n", i); return PR_FALSE; } } else { if( *b != '-' ) { printf("FAIL %d: overstepped\n", i); return PR_FALSE; } } } } printf("PASS\n"); return PR_TRUE; } /* PL_strncpyz */ PRBool test_005(void) { static char buffer[ 1024 ]; static struct { const char *str; PRUint32 len; char *dest; char *rv; PRBool comp; const char *result; } array[] = { { (const char *)0, 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { (const char *)0, 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { (const char *)0, 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { (const char *)0, 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { (const char *)0, 1, buffer, (char *)0, PR_FALSE, (const char *)0 }, { (const char *)0, 7, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "", 1, buffer, buffer, PR_TRUE, "" }, { "", 7, buffer, buffer, PR_TRUE, "" }, { "a", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "a", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "a", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "a", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "b", 1, buffer, buffer, PR_TRUE, "" }, { "c", 7, buffer, buffer, PR_TRUE, "c" }, { "de", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "de", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "de", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "de", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "fg", 1, buffer, buffer, PR_TRUE, "" }, { "hi", 7, buffer, buffer, PR_TRUE, "hi" }, { "jklmnopq", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "jklmnopq", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "jklmnopq", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "jklmnopq", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "rstuvwxy", 1, buffer, buffer, PR_TRUE, "" }, { "zABCDEFG", 7, buffer, buffer, PR_TRUE, "zABCDE" }, { "a\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "a\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "a\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "a\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "b\0XXX", 1, buffer, buffer, PR_TRUE, "" }, { "c\0XXX", 7, buffer, buffer, PR_TRUE, "c" }, { "de\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "de\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "de\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "de\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "fg\0XXX", 1, buffer, buffer, PR_TRUE, "" }, { "hi\0XXX", 7, buffer, buffer, PR_TRUE, "hi" }, { "jklmnopq\0XXX", 0, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "jklmnopq\0XXX", 0, buffer, (char *)0, PR_FALSE, (const char *)0 }, { "jklmnopq\0XXX", 1, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "jklmnopq\0XXX", 7, (char *)0, (char *)0, PR_FALSE, (const char *)0 }, { "rstuvwxy\0XXX", 1, buffer, buffer, PR_TRUE, "" }, { "zABCDEFG\0XXX", 7, buffer, buffer, PR_TRUE, "zABCDE" }, }; int i; printf("Test 005 (PL_strncpyz) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv; int j; for( j = 0; j < sizeof(buffer); j++ ) buffer[j] = '-'; rv = PL_strncpyz(array[i].dest, array[i].str, array[i].len); if( array[i].rv != rv ) { printf("FAIL %d: (0x%x, %s, %lu)->0x%x\n", i, array[i].dest, array[i].str ? array[i].str : "(null)", array[i].len, rv); return PR_FALSE; } if( array[i].comp ) { const char *a = array[i].result; const char *b = array[i].dest; while( 1 ) { if( *a != *b ) { printf("FAIL %d: %s != %.32s\n", i, array[i].result, array[i].dest); return PR_FALSE; } if( (char)0 == *a ) break; a++; b++; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strdup */ PRBool test_006(void) { static const char *array[] = { (const char *)0, "", "a", "abcdefg" }; int i; printf("Test 006 (PL_strdup) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strdup(array[i]); if( (char *)0 == rv ) { printf("FAIL %d: 0x%x -> 0\n", i, array[i]); return PR_FALSE; } if( (const char *)0 == array[i] ) { if( (char)0 != *rv ) { printf("FAIL %d: (const char *)0 -> %.32s\n", i, rv); return PR_FALSE; } } else { const char *a = array[i]; const char *b = (const char *)rv; while( 1 ) { if( *a != *b ) { printf("FAIL %d: %s != %.32s\n", i, array[i], rv); return PR_FALSE; } if( (char)0 == *a ) break; a++; b++; } } PL_strfree(rv); } printf("PASS\n"); return PR_TRUE; } /* PL_strndup */ PRBool test_007(void) { static struct { const char *str; PRUint32 len; const char *result; } array[] = { { (const char *)0, 0, "" }, { (const char *)0, 1, "" }, { (const char *)0, 7, "" }, { "", 0, "" }, { "", 1, "" }, { "", 7, "" }, { "a", 0, "" }, { "a", 1, "a" }, { "a", 7, "a" }, { "ab", 0, "" }, { "ab", 1, "a" }, { "ab", 7, "ab" }, { "abcdefg", 0, "" }, { "abcdefg", 1, "a" }, { "abcdefg", 7, "abcdefg" }, { "abcdefghijk", 0, "" }, { "abcdefghijk", 1, "a" }, { "abcdefghijk", 7, "abcdefg" }, { "abcdef\0ghijk", 0, "" }, { "abcdef\0ghijk", 1, "a" }, { "abcdef\0ghijk", 7, "abcdef" } }; int i; printf("Test 007 (PL_strndup) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strndup(array[i].str, array[i].len); const char *a; const char *b; if( (char *)0 == rv ) { printf("FAIL %d: %s,%lu -> 0\n", i, array[i].str ? array[i].str : "(null)", array[i].len); return PR_FALSE; } a = array[i].result; b = (const char *)rv; while( 1 ) { if( *a != *b ) { printf("FAIL %d: %s != %.32s\n", i, array[i].result, rv); return PR_FALSE; } if( (char)0 == *a ) break; a++; b++; } free(rv); } printf("PASS\n"); return PR_TRUE; } /* PL_strcat */ PRBool test_008(void) { static struct { const char *first; const char *second; const char *result; } array[] = { { (const char *)0, (const char *)0, (const char *)0 }, { (const char *)0, "xyz", (const char *)0 }, { "", (const char *)0, "" }, { "", "", "" }, { "ab", "", "ab" }, { "cd", "ef", "cdef" }, { "gh\0X", "", "gh" }, { "ij\0X", "kl", "ijkl" }, { "mn\0X", "op\0X", "mnop" }, { "qr", "st\0X", "qrst" }, { "uv\0X", "wx\0X", "uvwx" } }; int i; printf("Test 008 (PL_strcat) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char buffer[ 1024 ]; int j; char *rv; for( j = 0; j < sizeof(buffer); j++ ) buffer[j] = '-'; if( (const char *)0 != array[i].first ) (void)PL_strcpy(buffer, array[i].first); rv = PL_strcat(((const char *)0 == array[i].first) ? (char *)0 : buffer, array[i].second); if( (const char *)0 == array[i].result ) { if( (char *)0 != rv ) { printf("FAIL %d: %s+%s -> %.32s, not zero\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s+%s -> null, not %s\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].result); return PR_FALSE; } else { const char *a = array[i].result; const char *b = (const char *)rv; while( 1 ) { if( *a != *b ) { printf("FAIL %d: %s+%s -> %.32s, not %s\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", rv, array[i].result); return PR_FALSE; } if( (char)0 == *a ) break; a++; b++; } } } } printf("PASS\n"); return PR_TRUE; } /* PL_strncat */ PRBool test_009(void) { static struct { const char *first; const char *second; PRUint32 length; PRBool nulled; const char *result; } array[] = { { (const char *)0, (const char *)0, 0, PR_FALSE, (const char *)0 }, { (const char *)0, (const char *)0, 1, PR_FALSE, (const char *)0 }, { (const char *)0, (const char *)0, 7, PR_FALSE, (const char *)0 }, { (const char *)0, "", 0, PR_FALSE, (const char *)0 }, { (const char *)0, "", 1, PR_FALSE, (const char *)0 }, { (const char *)0, "", 7, PR_FALSE, (const char *)0 }, { (const char *)0, "stuff", 0, PR_FALSE, (const char *)0 }, { (const char *)0, "stuff", 1, PR_FALSE, (const char *)0 }, { (const char *)0, "stuff", 7, PR_FALSE, (const char *)0 }, { "", (const char *)0, 0, PR_TRUE, "" }, { "", (const char *)0, 1, PR_TRUE, "" }, { "", (const char *)0, 7, PR_TRUE, "" }, { "", "", 0, PR_TRUE, "" }, { "", "", 1, PR_TRUE, "" }, { "", "", 7, PR_TRUE, "" }, { "", "abcdefgh", 0, PR_TRUE, "" }, { "", "abcdefgh", 1, PR_FALSE, "a" }, { "", "abcdefgh", 7, PR_FALSE, "abcdefg" }, { "xyz", (const char *)0, 0, PR_TRUE, "xyz" }, { "xyz", (const char *)0, 1, PR_TRUE, "xyz" }, { "xyz", (const char *)0, 7, PR_TRUE, "xyz" }, { "xyz", "", 0, PR_TRUE, "xyz" }, { "xyz", "", 1, PR_TRUE, "xyz" }, { "xyz", "", 7, PR_TRUE, "xyz" }, { "xyz", "abcdefgh", 0, PR_TRUE, "xyz" }, { "xyz", "abcdefgh", 1, PR_FALSE, "xyza" }, { "xyz", "abcdefgh", 7, PR_FALSE, "xyzabcdefg" } }; int i; printf("Test 009 (PL_strncat) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char buffer[ 1024 ]; int j; char *rv; for( j = 0; j < sizeof(buffer); j++ ) buffer[j] = '-'; if( (const char *)0 != array[i].first ) (void)PL_strcpy(buffer, array[i].first); rv = PL_strncat(((const char *)0 == array[i].first) ? (char *)0 : buffer, array[i].second, array[i].length); if( (const char *)0 == array[i].result ) { if( (char *)0 != rv ) { printf("FAIL %d: %s+%s/%lu -> %.32s, not zero\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s+%s/%lu -> null, not %s\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length, array[i].result); return PR_FALSE; } else { const char *a = array[i].result; const char *b = (const char *)rv; while( *a ) { if( *a != *b ) { printf("FAIL %d: %s+%s/%lu -> %.32s, not %s\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length, rv, array[i].result); return PR_FALSE; } a++; b++; } if( array[i].nulled ) { if( (char)0 != *b ) { printf("FAIL %d: %s+%s/%lu -> not nulled\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length); return PR_FALSE; } } else { if( (char)0 == *b ) { printf("FAIL %d: %s+%s/%lu -> overrun\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length); return PR_FALSE; } } } } } printf("PASS\n"); return PR_TRUE; } /* PL_strcatn */ PRBool test_010(void) { static struct { const char *first; const char *second; PRUint32 length; const char *result; } array[] = { { (const char *)0, (const char *)0, 0, (const char *)0 }, { (const char *)0, (const char *)0, 1, (const char *)0 }, { (const char *)0, (const char *)0, 7, (const char *)0 }, { (const char *)0, "", 0, (const char *)0 }, { (const char *)0, "", 1, (const char *)0 }, { (const char *)0, "", 7, (const char *)0 }, { (const char *)0, "stuff", 0, (const char *)0 }, { (const char *)0, "stuff", 1, (const char *)0 }, { (const char *)0, "stuff", 7, (const char *)0 }, { "", (const char *)0, 0, "" }, { "", (const char *)0, 1, "" }, { "", (const char *)0, 7, "" }, { "", "", 0, "" }, { "", "", 1, "" }, { "", "", 7, "" }, { "", "abcdefgh", 0, "" }, { "", "abcdefgh", 1, "" }, { "", "abcdefgh", 7, "abcdef" }, { "xyz", (const char *)0, 0, "xyz" }, { "xyz", (const char *)0, 1, "xyz" }, { "xyz", (const char *)0, 7, "xyz" }, { "xyz", "", 0, "xyz" }, { "xyz", "", 1, "xyz" }, { "xyz", "", 7, "xyz" }, { "xyz", "abcdefgh", 0, "xyz" }, { "xyz", "abcdefgh", 1, "xyz" }, { "xyz", "abcdefgh", 7, "xyzabc" } }; int i; printf("Test 010 (PL_strcatn) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char buffer[ 1024 ]; int j; char *rv; for( j = 0; j < sizeof(buffer); j++ ) buffer[j] = '-'; if( (const char *)0 != array[i].first ) (void)PL_strcpy(buffer, array[i].first); rv = PL_strcatn(((const char *)0 == array[i].first) ? (char *)0 : buffer, array[i].length, array[i].second); if( (const char *)0 == array[i].result ) { if( (char *)0 != rv ) { printf("FAIL %d: %s+%s/%lu -> %.32s, not zero\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s+%s/%lu -> null, not %s\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length, array[i].result); return PR_FALSE; } else { const char *a = array[i].result; const char *b = (const char *)rv; while( 1 ) { if( *a != *b ) { printf("FAIL %d: %s+%s/%lu -> %.32s, not %s\n", i, array[i].first ? array[i].first : "(null)", array[i].second ? array[i].second : "(null)", array[i].length, rv, array[i].result); return PR_FALSE; } if( (char)0 == *a ) break; a++; b++; } } } } printf("PASS\n"); return PR_TRUE; } /* PL_strcmp */ PRBool test_011(void) { static struct { const char *one; const char *two; PRIntn sign; } array[] = { { (const char *)0, (const char *)0, 0 }, { (const char *)0, "word", -1 }, { "word", (const char *)0, 1 }, { "word", "word", 0 }, { "aZYXVUT", "bZYXVUT", -1 }, { "aZYXVUT", "bAAAAAA", -1 }, { "a", "aa", -1 }, { "a", "a", 0 }, { "a", "A", 1 }, { "aaaaa", "baaaa", -1 }, { "aaaaa", "abaaa", -1 }, { "aaaaa", "aabaa", -1 }, { "aaaaa", "aaaba", -1 }, { "aaaaa", "aaaab", -1 }, { "bZYXVUT", "aZYXVUT", 1 }, { "bAAAAAA", "aZYXVUT", 1 }, { "aa", "a", 1 }, { "A", "a", -1 }, { "baaaa", "aaaaa", 1 }, { "abaaa", "aaaaa", 1 }, { "aabaa", "aaaaa", 1 }, { "aaaba", "aaaaa", 1 }, { "aaaab", "aaaaa", 1 }, { "word", "Word", 1 }, { "word", "wOrd", 1 }, { "word", "woRd", 1 }, { "word", "worD", 1 }, { "WORD", "wORD", -1 }, { "WORD", "WoRD", -1 }, { "WORD", "WOrD", -1 }, { "WORD", "WORd", -1 } }; int i; printf("Test 011 (PL_strcmp) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRIntn rv = PL_strcmp(array[i].one, array[i].two); switch( array[i].sign ) { case -1: if( rv < 0 ) continue; break; case 1: if( rv > 0 ) continue; break; case 0: if( 0 == rv ) continue; break; default: PR_NOT_REACHED("static data inconsistancy"); break; } printf("FAIL %d: %s-%s -> %d, not %d\n", i, array[i].one ? array[i].one : "(null)", array[i].two ? array[i].two : "(null)", rv, array[i].sign); return PR_FALSE; } printf("PASS\n"); return PR_TRUE; } /* PL_strncmp */ PRBool test_012(void) { static struct { const char *one; const char *two; PRUint32 max; PRIntn sign; } array[] = { { (const char *)0, (const char *)0, 0, 0 }, { (const char *)0, (const char *)0, 1, 0 }, { (const char *)0, (const char *)0, 4, 0 }, { (const char *)0, "word", 0, -1 }, { (const char *)0, "word", 1, -1 }, { (const char *)0, "word", 4, -1 }, { "word", (const char *)0, 0, 1 }, { "word", (const char *)0, 1, 1 }, { "word", (const char *)0, 4, 1 }, { "word", "word", 0, 0 }, { "word", "word", 1, 0 }, { "word", "word", 3, 0 }, { "word", "word", 5, 0 }, { "aZYXVUT", "bZYXVUT", 0, 0 }, { "aZYXVUT", "bZYXVUT", 1, -1 }, { "aZYXVUT", "bZYXVUT", 4, -1 }, { "aZYXVUT", "bZYXVUT", 9, -1 }, { "aZYXVUT", "bAAAAAA", 0, 0 }, { "aZYXVUT", "bAAAAAA", 1, -1 }, { "aZYXVUT", "bAAAAAA", 4, -1 }, { "aZYXVUT", "bAAAAAA", 5, -1 }, { "a", "aa", 0, 0 }, { "a", "aa", 1, 0 }, { "a", "aa", 4, -1 }, { "a", "a", 0, 0 }, { "a", "a", 1, 0 }, { "a", "a", 4, 0 }, { "a", "A", 0, 0 }, { "a", "A", 1, 1 }, { "a", "A", 4, 1 }, { "aaaaa", "baaaa", 0, 0 }, { "aaaaa", "baaaa", 1, -1 }, { "aaaaa", "baaaa", 4, -1 }, { "aaaaa", "abaaa", 0, 0 }, { "aaaaa", "abaaa", 1, 0 }, { "aaaaa", "abaaa", 4, -1 }, { "aaaaa", "aabaa", 0, 0 }, { "aaaaa", "aabaa", 1, 0 }, { "aaaaa", "aabaa", 4, -1 }, { "aaaaa", "aaaba", 0, 0 }, { "aaaaa", "aaaba", 1, 0 }, { "aaaaa", "aaaba", 4, -1 }, { "aaaaa", "aaaab", 0, 0 }, { "aaaaa", "aaaab", 1, 0 }, { "aaaaa", "aaaab", 4, 0 }, { "bZYXVUT", "aZYXVUT", 0, 0 }, { "bZYXVUT", "aZYXVUT", 1, 1 }, { "bZYXVUT", "aZYXVUT", 4, 1 }, { "bAAAAAA", "aZYXVUT", 0, 0 }, { "bAAAAAA", "aZYXVUT", 1, 1 }, { "bAAAAAA", "aZYXVUT", 4, 1 }, { "aa", "a", 0, 0 }, { "aa", "a", 1, 0 }, { "aa", "a", 4, 1 }, { "A", "a", 0, 0 }, { "A", "a", 1, -1 }, { "A", "a", 4, -1 }, { "baaaa", "aaaaa", 0, 0 }, { "baaaa", "aaaaa", 1, 1 }, { "baaaa", "aaaaa", 4, 1 }, { "abaaa", "aaaaa", 0, 0 }, { "abaaa", "aaaaa", 1, 0 }, { "abaaa", "aaaaa", 4, 1 }, { "aabaa", "aaaaa", 0, 0 }, { "aabaa", "aaaaa", 1, 0 }, { "aabaa", "aaaaa", 4, 1 }, { "aaaba", "aaaaa", 0, 0 }, { "aaaba", "aaaaa", 1, 0 }, { "aaaba", "aaaaa", 4, 1 }, { "aaaab", "aaaaa", 0, 0 }, { "aaaab", "aaaaa", 1, 0 }, { "aaaab", "aaaaa", 4, 0 }, { "word", "Word", 0, 0 }, { "word", "Word", 1, 1 }, { "word", "Word", 3, 1 }, { "word", "wOrd", 0, 0 }, { "word", "wOrd", 1, 0 }, { "word", "wOrd", 3, 1 }, { "word", "woRd", 0, 0 }, { "word", "woRd", 1, 0 }, { "word", "woRd", 3, 1 }, { "word", "worD", 0, 0 }, { "word", "worD", 1, 0 }, { "word", "worD", 3, 0 }, { "WORD", "wORD", 0, 0 }, { "WORD", "wORD", 1, -1 }, { "WORD", "wORD", 3, -1 }, { "WORD", "WoRD", 0, 0 }, { "WORD", "WoRD", 1, 0 }, { "WORD", "WoRD", 3, -1 }, { "WORD", "WOrD", 0, 0 }, { "WORD", "WOrD", 1, 0 }, { "WORD", "WOrD", 3, -1 }, { "WORD", "WORd", 0, 0 }, { "WORD", "WORd", 1, 0 }, { "WORD", "WORd", 3, 0 } }; int i; printf("Test 012 (PL_strncmp) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRIntn rv = PL_strncmp(array[i].one, array[i].two, array[i].max); switch( array[i].sign ) { case -1: if( rv < 0 ) continue; break; case 1: if( rv > 0 ) continue; break; case 0: if( 0 == rv ) continue; break; default: PR_NOT_REACHED("static data inconsistancy"); break; } printf("FAIL %d: %s-%s/%ld -> %d, not %d\n", i, array[i].one ? array[i].one : "(null)", array[i].two ? array[i].two : "(null)", array[i].max, rv, array[i].sign); return PR_FALSE; } printf("PASS\n"); return PR_TRUE; } /* PL_strcasecmp */ PRBool test_013(void) { static struct { const char *one; const char *two; PRIntn sign; } array[] = { { (const char *)0, (const char *)0, 0 }, { (const char *)0, "word", -1 }, { "word", (const char *)0, 1 }, { "word", "word", 0 }, { "aZYXVUT", "bZYXVUT", -1 }, { "aZYXVUT", "bAAAAAA", -1 }, { "a", "aa", -1 }, { "a", "a", 0 }, { "a", "A", 0 }, { "aaaaa", "baaaa", -1 }, { "aaaaa", "abaaa", -1 }, { "aaaaa", "aabaa", -1 }, { "aaaaa", "aaaba", -1 }, { "aaaaa", "aaaab", -1 }, { "bZYXVUT", "aZYXVUT", 1 }, { "bAAAAAA", "aZYXVUT", 1 }, { "aa", "a", 1 }, { "A", "a", 0 }, { "baaaa", "aaaaa", 1 }, { "abaaa", "aaaaa", 1 }, { "aabaa", "aaaaa", 1 }, { "aaaba", "aaaaa", 1 }, { "aaaab", "aaaaa", 1 }, { "word", "Word", 0 }, { "word", "wOrd", 0 }, { "word", "woRd", 0 }, { "word", "worD", 0 }, { "WORD", "wORD", 0 }, { "WORD", "WoRD", 0 }, { "WORD", "WOrD", 0 }, { "WORD", "WORd", 0 } }; int i; printf("Test 013 (PL_strcasecmp) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRIntn rv = PL_strcasecmp(array[i].one, array[i].two); switch( array[i].sign ) { case -1: if( rv < 0 ) continue; break; case 1: if( rv > 0 ) continue; break; case 0: if( 0 == rv ) continue; break; default: PR_NOT_REACHED("static data inconsistancy"); break; } printf("FAIL %d: %s-%s -> %d, not %d\n", i, array[i].one ? array[i].one : "(null)", array[i].two ? array[i].two : "(null)", rv, array[i].sign); return PR_FALSE; } printf("PASS\n"); return PR_TRUE; } /* PL_strncasecmp */ PRBool test_014(void) { static struct { const char *one; const char *two; PRUint32 max; PRIntn sign; } array[] = { { (const char *)0, (const char *)0, 0, 0 }, { (const char *)0, (const char *)0, 1, 0 }, { (const char *)0, (const char *)0, 4, 0 }, { (const char *)0, "word", 0, -1 }, { (const char *)0, "word", 1, -1 }, { (const char *)0, "word", 4, -1 }, { "word", (const char *)0, 0, 1 }, { "word", (const char *)0, 1, 1 }, { "word", (const char *)0, 4, 1 }, { "word", "word", 0, 0 }, { "word", "word", 1, 0 }, { "word", "word", 3, 0 }, { "word", "word", 5, 0 }, { "aZYXVUT", "bZYXVUT", 0, 0 }, { "aZYXVUT", "bZYXVUT", 1, -1 }, { "aZYXVUT", "bZYXVUT", 4, -1 }, { "aZYXVUT", "bZYXVUT", 9, -1 }, { "aZYXVUT", "bAAAAAA", 0, 0 }, { "aZYXVUT", "bAAAAAA", 1, -1 }, { "aZYXVUT", "bAAAAAA", 4, -1 }, { "aZYXVUT", "bAAAAAA", 5, -1 }, { "a", "aa", 0, 0 }, { "a", "aa", 1, 0 }, { "a", "aa", 4, -1 }, { "a", "a", 0, 0 }, { "a", "a", 1, 0 }, { "a", "a", 4, 0 }, { "a", "A", 0, 0 }, { "a", "A", 1, 0 }, { "a", "A", 4, 0 }, { "aaaaa", "baaaa", 0, 0 }, { "aaaaa", "baaaa", 1, -1 }, { "aaaaa", "baaaa", 4, -1 }, { "aaaaa", "abaaa", 0, 0 }, { "aaaaa", "abaaa", 1, 0 }, { "aaaaa", "abaaa", 4, -1 }, { "aaaaa", "aabaa", 0, 0 }, { "aaaaa", "aabaa", 1, 0 }, { "aaaaa", "aabaa", 4, -1 }, { "aaaaa", "aaaba", 0, 0 }, { "aaaaa", "aaaba", 1, 0 }, { "aaaaa", "aaaba", 4, -1 }, { "aaaaa", "aaaab", 0, 0 }, { "aaaaa", "aaaab", 1, 0 }, { "aaaaa", "aaaab", 4, 0 }, { "bZYXVUT", "aZYXVUT", 0, 0 }, { "bZYXVUT", "aZYXVUT", 1, 1 }, { "bZYXVUT", "aZYXVUT", 4, 1 }, { "bAAAAAA", "aZYXVUT", 0, 0 }, { "bAAAAAA", "aZYXVUT", 1, 1 }, { "bAAAAAA", "aZYXVUT", 4, 1 }, { "aa", "a", 0, 0 }, { "aa", "a", 1, 0 }, { "aa", "a", 4, 1 }, { "A", "a", 0, 0 }, { "A", "a", 1, 0 }, { "A", "a", 4, 0 }, { "baaaa", "aaaaa", 0, 0 }, { "baaaa", "aaaaa", 1, 1 }, { "baaaa", "aaaaa", 4, 1 }, { "abaaa", "aaaaa", 0, 0 }, { "abaaa", "aaaaa", 1, 0 }, { "abaaa", "aaaaa", 4, 1 }, { "aabaa", "aaaaa", 0, 0 }, { "aabaa", "aaaaa", 1, 0 }, { "aabaa", "aaaaa", 4, 1 }, { "aaaba", "aaaaa", 0, 0 }, { "aaaba", "aaaaa", 1, 0 }, { "aaaba", "aaaaa", 4, 1 }, { "aaaab", "aaaaa", 0, 0 }, { "aaaab", "aaaaa", 1, 0 }, { "aaaab", "aaaaa", 4, 0 }, { "word", "Word", 0, 0 }, { "word", "Word", 1, 0 }, { "word", "Word", 3, 0 }, { "word", "wOrd", 0, 0 }, { "word", "wOrd", 1, 0 }, { "word", "wOrd", 3, 0 }, { "word", "woRd", 0, 0 }, { "word", "woRd", 1, 0 }, { "word", "woRd", 3, 0 }, { "word", "worD", 0, 0 }, { "word", "worD", 1, 0 }, { "word", "worD", 3, 0 }, { "WORD", "wORD", 0, 0 }, { "WORD", "wORD", 1, 0 }, { "WORD", "wORD", 3, 0 }, { "WORD", "WoRD", 0, 0 }, { "WORD", "WoRD", 1, 0 }, { "WORD", "WoRD", 3, 0 }, { "WORD", "WOrD", 0, 0 }, { "WORD", "WOrD", 1, 0 }, { "WORD", "WOrD", 3, 0 }, { "WORD", "WORd", 0, 0 }, { "WORD", "WORd", 1, 0 }, { "WORD", "WORd", 3, 0 } }; int i; printf("Test 014 (PL_strncasecmp) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { PRIntn rv = PL_strncasecmp(array[i].one, array[i].two, array[i].max); switch( array[i].sign ) { case -1: if( rv < 0 ) continue; break; case 1: if( rv > 0 ) continue; break; case 0: if( 0 == rv ) continue; break; default: PR_NOT_REACHED("static data inconsistancy"); break; } printf("FAIL %d: %s-%s/%ld -> %d, not %d\n", i, array[i].one ? array[i].one : "(null)", array[i].two ? array[i].two : "(null)", array[i].max, rv, array[i].sign); return PR_FALSE; } printf("PASS\n"); return PR_TRUE; } /* PL_strchr */ PRBool test_015(void) { static struct { const char *str; char chr; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, 'a', PR_FALSE, 0 }, { (const char *)0, '\0', PR_FALSE, 0 }, { "abcdefg", 'a', PR_TRUE, 0 }, { "abcdefg", 'b', PR_TRUE, 1 }, { "abcdefg", 'c', PR_TRUE, 2 }, { "abcdefg", 'd', PR_TRUE, 3 }, { "abcdefg", 'e', PR_TRUE, 4 }, { "abcdefg", 'f', PR_TRUE, 5 }, { "abcdefg", 'g', PR_TRUE, 6 }, { "abcdefg", 'h', PR_FALSE, 0 }, { "abcdefg", '\0', PR_TRUE, 7 }, { "abcdefg", 'A', PR_FALSE, 0 }, { "abcdefg", 'B', PR_FALSE, 0 }, { "abcdefg", 'C', PR_FALSE, 0 }, { "abcdefg", 'D', PR_FALSE, 0 }, { "abcdefg", 'E', PR_FALSE, 0 }, { "abcdefg", 'F', PR_FALSE, 0 }, { "abcdefg", 'G', PR_FALSE, 0 }, { "abcdefg", 'H', PR_FALSE, 0 }, { "abcdefgabcdefg", 'a', PR_TRUE, 0 }, { "abcdefgabcdefg", 'b', PR_TRUE, 1 }, { "abcdefgabcdefg", 'c', PR_TRUE, 2 }, { "abcdefgabcdefg", 'd', PR_TRUE, 3 }, { "abcdefgabcdefg", 'e', PR_TRUE, 4 }, { "abcdefgabcdefg", 'f', PR_TRUE, 5 }, { "abcdefgabcdefg", 'g', PR_TRUE, 6 }, { "abcdefgabcdefg", 'h', PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', PR_TRUE, 14 } }; int i; printf("Test 015 (PL_strchr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strchr(array[i].str, array[i].chr); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%c -> %.32s, not zero\n", i, array[i].str, array[i].chr, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%c -> null, not +%lu\n", i, array[i].str, array[i].chr, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%c -> 0x%x, not 0x%x+%lu\n", i, array[i].str, array[i].chr, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strrchr */ PRBool test_016(void) { static struct { const char *str; char chr; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, 'a', PR_FALSE, 0 }, { (const char *)0, '\0', PR_FALSE, 0 }, { "abcdefg", 'a', PR_TRUE, 0 }, { "abcdefg", 'b', PR_TRUE, 1 }, { "abcdefg", 'c', PR_TRUE, 2 }, { "abcdefg", 'd', PR_TRUE, 3 }, { "abcdefg", 'e', PR_TRUE, 4 }, { "abcdefg", 'f', PR_TRUE, 5 }, { "abcdefg", 'g', PR_TRUE, 6 }, { "abcdefg", 'h', PR_FALSE, 0 }, { "abcdefg", '\0', PR_TRUE, 7 }, { "abcdefg", 'A', PR_FALSE, 0 }, { "abcdefg", 'B', PR_FALSE, 0 }, { "abcdefg", 'C', PR_FALSE, 0 }, { "abcdefg", 'D', PR_FALSE, 0 }, { "abcdefg", 'E', PR_FALSE, 0 }, { "abcdefg", 'F', PR_FALSE, 0 }, { "abcdefg", 'G', PR_FALSE, 0 }, { "abcdefg", 'H', PR_FALSE, 0 }, { "abcdefgabcdefg", 'a', PR_TRUE, 7 }, { "abcdefgabcdefg", 'b', PR_TRUE, 8 }, { "abcdefgabcdefg", 'c', PR_TRUE, 9 }, { "abcdefgabcdefg", 'd', PR_TRUE, 10 }, { "abcdefgabcdefg", 'e', PR_TRUE, 11 }, { "abcdefgabcdefg", 'f', PR_TRUE, 12 }, { "abcdefgabcdefg", 'g', PR_TRUE, 13 }, { "abcdefgabcdefg", 'h', PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', PR_TRUE, 14 } }; int i; printf("Test 016 (PL_strrchr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strrchr(array[i].str, array[i].chr); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%c -> %.32s, not zero\n", i, array[i].str, array[i].chr, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%c -> null, not +%lu\n", i, array[i].str, array[i].chr, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%c -> 0x%x, not 0x%x+%lu\n", i, array[i].str, array[i].chr, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strnchr */ PRBool test_017(void) { static struct { const char *str; char chr; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, 'a', 2, PR_FALSE, 0 }, { (const char *)0, '\0', 2, PR_FALSE, 0 }, { "abcdefg", 'a', 5, PR_TRUE, 0 }, { "abcdefg", 'b', 5, PR_TRUE, 1 }, { "abcdefg", 'c', 5, PR_TRUE, 2 }, { "abcdefg", 'd', 5, PR_TRUE, 3 }, { "abcdefg", 'e', 5, PR_TRUE, 4 }, { "abcdefg", 'f', 5, PR_FALSE, 0 }, { "abcdefg", 'g', 5, PR_FALSE, 0 }, { "abcdefg", 'h', 5, PR_FALSE, 0 }, { "abcdefg", '\0', 5, PR_FALSE, 0 }, { "abcdefg", '\0', 15, PR_TRUE, 7 }, { "abcdefg", 'A', 5, PR_FALSE, 0 }, { "abcdefg", 'B', 5, PR_FALSE, 0 }, { "abcdefg", 'C', 5, PR_FALSE, 0 }, { "abcdefg", 'D', 5, PR_FALSE, 0 }, { "abcdefg", 'E', 5, PR_FALSE, 0 }, { "abcdefg", 'F', 5, PR_FALSE, 0 }, { "abcdefg", 'G', 5, PR_FALSE, 0 }, { "abcdefg", 'H', 5, PR_FALSE, 0 }, { "abcdefgabcdefg", 'a', 10, PR_TRUE, 0 }, { "abcdefgabcdefg", 'b', 10, PR_TRUE, 1 }, { "abcdefgabcdefg", 'c', 10, PR_TRUE, 2 }, { "abcdefgabcdefg", 'd', 10, PR_TRUE, 3 }, { "abcdefgabcdefg", 'e', 10, PR_TRUE, 4 }, { "abcdefgabcdefg", 'f', 10, PR_TRUE, 5 }, { "abcdefgabcdefg", 'g', 10, PR_TRUE, 6 }, { "abcdefgabcdefg", 'h', 10, PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', 10, PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', 14, PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', 15, PR_TRUE, 14 } }; int i; printf("Test 017 (PL_strnchr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strnchr(array[i].str, array[i].chr, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%c/%lu -> %.32s, not zero\n", i, array[i].str, array[i].chr, array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%c/%lu -> null, not +%lu\n", i, array[i].str, array[i].chr, array[i].max, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%c/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str, array[i].chr, array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strnrchr */ PRBool test_018(void) { static struct { const char *str; char chr; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, 'a', 2, PR_FALSE, 0 }, { (const char *)0, '\0', 2, PR_FALSE, 0 }, { "abcdefg", 'a', 5, PR_TRUE, 0 }, { "abcdefg", 'b', 5, PR_TRUE, 1 }, { "abcdefg", 'c', 5, PR_TRUE, 2 }, { "abcdefg", 'd', 5, PR_TRUE, 3 }, { "abcdefg", 'e', 5, PR_TRUE, 4 }, { "abcdefg", 'f', 5, PR_FALSE, 0 }, { "abcdefg", 'g', 5, PR_FALSE, 0 }, { "abcdefg", 'h', 5, PR_FALSE, 0 }, { "abcdefg", '\0', 5, PR_FALSE, 0 }, { "abcdefg", '\0', 15, PR_TRUE, 7 }, { "abcdefg", 'A', 5, PR_FALSE, 0 }, { "abcdefg", 'B', 5, PR_FALSE, 0 }, { "abcdefg", 'C', 5, PR_FALSE, 0 }, { "abcdefg", 'D', 5, PR_FALSE, 0 }, { "abcdefg", 'E', 5, PR_FALSE, 0 }, { "abcdefg", 'F', 5, PR_FALSE, 0 }, { "abcdefg", 'G', 5, PR_FALSE, 0 }, { "abcdefg", 'H', 5, PR_FALSE, 0 }, { "abcdefgabcdefg", 'a', 10, PR_TRUE, 7 }, { "abcdefgabcdefg", 'b', 10, PR_TRUE, 8 }, { "abcdefgabcdefg", 'c', 10, PR_TRUE, 9 }, { "abcdefgabcdefg", 'd', 10, PR_TRUE, 3 }, { "abcdefgabcdefg", 'e', 10, PR_TRUE, 4 }, { "abcdefgabcdefg", 'f', 10, PR_TRUE, 5 }, { "abcdefgabcdefg", 'g', 10, PR_TRUE, 6 }, { "abcdefgabcdefg", 'h', 10, PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', 10, PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', 14, PR_FALSE, 0 }, { "abcdefgabcdefg", '\0', 15, PR_TRUE, 14 } }; int i; printf("Test 018 (PL_strnrchr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strnrchr(array[i].str, array[i].chr, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%c/%lu -> %.32s, not zero\n", i, array[i].str, array[i].chr, array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%c/%lu -> null, not +%lu\n", i, array[i].str, array[i].chr, array[i].max, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%c/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str, array[i].chr, array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strpbrk */ PRBool test_019(void) { static struct { const char *str; const char *chrs; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, PR_FALSE, 0 }, { (const char *)0, "abc", PR_FALSE, 0 }, { "abc", (const char *)0, PR_FALSE, 0 }, { "abcdefg", "", PR_FALSE, 0 }, { "", "aeiou", PR_FALSE, 0 }, { "abcdefg", "ae", PR_TRUE, 0 }, { "abcdefg", "ei", PR_TRUE, 4 }, { "abcdefg", "io", PR_FALSE, 0 }, { "abcdefg", "bcd", PR_TRUE, 1 }, { "abcdefg", "cbd", PR_TRUE, 1 }, { "abcdefg", "dbc", PR_TRUE, 1 }, { "abcdefg", "ghi", PR_TRUE, 6 }, { "abcdefg", "AE", PR_FALSE, 0 }, { "abcdefg", "EI", PR_FALSE, 0 }, { "abcdefg", "IO", PR_FALSE, 0 }, { "abcdefg", "BCD", PR_FALSE, 0 }, { "abcdefg", "CBD", PR_FALSE, 0 }, { "abcdefg", "DBC", PR_FALSE, 0 }, { "abcdefg", "GHI", PR_FALSE, 0 }, { "abcdefgabcdefg", "ae", PR_TRUE, 0 }, { "abcdefgabcdefg", "ei", PR_TRUE, 4 }, { "abcdefgabcdefg", "io", PR_FALSE, 0 }, { "abcdefgabcdefg", "bcd", PR_TRUE, 1 }, { "abcdefgabcdefg", "cbd", PR_TRUE, 1 }, { "abcdefgabcdefg", "dbc", PR_TRUE, 1 }, { "abcdefgabcdefg", "ghi", PR_TRUE, 6 }, { "abcdefgabcdefg", "AE", PR_FALSE, 0 }, { "abcdefgabcdefg", "EI", PR_FALSE, 0 }, { "abcdefgabcdefg", "IO", PR_FALSE, 0 }, { "abcdefgabcdefg", "BCD", PR_FALSE, 0 }, { "abcdefgabcdefg", "CBD", PR_FALSE, 0 }, { "abcdefgabcdefg", "DBC", PR_FALSE, 0 }, { "abcdefgabcdefg", "GHI", PR_FALSE, 0 } }; int i; printf("Test 019 (PL_strpbrk) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strpbrk(array[i].str, array[i].chrs); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s -> null, not +%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strprbrk */ PRBool test_020(void) { static struct { const char *str; const char *chrs; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, PR_FALSE, 0 }, { (const char *)0, "abc", PR_FALSE, 0 }, { "abc", (const char *)0, PR_FALSE, 0 }, { "abcdefg", "", PR_FALSE, 0 }, { "", "aeiou", PR_FALSE, 0 }, { "abcdefg", "ae", PR_TRUE, 4 }, { "abcdefg", "ei", PR_TRUE, 4 }, { "abcdefg", "io", PR_FALSE, 0 }, { "abcdefg", "bcd", PR_TRUE, 3 }, { "abcdefg", "cbd", PR_TRUE, 3 }, { "abcdefg", "dbc", PR_TRUE, 3 }, { "abcdefg", "ghi", PR_TRUE, 6 }, { "abcdefg", "AE", PR_FALSE, 0 }, { "abcdefg", "EI", PR_FALSE, 0 }, { "abcdefg", "IO", PR_FALSE, 0 }, { "abcdefg", "BCD", PR_FALSE, 0 }, { "abcdefg", "CBD", PR_FALSE, 0 }, { "abcdefg", "DBC", PR_FALSE, 0 }, { "abcdefg", "GHI", PR_FALSE, 0 }, { "abcdefgabcdefg", "ae", PR_TRUE, 11 }, { "abcdefgabcdefg", "ei", PR_TRUE, 11 }, { "abcdefgabcdefg", "io", PR_FALSE, 0 }, { "abcdefgabcdefg", "bcd", PR_TRUE, 10 }, { "abcdefgabcdefg", "cbd", PR_TRUE, 10 }, { "abcdefgabcdefg", "dbc", PR_TRUE, 10 }, { "abcdefgabcdefg", "ghi", PR_TRUE, 13 }, { "abcdefgabcdefg", "AE", PR_FALSE, 0 }, { "abcdefgabcdefg", "EI", PR_FALSE, 0 }, { "abcdefgabcdefg", "IO", PR_FALSE, 0 }, { "abcdefgabcdefg", "BCD", PR_FALSE, 0 }, { "abcdefgabcdefg", "CBD", PR_FALSE, 0 }, { "abcdefgabcdefg", "DBC", PR_FALSE, 0 }, { "abcdefgabcdefg", "GHI", PR_FALSE, 0 } }; int i; printf("Test 020 (PL_strprbrk) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strprbrk(array[i].str, array[i].chrs); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s -> null, not +%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strnpbrk */ PRBool test_021(void) { static struct { const char *str; const char *chrs; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, 3, PR_FALSE, 0 }, { (const char *)0, "abc", 3, PR_FALSE, 0 }, { "abc", (const char *)0, 3, PR_FALSE, 0 }, { "abcdefg", "", 3, PR_FALSE, 0 }, { "", "aeiou", 3, PR_FALSE, 0 }, { "abcdefg", "ae", 0, PR_FALSE, 0 }, { "abcdefg", "ae", 1, PR_TRUE, 0 }, { "abcdefg", "ae", 4, PR_TRUE, 0 }, { "abcdefg", "ae", 5, PR_TRUE, 0 }, { "abcdefg", "ae", 6, PR_TRUE, 0 }, { "abcdefg", "ei", 4, PR_FALSE, 0 }, { "abcdefg", "io", 10, PR_FALSE, 0 }, { "abcdefg", "bcd", 2, PR_TRUE, 1 }, { "abcdefg", "cbd", 2, PR_TRUE, 1 }, { "abcdefg", "dbc", 2, PR_TRUE, 1 }, { "abcdefg", "ghi", 6, PR_FALSE, 0 }, { "abcdefg", "ghi", 7, PR_TRUE, 6 }, { "abcdefg", "AE", 9, PR_FALSE, 0 }, { "abcdefg", "EI", 9, PR_FALSE, 0 }, { "abcdefg", "IO", 9, PR_FALSE, 0 }, { "abcdefg", "BCD", 9, PR_FALSE, 0 }, { "abcdefg", "CBD", 9, PR_FALSE, 0 }, { "abcdefg", "DBC", 9, PR_FALSE, 0 }, { "abcdefg", "GHI", 9, PR_FALSE, 0 }, { "abcdefgabcdefg", "ae", 10, PR_TRUE, 0 }, { "abcdefgabcdefg", "ei", 10, PR_TRUE, 4 }, { "abcdefgabcdefg", "io", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "bcd", 10, PR_TRUE, 1 }, { "abcdefgabcdefg", "cbd", 10, PR_TRUE, 1 }, { "abcdefgabcdefg", "dbc", 10, PR_TRUE, 1 }, { "abcdefgabcdefg", "ghi", 10, PR_TRUE, 6 }, { "abcdefgabcdefg", "AE", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "EI", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "IO", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "BCD", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "CBD", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "DBC", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "GHI", 10, PR_FALSE, 0 } }; int i; printf("Test 021 (PL_strnpbrk) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strnpbrk(array[i].str, array[i].chrs, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s/%lu -> null, not +%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].max, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strnprbrk */ PRBool test_022(void) { static struct { const char *str; const char *chrs; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, 3, PR_FALSE, 0 }, { (const char *)0, "abc", 3, PR_FALSE, 0 }, { "abc", (const char *)0, 3, PR_FALSE, 0 }, { "abcdefg", "", 3, PR_FALSE, 0 }, { "", "aeiou", 3, PR_FALSE, 0 }, { "abcdefg", "ae", 0, PR_FALSE, 0 }, { "abcdefg", "ae", 1, PR_TRUE, 0 }, { "abcdefg", "ae", 4, PR_TRUE, 0 }, { "abcdefg", "ae", 5, PR_TRUE, 4 }, { "abcdefg", "ae", 6, PR_TRUE, 4 }, { "abcdefg", "ei", 4, PR_FALSE, 0 }, { "abcdefg", "io", 10, PR_FALSE, 0 }, { "abcdefg", "bcd", 2, PR_TRUE, 1 }, { "abcdefg", "cbd", 2, PR_TRUE, 1 }, { "abcdefg", "dbc", 2, PR_TRUE, 1 }, { "abcdefg", "bcd", 3, PR_TRUE, 2 }, { "abcdefg", "cbd", 3, PR_TRUE, 2 }, { "abcdefg", "dbc", 3, PR_TRUE, 2 }, { "abcdefg", "bcd", 5, PR_TRUE, 3 }, { "abcdefg", "cbd", 5, PR_TRUE, 3 }, { "abcdefg", "dbc", 5, PR_TRUE, 3 }, { "abcdefg", "bcd", 15, PR_TRUE, 3 }, { "abcdefg", "cbd", 15, PR_TRUE, 3 }, { "abcdefg", "dbc", 15, PR_TRUE, 3 }, { "abcdefg", "ghi", 6, PR_FALSE, 0 }, { "abcdefg", "ghi", 7, PR_TRUE, 6 }, { "abcdefg", "AE", 9, PR_FALSE, 0 }, { "abcdefg", "EI", 9, PR_FALSE, 0 }, { "abcdefg", "IO", 9, PR_FALSE, 0 }, { "abcdefg", "BCD", 9, PR_FALSE, 0 }, { "abcdefg", "CBD", 9, PR_FALSE, 0 }, { "abcdefg", "DBC", 9, PR_FALSE, 0 }, { "abcdefg", "GHI", 9, PR_FALSE, 0 }, { "abcdefgabcdefg", "ae", 10, PR_TRUE, 7 }, { "abcdefgabcdefg", "ei", 10, PR_TRUE, 4 }, { "abcdefgabcdefg", "io", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "bcd", 10, PR_TRUE, 9 }, { "abcdefgabcdefg", "cbd", 10, PR_TRUE, 9 }, { "abcdefgabcdefg", "dbc", 10, PR_TRUE, 9 }, { "abcdefgabcdefg", "ghi", 10, PR_TRUE, 6 }, { "abcdefgabcdefg", "AE", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "EI", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "IO", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "BCD", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "CBD", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "DBC", 10, PR_FALSE, 0 }, { "abcdefgabcdefg", "GHI", 10, PR_FALSE, 0 } }; int i; printf("Test 022 (PL_strnprbrk) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strnprbrk(array[i].str, array[i].chrs, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s/%lu -> null, not +%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].max, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].chrs ? array[i].chrs : "(null)", array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strstr */ PRBool test_023(void) { static struct { const char *str; const char *sub; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, PR_FALSE, 0 }, { (const char *)0, "blah", PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, PR_FALSE, 0 }, { "blah-de-blah", "blah", PR_TRUE, 0 }, { "", "blah", PR_FALSE, 0 }, { "blah-de-blah", "", PR_FALSE, 0 }, { "abcdefg", "a", PR_TRUE, 0 }, { "abcdefg", "c", PR_TRUE, 2 }, { "abcdefg", "e", PR_TRUE, 4 }, { "abcdefg", "g", PR_TRUE, 6 }, { "abcdefg", "i", PR_FALSE, 0 }, { "abcdefg", "ab", PR_TRUE, 0 }, { "abcdefg", "cd", PR_TRUE, 2 }, { "abcdefg", "ef", PR_TRUE, 4 }, { "abcdefg", "gh", PR_FALSE, 0 }, { "abcdabc", "bc", PR_TRUE, 1 }, { "abcdefg", "abcdefg", PR_TRUE, 0 }, { "abcdefgabcdefg", "a", PR_TRUE, 0 }, { "abcdefgabcdefg", "c", PR_TRUE, 2 }, { "abcdefgabcdefg", "e", PR_TRUE, 4 }, { "abcdefgabcdefg", "g", PR_TRUE, 6 }, { "abcdefgabcdefg", "i", PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", PR_TRUE, 0 }, { "abcdefgabcdefg", "cd", PR_TRUE, 2 }, { "abcdefgabcdefg", "ef", PR_TRUE, 4 }, { "abcdefgabcdefg", "gh", PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", PR_TRUE, 1 }, { "abcdefgabcdefg", "abcdefg", PR_TRUE, 0 }, { "ABCDEFG", "a", PR_FALSE, 0 }, { "ABCDEFG", "c", PR_FALSE, 0 }, { "ABCDEFG", "e", PR_FALSE, 0 }, { "ABCDEFG", "g", PR_FALSE, 0 }, { "ABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFG", "ab", PR_FALSE, 0 }, { "ABCDEFG", "cd", PR_FALSE, 0 }, { "ABCDEFG", "ef", PR_FALSE, 0 }, { "ABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABC", "bc", PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "a", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "c", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "e", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "g", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "cd", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ef", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", PR_FALSE, 0 } }; int i; printf("Test 023 (PL_strstr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strstr(array[i].str, array[i].sub); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strrstr */ PRBool test_024(void) { static struct { const char *str; const char *sub; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, PR_FALSE, 0 }, { (const char *)0, "blah", PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, PR_FALSE, 0 }, { "blah-de-blah", "blah", PR_TRUE, 8 }, { "", "blah", PR_FALSE, 0 }, { "blah-de-blah", "", PR_FALSE, 0 }, { "abcdefg", "a", PR_TRUE, 0 }, { "abcdefg", "c", PR_TRUE, 2 }, { "abcdefg", "e", PR_TRUE, 4 }, { "abcdefg", "g", PR_TRUE, 6 }, { "abcdefg", "i", PR_FALSE, 0 }, { "abcdefg", "ab", PR_TRUE, 0 }, { "abcdefg", "cd", PR_TRUE, 2 }, { "abcdefg", "ef", PR_TRUE, 4 }, { "abcdefg", "gh", PR_FALSE, 0 }, { "abcdabc", "bc", PR_TRUE, 5 }, { "abcdefg", "abcdefg", PR_TRUE, 0 }, { "abcdefgabcdefg", "a", PR_TRUE, 7 }, { "abcdefgabcdefg", "c", PR_TRUE, 9 }, { "abcdefgabcdefg", "e", PR_TRUE, 11 }, { "abcdefgabcdefg", "g", PR_TRUE, 13 }, { "abcdefgabcdefg", "i", PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", PR_TRUE, 7 }, { "abcdefgabcdefg", "cd", PR_TRUE, 9 }, { "abcdefgabcdefg", "ef", PR_TRUE, 11 }, { "abcdefgabcdefg", "gh", PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", PR_TRUE, 12 }, { "abcdefgabcdefg", "abcdefg", PR_TRUE, 7 }, { "ABCDEFG", "a", PR_FALSE, 0 }, { "ABCDEFG", "c", PR_FALSE, 0 }, { "ABCDEFG", "e", PR_FALSE, 0 }, { "ABCDEFG", "g", PR_FALSE, 0 }, { "ABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFG", "ab", PR_FALSE, 0 }, { "ABCDEFG", "cd", PR_FALSE, 0 }, { "ABCDEFG", "ef", PR_FALSE, 0 }, { "ABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABC", "bc", PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "a", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "c", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "e", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "g", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "cd", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ef", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", PR_FALSE, 0 } }; int i; printf("Test 024 (PL_strrstr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strrstr(array[i].str, array[i].sub); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strnstr */ PRBool test_025(void) { static struct { const char *str; const char *sub; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, 12, PR_FALSE, 0 }, { (const char *)0, "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 }, { "blah-de-blah", "blah", 0, PR_FALSE, 0 }, { "blah-de-blah", "blah", 2, PR_FALSE, 0 }, { "blah-de-blah", "blah", 3, PR_FALSE, 0 }, { "blah-de-blah", "blah", 4, PR_TRUE, 0 }, { "blah-de-blah", "blah", 5, PR_TRUE, 0 }, { "blah-de-blah", "blah", 12, PR_TRUE, 0 }, { "", "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", "", 12, PR_FALSE, 0 }, { "abcdefg", "a", 5, PR_TRUE, 0 }, { "abcdefg", "c", 5, PR_TRUE, 2 }, { "abcdefg", "e", 5, PR_TRUE, 4 }, { "abcdefg", "g", 5, PR_FALSE, 0 }, { "abcdefg", "i", 5, PR_FALSE, 0 }, { "abcdefg", "ab", 5, PR_TRUE, 0 }, { "abcdefg", "cd", 5, PR_TRUE, 2 }, { "abcdefg", "ef", 5, PR_FALSE, 0 }, { "abcdefg", "gh", 5, PR_FALSE, 0 }, { "abcdabc", "bc", 5, PR_TRUE, 1 }, { "abcdabc", "bc", 6, PR_TRUE, 1 }, { "abcdabc", "bc", 7, PR_TRUE, 1 }, { "abcdefg", "abcdefg", 6, PR_FALSE, 0 }, { "abcdefg", "abcdefg", 7, PR_TRUE, 0 }, { "abcdefg", "abcdefg", 8, PR_TRUE, 0 }, { "abcdefgabcdefg", "a", 12, PR_TRUE, 0 }, { "abcdefgabcdefg", "c", 12, PR_TRUE, 2 }, { "abcdefgabcdefg", "e", 12, PR_TRUE, 4 }, { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 }, { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", 12, PR_TRUE, 0 }, { "abcdefgabcdefg", "cd", 12, PR_TRUE, 2 }, { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 }, { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", 5, PR_TRUE, 1 }, { "abcdabcabcdabc", "bc", 6, PR_TRUE, 1 }, { "abcdabcabcdabc", "bc", 7, PR_TRUE, 1 }, { "abcdefgabcdefg", "abcdefg", 6, PR_FALSE, 0 }, { "abcdefgabcdefg", "abcdefg", 7, PR_TRUE, 0 }, { "abcdefgabcdefg", "abcdefg", 8, PR_TRUE, 0 }, { "ABCDEFG", "a", 5, PR_FALSE, 0 }, { "ABCDEFG", "c", 5, PR_FALSE, 0 }, { "ABCDEFG", "e", 5, PR_FALSE, 0 }, { "ABCDEFG", "g", 5, PR_FALSE, 0 }, { "ABCDEFG", "i", 5, PR_FALSE, 0 }, { "ABCDEFG", "ab", 5, PR_FALSE, 0 }, { "ABCDEFG", "cd", 5, PR_FALSE, 0 }, { "ABCDEFG", "ef", 5, PR_FALSE, 0 }, { "ABCDEFG", "gh", 5, PR_FALSE, 0 }, { "ABCDABC", "bc", 5, PR_FALSE, 0 }, { "ABCDABC", "bc", 6, PR_FALSE, 0 }, { "ABCDABC", "bc", 7, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 7, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 8, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "a", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "c", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "e", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "g", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "cd", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ef", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 5, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 6, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 7, PR_FALSE, }, { "ABCDEFGABCDEFG", "abcdefg", 6, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 7, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 8, PR_FALSE, 0 } }; int i; printf("Test 025 (PL_strnstr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strnstr(array[i].str, array[i].sub, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strnrstr */ PRBool test_026(void) { static struct { const char *str; const char *sub; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, 12, PR_FALSE, 0 }, { (const char *)0, "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 }, { "blah-de-blah", "blah", 0, PR_FALSE, 0 }, { "blah-de-blah", "blah", 2, PR_FALSE, 0 }, { "blah-de-blah", "blah", 3, PR_FALSE, 0 }, { "blah-de-blah", "blah", 4, PR_TRUE, 0 }, { "blah-de-blah", "blah", 5, PR_TRUE, 0 }, { "blah-de-blah", "blah", 11, PR_TRUE, 0 }, { "blah-de-blah", "blah", 12, PR_TRUE, 8 }, { "blah-de-blah", "blah", 13, PR_TRUE, 8 }, { "", "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", "", 12, PR_FALSE, 0 }, { "abcdefg", "a", 5, PR_TRUE, 0 }, { "abcdefg", "c", 5, PR_TRUE, 2 }, { "abcdefg", "e", 5, PR_TRUE, 4 }, { "abcdefg", "g", 5, PR_FALSE, 0 }, { "abcdefg", "i", 5, PR_FALSE, 0 }, { "abcdefg", "ab", 5, PR_TRUE, 0 }, { "abcdefg", "cd", 5, PR_TRUE, 2 }, { "abcdefg", "ef", 5, PR_FALSE, 0 }, { "abcdefg", "gh", 5, PR_FALSE, 0 }, { "abcdabc", "bc", 5, PR_TRUE, 1 }, { "abcdabc", "bc", 6, PR_TRUE, 1 }, { "abcdabc", "bc", 7, PR_TRUE, 5 }, { "abcdefg", "abcdefg", 6, PR_FALSE, 0 }, { "abcdefg", "abcdefg", 7, PR_TRUE, 0 }, { "abcdefg", "abcdefg", 8, PR_TRUE, 0 }, { "abcdefgabcdefg", "a", 12, PR_TRUE, 7 }, { "abcdefgabcdefg", "c", 12, PR_TRUE, 9 }, { "abcdefgabcdefg", "e", 12, PR_TRUE, 11 }, { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 }, { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", 12, PR_TRUE, 7 }, { "abcdefgabcdefg", "cd", 12, PR_TRUE, 9 }, { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 }, { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", 12, PR_TRUE, 8 }, { "abcdabcabcdabc", "bc", 13, PR_TRUE, 8 }, { "abcdabcabcdabc", "bc", 14, PR_TRUE, 12 }, { "abcdefgabcdefg", "abcdefg", 13, PR_TRUE, 0 }, { "abcdefgabcdefg", "abcdefg", 14, PR_TRUE, 7 }, { "abcdefgabcdefg", "abcdefg", 15, PR_TRUE, 7 }, { "ABCDEFG", "a", 5, PR_FALSE, 0 }, { "ABCDEFG", "c", 5, PR_FALSE, 0 }, { "ABCDEFG", "e", 5, PR_FALSE, 0 }, { "ABCDEFG", "g", 5, PR_FALSE, 0 }, { "ABCDEFG", "i", 5, PR_FALSE, 0 }, { "ABCDEFG", "ab", 5, PR_FALSE, 0 }, { "ABCDEFG", "cd", 5, PR_FALSE, 0 }, { "ABCDEFG", "ef", 5, PR_FALSE, 0 }, { "ABCDEFG", "gh", 5, PR_FALSE, 0 }, { "ABCDABC", "bc", 5, PR_FALSE, 0 }, { "ABCDABC", "bc", 6, PR_FALSE, 0 }, { "ABCDABC", "bc", 7, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 7, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 8, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "a", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "c", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "e", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "g", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "cd", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ef", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 12, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 13, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 14, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 13, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 14, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 15, PR_FALSE, 0 } }; int i; printf("Test 026 (PL_strnrstr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strnrstr(array[i].str, array[i].sub, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strcasestr */ PRBool test_027(void) { static struct { const char *str; const char *sub; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, PR_FALSE, 0 }, { (const char *)0, "blah", PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, PR_FALSE, 0 }, { "blah-de-blah", "blah", PR_TRUE, 0 }, { "", "blah", PR_FALSE, 0 }, { "blah-de-blah", "", PR_FALSE, 0 }, { "abcdefg", "a", PR_TRUE, 0 }, { "abcdefg", "c", PR_TRUE, 2 }, { "abcdefg", "e", PR_TRUE, 4 }, { "abcdefg", "g", PR_TRUE, 6 }, { "abcdefg", "i", PR_FALSE, 0 }, { "abcdefg", "ab", PR_TRUE, 0 }, { "abcdefg", "cd", PR_TRUE, 2 }, { "abcdefg", "ef", PR_TRUE, 4 }, { "abcdefg", "gh", PR_FALSE, 0 }, { "abcdabc", "bc", PR_TRUE, 1 }, { "abcdefg", "abcdefg", PR_TRUE, 0 }, { "abcdefgabcdefg", "a", PR_TRUE, 0 }, { "abcdefgabcdefg", "c", PR_TRUE, 2 }, { "abcdefgabcdefg", "e", PR_TRUE, 4 }, { "abcdefgabcdefg", "g", PR_TRUE, 6 }, { "abcdefgabcdefg", "i", PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", PR_TRUE, 0 }, { "abcdefgabcdefg", "cd", PR_TRUE, 2 }, { "abcdefgabcdefg", "ef", PR_TRUE, 4 }, { "abcdefgabcdefg", "gh", PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", PR_TRUE, 1 }, { "abcdefgabcdefg", "abcdefg", PR_TRUE, 0 }, { "ABCDEFG", "a", PR_TRUE, 0 }, { "ABCDEFG", "c", PR_TRUE, 2 }, { "ABCDEFG", "e", PR_TRUE, 4 }, { "ABCDEFG", "g", PR_TRUE, 6 }, { "ABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFG", "ab", PR_TRUE, 0 }, { "ABCDEFG", "cd", PR_TRUE, 2 }, { "ABCDEFG", "ef", PR_TRUE, 4 }, { "ABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABC", "bc", PR_TRUE, 1 }, { "ABCDEFG", "abcdefg", PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "a", PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "c", PR_TRUE, 2 }, { "ABCDEFGABCDEFG", "e", PR_TRUE, 4 }, { "ABCDEFGABCDEFG", "g", PR_TRUE, 6 }, { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "cd", PR_TRUE, 2 }, { "ABCDEFGABCDEFG", "ef", PR_TRUE, 4 }, { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", PR_TRUE, 1 }, { "ABCDEFGABCDEFG", "abcdefg", PR_TRUE, 0 } }; int i; printf("Test 027 (PL_strcasestr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strcasestr(array[i].str, array[i].sub); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strcaserstr */ PRBool test_028(void) { static struct { const char *str; const char *sub; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, PR_FALSE, 0 }, { (const char *)0, "blah", PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, PR_FALSE, 0 }, { "blah-de-blah", "blah", PR_TRUE, 8 }, { "", "blah", PR_FALSE, 0 }, { "blah-de-blah", "", PR_FALSE, 0 }, { "abcdefg", "a", PR_TRUE, 0 }, { "abcdefg", "c", PR_TRUE, 2 }, { "abcdefg", "e", PR_TRUE, 4 }, { "abcdefg", "g", PR_TRUE, 6 }, { "abcdefg", "i", PR_FALSE, 0 }, { "abcdefg", "ab", PR_TRUE, 0 }, { "abcdefg", "cd", PR_TRUE, 2 }, { "abcdefg", "ef", PR_TRUE, 4 }, { "abcdefg", "gh", PR_FALSE, 0 }, { "abcdabc", "bc", PR_TRUE, 5 }, { "abcdefg", "abcdefg", PR_TRUE, 0 }, { "abcdefgabcdefg", "a", PR_TRUE, 7 }, { "abcdefgabcdefg", "c", PR_TRUE, 9 }, { "abcdefgabcdefg", "e", PR_TRUE, 11 }, { "abcdefgabcdefg", "g", PR_TRUE, 13 }, { "abcdefgabcdefg", "i", PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", PR_TRUE, 7 }, { "abcdefgabcdefg", "cd", PR_TRUE, 9 }, { "abcdefgabcdefg", "ef", PR_TRUE, 11 }, { "abcdefgabcdefg", "gh", PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", PR_TRUE, 12 }, { "abcdefgabcdefg", "abcdefg", PR_TRUE, 7 }, { "ABCDEFG", "a", PR_TRUE, 0 }, { "ABCDEFG", "c", PR_TRUE, 2 }, { "ABCDEFG", "e", PR_TRUE, 4 }, { "ABCDEFG", "g", PR_TRUE, 6 }, { "ABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFG", "ab", PR_TRUE, 0 }, { "ABCDEFG", "cd", PR_TRUE, 2 }, { "ABCDEFG", "ef", PR_TRUE, 4 }, { "ABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABC", "bc", PR_TRUE, 5 }, { "ABCDEFG", "abcdefg", PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "a", PR_TRUE, 7 }, { "ABCDEFGABCDEFG", "c", PR_TRUE, 9 }, { "ABCDEFGABCDEFG", "e", PR_TRUE, 11 }, { "ABCDEFGABCDEFG", "g", PR_TRUE, 13 }, { "ABCDEFGABCDEFG", "i", PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", PR_TRUE, 7 }, { "ABCDEFGABCDEFG", "cd", PR_TRUE, 9 }, { "ABCDEFGABCDEFG", "ef", PR_TRUE, 11 }, { "ABCDEFGABCDEFG", "gh", PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", PR_TRUE, 12 }, { "ABCDEFGABCDEFG", "abcdefg", PR_TRUE, 7 } }; int i; printf("Test 028 (PL_strcaserstr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strcaserstr(array[i].str, array[i].sub); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strncasestr */ PRBool test_029(void) { static struct { const char *str; const char *sub; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, 12, PR_FALSE, 0 }, { (const char *)0, "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 }, { "blah-de-blah", "blah", 0, PR_FALSE, 0 }, { "blah-de-blah", "blah", 2, PR_FALSE, 0 }, { "blah-de-blah", "blah", 3, PR_FALSE, 0 }, { "blah-de-blah", "blah", 4, PR_TRUE, 0 }, { "blah-de-blah", "blah", 5, PR_TRUE, 0 }, { "blah-de-blah", "blah", 12, PR_TRUE, 0 }, { "", "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", "", 12, PR_FALSE, 0 }, { "abcdefg", "a", 5, PR_TRUE, 0 }, { "abcdefg", "c", 5, PR_TRUE, 2 }, { "abcdefg", "e", 5, PR_TRUE, 4 }, { "abcdefg", "g", 5, PR_FALSE, 0 }, { "abcdefg", "i", 5, PR_FALSE, 0 }, { "abcdefg", "ab", 5, PR_TRUE, 0 }, { "abcdefg", "cd", 5, PR_TRUE, 2 }, { "abcdefg", "ef", 5, PR_FALSE, 0 }, { "abcdefg", "gh", 5, PR_FALSE, 0 }, { "abcdabc", "bc", 5, PR_TRUE, 1 }, { "abcdabc", "bc", 6, PR_TRUE, 1 }, { "abcdabc", "bc", 7, PR_TRUE, 1 }, { "abcdefg", "abcdefg", 6, PR_FALSE, 0 }, { "abcdefg", "abcdefg", 7, PR_TRUE, 0 }, { "abcdefg", "abcdefg", 8, PR_TRUE, 0 }, { "abcdefgabcdefg", "a", 12, PR_TRUE, 0 }, { "abcdefgabcdefg", "c", 12, PR_TRUE, 2 }, { "abcdefgabcdefg", "e", 12, PR_TRUE, 4 }, { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 }, { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", 12, PR_TRUE, 0 }, { "abcdefgabcdefg", "cd", 12, PR_TRUE, 2 }, { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 }, { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", 5, PR_TRUE, 1 }, { "abcdabcabcdabc", "bc", 6, PR_TRUE, 1 }, { "abcdabcabcdabc", "bc", 7, PR_TRUE, 1 }, { "abcdefgabcdefg", "abcdefg", 6, PR_FALSE, 0 }, { "abcdefgabcdefg", "abcdefg", 7, PR_TRUE, 0 }, { "abcdefgabcdefg", "abcdefg", 8, PR_TRUE, 0 }, { "ABCDEFG", "a", 5, PR_TRUE, 0 }, { "ABCDEFG", "c", 5, PR_TRUE, 2 }, { "ABCDEFG", "e", 5, PR_TRUE, 4 }, { "ABCDEFG", "g", 5, PR_FALSE, 0 }, { "ABCDEFG", "i", 5, PR_FALSE, 0 }, { "ABCDEFG", "ab", 5, PR_TRUE, 0 }, { "ABCDEFG", "cd", 5, PR_TRUE, 2 }, { "ABCDEFG", "ef", 5, PR_FALSE, 0 }, { "ABCDEFG", "gh", 5, PR_FALSE, 0 }, { "ABCDABC", "bc", 5, PR_TRUE, 1 }, { "ABCDABC", "bc", 6, PR_TRUE, 1 }, { "ABCDABC", "bc", 7, PR_TRUE, 1 }, { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 7, PR_TRUE, 0 }, { "ABCDEFG", "abcdefg", 8, PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "a", 12, PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "c", 12, PR_TRUE, 2 }, { "ABCDEFGABCDEFG", "e", 12, PR_TRUE, 4 }, { "ABCDEFGABCDEFG", "g", 12, PR_TRUE, 6 }, { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", 12, PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "cd", 12, PR_TRUE, 2 }, { "ABCDEFGABCDEFG", "ef", 12, PR_TRUE, 4 }, { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 5, PR_TRUE, 1 }, { "ABCDABCABCDABC", "bc", 6, PR_TRUE, 1 }, { "ABCDABCABCDABC", "bc", 7, PR_TRUE, 1 }, { "ABCDEFGABCDEFG", "abcdefg", 6, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 7, PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 8, PR_TRUE, 0 } }; int i; printf("Test 029 (PL_strncasestr) ..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strncasestr(array[i].str, array[i].sub, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strncaserstr */ PRBool test_030(void) { static struct { const char *str; const char *sub; PRUint32 max; PRBool ret; PRUint32 off; } array[] = { { (const char *)0, (const char *)0, 12, PR_FALSE, 0 }, { (const char *)0, "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", (const char *)0, 12, PR_FALSE, 0 }, { "blah-de-blah", "blah", 0, PR_FALSE, 0 }, { "blah-de-blah", "blah", 2, PR_FALSE, 0 }, { "blah-de-blah", "blah", 3, PR_FALSE, 0 }, { "blah-de-blah", "blah", 4, PR_TRUE, 0 }, { "blah-de-blah", "blah", 5, PR_TRUE, 0 }, { "blah-de-blah", "blah", 11, PR_TRUE, 0 }, { "blah-de-blah", "blah", 12, PR_TRUE, 8 }, { "blah-de-blah", "blah", 13, PR_TRUE, 8 }, { "", "blah", 12, PR_FALSE, 0 }, { "blah-de-blah", "", 12, PR_FALSE, 0 }, { "abcdefg", "a", 5, PR_TRUE, 0 }, { "abcdefg", "c", 5, PR_TRUE, 2 }, { "abcdefg", "e", 5, PR_TRUE, 4 }, { "abcdefg", "g", 5, PR_FALSE, 0 }, { "abcdefg", "i", 5, PR_FALSE, 0 }, { "abcdefg", "ab", 5, PR_TRUE, 0 }, { "abcdefg", "cd", 5, PR_TRUE, 2 }, { "abcdefg", "ef", 5, PR_FALSE, 0 }, { "abcdefg", "gh", 5, PR_FALSE, 0 }, { "abcdabc", "bc", 5, PR_TRUE, 1 }, { "abcdabc", "bc", 6, PR_TRUE, 1 }, { "abcdabc", "bc", 7, PR_TRUE, 5 }, { "abcdefg", "abcdefg", 6, PR_FALSE, 0 }, { "abcdefg", "abcdefg", 7, PR_TRUE, 0 }, { "abcdefg", "abcdefg", 8, PR_TRUE, 0 }, { "abcdefgabcdefg", "a", 12, PR_TRUE, 7 }, { "abcdefgabcdefg", "c", 12, PR_TRUE, 9 }, { "abcdefgabcdefg", "e", 12, PR_TRUE, 11 }, { "abcdefgabcdefg", "g", 12, PR_TRUE, 6 }, { "abcdefgabcdefg", "i", 12, PR_FALSE, 0 }, { "abcdefgabcdefg", "ab", 12, PR_TRUE, 7 }, { "abcdefgabcdefg", "cd", 12, PR_TRUE, 9 }, { "abcdefgabcdefg", "ef", 12, PR_TRUE, 4 }, { "abcdefgabcdefg", "gh", 12, PR_FALSE, 0 }, { "abcdabcabcdabc", "bc", 12, PR_TRUE, 8 }, { "abcdabcabcdabc", "bc", 13, PR_TRUE, 8 }, { "abcdabcabcdabc", "bc", 14, PR_TRUE, 12 }, { "abcdefgabcdefg", "abcdefg", 13, PR_TRUE, 0 }, { "abcdefgabcdefg", "abcdefg", 14, PR_TRUE, 7 }, { "abcdefgabcdefg", "abcdefg", 15, PR_TRUE, 7 }, { "ABCDEFG", "a", 5, PR_TRUE, 0 }, { "ABCDEFG", "c", 5, PR_TRUE, 2 }, { "ABCDEFG", "e", 5, PR_TRUE, 4 }, { "ABCDEFG", "g", 5, PR_FALSE, 0 }, { "ABCDEFG", "i", 5, PR_FALSE, 0 }, { "ABCDEFG", "ab", 5, PR_TRUE, 0 }, { "ABCDEFG", "cd", 5, PR_TRUE, 2 }, { "ABCDEFG", "ef", 5, PR_FALSE, 0 }, { "ABCDEFG", "gh", 5, PR_FALSE, 0 }, { "ABCDABC", "bc", 5, PR_TRUE, 1 }, { "ABCDABC", "bc", 6, PR_TRUE, 1 }, { "ABCDABC", "bc", 7, PR_TRUE, 5 }, { "ABCDEFG", "abcdefg", 6, PR_FALSE, 0 }, { "ABCDEFG", "abcdefg", 7, PR_TRUE, 0 }, { "ABCDEFG", "abcdefg", 8, PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "a", 12, PR_TRUE, 7 }, { "ABCDEFGABCDEFG", "c", 12, PR_TRUE, 9 }, { "ABCDEFGABCDEFG", "e", 12, PR_TRUE, 11 }, { "ABCDEFGABCDEFG", "g", 12, PR_TRUE, 6 }, { "ABCDEFGABCDEFG", "i", 12, PR_FALSE, 0 }, { "ABCDEFGABCDEFG", "ab", 12, PR_TRUE, 7 }, { "ABCDEFGABCDEFG", "cd", 12, PR_TRUE, 9 }, { "ABCDEFGABCDEFG", "ef", 12, PR_TRUE, 4 }, { "ABCDEFGABCDEFG", "gh", 12, PR_FALSE, 0 }, { "ABCDABCABCDABC", "bc", 12, PR_TRUE, 8 }, { "ABCDABCABCDABC", "bc", 13, PR_TRUE, 8 }, { "ABCDABCABCDABC", "bc", 14, PR_TRUE, 12 }, { "ABCDEFGABCDEFG", "abcdefg", 13, PR_TRUE, 0 }, { "ABCDEFGABCDEFG", "abcdefg", 14, PR_TRUE, 7 }, { "ABCDEFGABCDEFG", "abcdefg", 15, PR_TRUE, 7 } }; int i; printf("Test 030 (PL_strncaserstr)..."); fflush(stdout); for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) { char *rv = PL_strncaserstr(array[i].str, array[i].sub, array[i].max); if( PR_FALSE == array[i].ret ) { if( (char *)0 != rv ) { printf("FAIL %d: %s,%s/%lu -> %.32s, not null\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv); return PR_FALSE; } } else { if( (char *)0 == rv ) { printf("FAIL %d: %s,%s/%lu -> null, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, array[i].str, array[i].off); return PR_FALSE; } if( &array[i].str[ array[i].off ] != rv ) { printf("FAIL %d: %s,%s/%lu -> 0x%x, not 0x%x+%lu\n", i, array[i].str ? array[i].str : "(null)", array[i].sub ? array[i].sub : "(null)", array[i].max, rv, array[i].str, array[i].off); return PR_FALSE; } } } printf("PASS\n"); return PR_TRUE; } /* PL_strtok_r */ PRBool test_031(void) { static const char *tokens[] = { "wtc", "relyea", "nelsonb", "jpierre", "nicolson", "ian.mcgreer", "kirk.erickson", "sonja.mirtitsch", "mhein" }; static const char *seps[] = { ", ", ",", " ", "\t", ",,,", " ,", " ", " \t\t", "," }; static const char s2[] = ", \t"; char string[ 1024 ]; char *s1; char *token; char *lasts; unsigned int i; printf("Test 031 (PL_strtok_r) ..."); fflush(stdout); /* Build the string. */ string[0] = '\0'; for( i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++ ) { PL_strcat(string, tokens[i]); PL_strcat(string, seps[i]); } /* Scan the string for tokens. */ i = 0; s1 = string; while( (token = PL_strtok_r(s1, s2, &lasts)) != NULL) { if( PL_strcmp(token, tokens[i]) != 0 ) { printf("FAIL wrong token scanned\n"); return PR_FALSE; } i++; s1 = NULL; } if( i != sizeof(tokens)/sizeof(tokens[0]) ) { printf("FAIL wrong number of tokens scanned\n"); return PR_FALSE; } printf("PASS\n"); return PR_TRUE; } int main ( int argc, char *argv[] ) { printf("Testing the Portable Library string functions:\n"); if( 1 && test_001() && test_001() && test_002() && test_003() && test_004() && test_005() && test_006() && test_007() && test_008() && test_009() && test_010() && test_011() && test_012() && test_013() && test_014() && test_015() && test_016() && test_017() && test_018() && test_019() && test_020() && test_021() && test_022() && test_023() && test_024() && test_025() && test_026() && test_027() && test_028() && test_029() && test_030() && test_031() ) { printf("Suite passed.\n"); return 0; } else { printf("Suite failed.\n"); return 1; } /*NOTREACHED*/ } nspr-4.11/nspr/pkg/Makefile.in0000644000000000000000000000113112623070344014354 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = .. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk DIRS = ifeq ($(OS_TARGET),Linux) DIRS = linux endif ifeq ($(OS_TARGET),SunOS) DIRS = solaris endif publish:: +$(LOOP_OVER_DIRS) include $(topsrcdir)/config/rules.mk nspr-4.11/nspr/pkg/linux/Makefile.in0000644000000000000000000000515112623070344015521 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ NAME = sun-nspr ifndef RPM_RELEASE RPM_RELEASE = 1 endif TOPDIR = /usr/src/redhat VERSION = `grep PR_VERSION $(dist_includedir)/prinit.h \ | sed -e 's/"$$//' -e 's/.*"//' -e 's/ .*//'` SPECFILE = $(NAME).spec include $(MOD_DEPTH)/config/autoconf.mk # Force i386 for non 64 bit build ifneq ($(USE_64),1) RPMTARGET = "--target=i386" RPMLIBDIR = lib else RPMLIBDIR = lib64 endif publish: $(MAKE) clean mkdir -p SOURCES SRPMS RPMS BUILD (cd $(dist_libdir) && tar cphf - libnspr4.so libplds4.so libplc4.so) \ | (mkdir -p opt/sun/private/$(RPMLIBDIR) && cd opt/sun/private/$(RPMLIBDIR) && tar xvfBp -) (cd $(dist_includedir) && tar cphf - .) \ | (mkdir -p opt/sun/private/include/nspr && cd opt/sun/private/include/nspr && tar xvfBp -) (cd opt/sun/private/include/nspr && \ rm -rf md) tar czvf SOURCES/$(NAME)-$(VERSION).tar.gz opt echo "%define name $(NAME)" >$(SPECFILE) echo "%define version $(VERSION)" >>$(SPECFILE) echo "%define release $(RPM_RELEASE)" >>$(SPECFILE) echo "%define buildroot `pwd`/$(NAME)-root" >>$(SPECFILE) echo "%define _topdir `pwd`" >>$(SPECFILE) echo "%define _unpackaged_files_terminate_build 0" >>$(SPECFILE) cat $(srcdir)/$(NAME).spec >>$(SPECFILE) echo "" >>$(SPECFILE) echo "%files" >>$(SPECFILE) echo "%defattr(-,root,root)" >>$(SPECFILE) echo "%dir /opt" >>$(SPECFILE) echo "%dir /opt/sun" >>$(SPECFILE) echo "%dir /opt/sun/private" >>$(SPECFILE) echo "%dir /opt/sun/private/$(RPMLIBDIR)" >>$(SPECFILE) find opt \( -name "*.so" \) | sed -e "s-^-/-" >>$(SPECFILE) echo "" >>$(SPECFILE) echo "%files devel" >>$(SPECFILE) echo "%defattr(-,root,root)" >>$(SPECFILE) echo "%dir /opt" >>$(SPECFILE) echo "%dir /opt/sun" >>$(SPECFILE) echo "%dir /opt/sun/private" >>$(SPECFILE) echo "%dir /opt/sun/private/include" >>$(SPECFILE) echo "%dir /opt/sun/private/include/nspr" >>$(SPECFILE) echo "%dir /opt/sun/private/include/nspr/obsolete" >>$(SPECFILE) echo "%dir /opt/sun/private/include/nspr/private" >>$(SPECFILE) find opt -type f \( -name "*.h" \) \ | sed -e "s-^-/-" >>$(SPECFILE) rpmbuild $(RPMTARGET) -bb $(SPECFILE) clean: rm -rf $(TOPDIR)/BUILD/$(NAME) rm -rf SOURCES SRPMS RPMS BUILD rm -rf RPMS SRPMS opt rm -f $(NAME)-$(VERSION).tar.gz nspr-4.11/nspr/pkg/linux/sun-nspr.spec0000644000000000000000000000267712623070344016127 0ustar 00000000000000Summary: Netscape Portable Runtime Name: %{name} Vendor: Sun Microsystems, Inc. Version: %{version} Release: %{release} Copyright: Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Also under other license(s) as shown at the Description field. Distribution: Sun Java(TM) Enterprise System URL: http://www.sun.com Group: System Environment/Base Source: %{name}-%{version}.tar.gz ExclusiveOS: Linux BuildRoot: /var/tmp/%{name}-root %description NSPR provides platform independence for non-GUI operating system facilities. These facilities include threads, thread synchronization, normal file and network I/O, interval timing and calendar time, basic memory management (malloc and free) and shared library linking. See: http://www.mozilla.org/projects/nspr/about-nspr.html This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. %package devel Summary: Development Libraries for the Netscape Portable Runtime Group: Development/Libraries Requires: %{name} = %{version}-%{release} %description devel Header files for doing development with the Netscape Portable Runtime. Under "MPL/GPL" license. %prep %setup -c %build %install rm -rf $RPM_BUILD_ROOT mkdir $RPM_BUILD_ROOT cd $RPM_BUILD_ROOT tar xvzf $RPM_SOURCE_DIR/%{name}-%{version}.tar.gz %clean rm -rf $RPM_BUILD_ROOT nspr-4.11/nspr/pkg/solaris/Makefile-devl.com0000755000000000000000000000136012623070344017137 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # MACH = $(shell mach) PUBLISH_ROOT = $(DIST) ifeq ($(MOD_DEPTH),../..) ROOT = ROOT else ROOT = $(subst ../../,,$(MOD_DEPTH))/ROOT endif PKGARCHIVE = $(dist_prefix)/pkgarchive DATAFILES = copyright FILES = $(DATAFILES) pkginfo PACKAGE = $(shell basename `pwd`) PRODUCT_VERSION = "$(MOD_VERSION).$(MOD_MINOR).$(MOD_PATCH)$(MOD_BETA)" LN = /usr/bin/ln CLOBBERFILES = $(FILES) include $(topsrcdir)/config/rules.mk # vim: ft=make nspr-4.11/nspr/pkg/solaris/Makefile-devl.targ0000755000000000000000000000166312623070344017324 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # include $(srcdir)/../proto64.mk pkginfo: pkginfo.tmpl ../awk_pkginfo $(RM) $@; nawk -f ../awk_pkginfo $(srcdir)/$@.tmpl > $@ pkg: $(PKGARCHIVE) cat $(srcdir)/prototype | sed $(sed_proto64) > prototype cp $(srcdir)/depend . pkgmk -f prototype -d $(PKGARCHIVE) -r $(ROOT) -o $(PACKAGE) $(PKGARCHIVE): [ -d $(PKGARCHIVE) ] || mkdir -p $(PKGARCHIVE) $(DATAFILES): %: $(srcdir)/../common_files/% $(RM) $@; cp $(srcdir)/../common_files/$@ $@ $(MACHDATAFILES): %: $(srcdir)/../common_files/%_$(MACH) $(RM) $@; cp $(srcdir)/../common_files/$@_$(MACH) $@ clobber clean:: -$(RM) $(CLOBBERFILES) $(CLEANFILES) .PHONY: pkg nspr-4.11/nspr/pkg/solaris/Makefile.com0000644000000000000000000000146512623070344016212 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # MACH = $(shell mach) PUBLISH_ROOT = $(DIST) ifeq ($(MOD_DEPTH),../..) ROOT = ROOT else ROOT = $(subst ../../,,$(MOD_DEPTH))/ROOT endif PKGARCHIVE = $(dist_prefix)/pkgarchive DATAFILES = copyright FILES = $(DATAFILES) pkginfo PACKAGE = $(shell basename `pwd`) PRODUCT_VERSION = $(shell grep PR_VERSION $(dist_includedir)/prinit.h \ | sed -e 's/"$$//' -e 's/.*"//' -e 's/ .*//') LN = /usr/bin/ln CP = /usr/bin/cp CLOBBERFILES = $(FILES) include $(topsrcdir)/config/rules.mk # vim: ft=make nspr-4.11/nspr/pkg/solaris/Makefile.in0000644000000000000000000000434312623070344016040 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk abs_dist_libdir := $(shell (cd $(dist_libdir);pwd)) abs_dist_includedir := $(shell (cd $(dist_includedir);pwd)) %: %.ksh $(RM) $@ cp $< $@ chmod +x $@ DIRS = \ SUNWpr \ SUNWprd include $(srcdir)/Makefile.com PROTO = \ $(ROOT) \ $(ROOT)/usr/lib/mps \ $(ROOT)/usr/include/mps ifeq ($(MACH), sparc) PROTO += $(ROOT)/usr/lib/mps/cpu/sparcv8plus endif ifeq ($(USE_64), 1) ifeq ($(MACH), sparc) # Sparc PROTO += $(ROOT)/usr/lib/mps/sparcv9 else # AMD64 PROTO += $(ROOT)/usr/lib/mps/amd64 endif abs_dist64_libdir = $(abs_dist_libdir) abs_dist32_libdir = $(shell echo $(abs_dist_libdir) | sed -e "s|_64_OPT|_OPT|g" -e "s|_64_DBG|_DBG|g") abs_dist64_includedir = $(abs_dist_includedir) abs_dist32_includedir = $(shell echo $(abs_dist_includedir) | sed -e "s|_64_OPT|_OPT|g" -e "s|_64_DBG|_DBG|g") else abs_dist32_libdir = $(abs_dist_libdir) abs_dist64_libdir = $(shell echo $(abs_dist_libdir) | sed -e "s|_OPT|_64_OPT|g" -e "s|_DBG|_64_DBG|g") abs_dist32_includedir = $(abs_dist_includedir) abs_dist64_includedir = $(shell echo $(abs_dist_includedir) | sed -e "s|_OPT|_64_OPT|g" -e "s|_DBG|_64_DBG|g") endif awk_pkginfo: bld_awk_pkginfo ./bld_awk_pkginfo -m $(MACH) -p "$(PRODUCT_VERSION)" -o $@ -v $(PRODUCT_VERSION) all:: awk_pkginfo $(PROTO) publish: awk_pkginfo $(PROTO) +$(LOOP_OVER_DIRS) clean clobber:: $(RM) awk_pkginfo bld_awk_pkginfo $(RM) -r $(ROOT) $(ROOT): mkdir -p $@ $(ROOT)/usr/lib/mps/sparcv9: mkdir -p $@ $(CP) -r $(abs_dist64_libdir)/*.so $@ $(ROOT)/usr/lib/mps/amd64: mkdir -p $@ $(CP) -r $(abs_dist64_libdir)/*.so $@ $(ROOT)/usr/lib/mps: mkdir -p $@ $(CP) -r $(abs_dist32_libdir)/*.so $@ $(ROOT)/usr/lib/mps/cpu/sparcv8plus: mkdir -p $@ $(CP) -r $(abs_dist32_libdir)/cpu/sparcv8plus/*.so $@ $(ROOT)/usr/include/mps: mkdir -p $@ $(CP) -r $(abs_dist32_includedir)/* $@ nspr-4.11/nspr/pkg/solaris/Makefile.targ0000644000000000000000000000157412623070344016372 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # include $(srcdir)/../proto64.mk pkginfo: pkginfo.tmpl ../awk_pkginfo $(RM) $@; nawk -f ../awk_pkginfo $< > $@ pkg: $(PKGARCHIVE) prototype_$(MACH) cp $(srcdir)/prototype_com . cat $(srcdir)/prototype_$(MACH) | sed $(sed_proto64) > prototype_$(MACH) cp $(srcdir)/depend . pkgmk -f prototype_$(MACH) -d $(PKGARCHIVE) -r $(ROOT) -o $(PACKAGE) $(PKGARCHIVE): [ -d $(PKGARCHIVE) ] || mkdir -p $(PKGARCHIVE) $(DATAFILES): %: $(srcdir)/../common_files/% $(RM) $@; cp $(srcdir)/../common_files/$@ $@ clobber clean:: -$(RM) $(CLOBBERFILES) $(CLEANFILES) .PHONY: pkg nspr-4.11/nspr/pkg/solaris/SUNWpr/Makefile.in0000644000000000000000000000107512623070344017175 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(srcdir)/../Makefile.com DATAFILES += all:: $(FILES) publish:: all pkg include $(srcdir)/../Makefile.targ nspr-4.11/nspr/pkg/solaris/SUNWpr/depend0000644000000000000000000000204712623070344016312 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # $Id$ # # This package information file defines software dependencies associated # with the pkg. You can define three types of pkg dependencies with this file: # P indicates a prerequisite for installation # I indicates an incompatible package # R indicates a reverse dependency # see pkginfo(4), PKG parameter # see pkginfo(4), NAME parameter # see pkginfo(4), VERSION parameter # see pkginfo(4), ARCH parameter # # () # () # ... # # ... P SUNWcar Core Architecture, (Root) P SUNWkvm Core Architecture, (Kvm) P SUNWcsr Core Solaris, (Root) P SUNWcsu Core Solaris, (Usr) P SUNWcsd Core Solaris Devices P SUNWcsl Core Solaris Libraries nspr-4.11/nspr/pkg/solaris/SUNWpr/pkginfo.tmpl0000644000000000000000000000215612623070344017464 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # # This required package information file describes characteristics of the # package, such as package abbreviation, full package name, package version, # and package architecture. # PKG="SUNWpr" NAME="Netscape Portable Runtime" ARCH="ISA" VERSION="NSPRVERS,REV=0.0.0" SUNW_PRODNAME="Netscape Portable Runtime" SUNW_PRODVERS="NSPRVERS" SUNW_PKGTYPE="usr" MAXINST="1000" CATEGORY="system" DESC="Netscape Portable Runtime Interface" VENDOR="Sun Microsystems, Inc." HOTLINE="Please contact your local service provider" EMAIL="" CLASSES="none" BASEDIR=/ SUNW_PKGVERS="1.0" #VSTOCK="" #ISTATES="" #RSTATES='' #ULIMIT="" #ORDER="" #PSTAMP="" #INTONLY="" nspr-4.11/nspr/pkg/solaris/SUNWpr/prototype_com0000644000000000000000000000256512623070344017763 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package # and their location on the development machine when building the package. # Can be created via a text editor or through use of the 'pkgproto' command. #!search # where to find pkg objects #!include # include another 'prototype' file #!default # default used if not specified on entry #!= # puts parameter in pkg environment # packaging files i copyright i pkginfo i depend # # source locations relative to the prototype file # # SUNWpr # d none usr 755 root sys d none usr/lib 755 root bin d none usr/lib/mps 755 root bin d none usr/lib/mps/secv1 755 root bin f none usr/lib/mps/libnspr4.so 755 root bin f none usr/lib/mps/libplc4.so 755 root bin f none usr/lib/mps/libplds4.so 755 root bin s none usr/lib/mps/secv1/libnspr4.so=../libnspr4.so s none usr/lib/mps/secv1/libplc4.so=../libplc4.so s none usr/lib/mps/secv1/libplds4.so=../libplds4.so nspr-4.11/nspr/pkg/solaris/SUNWpr/prototype_i3860000644000000000000000000000307712623070344017675 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package # and their location on the development machine when building the package. # Can be created via a text editor or through use of the 'pkgproto' command. #!search # where to find pkg objects #!include # include another 'prototype' file #!default # default used if not specified on entry #!= # puts parameter in pkg environment # # Include ISA independent files (prototype_com) # !include prototype_com # # # # List files which are i386 specific here # # source locations relative to the prototype file # # # SUNWpr # #64#s none usr/lib/mps/64=amd64 #64#s none usr/lib/mps/secv1/64=amd64 #64#d none usr/lib/mps/amd64 755 root bin #64#d none usr/lib/mps/secv1/amd64 755 root bin #64#f none usr/lib/mps/amd64/libnspr4.so 755 root bin #64#f none usr/lib/mps/amd64/libplc4.so 755 root bin #64#f none usr/lib/mps/amd64/libplds4.so 755 root bin #64#s none usr/lib/mps/secv1/amd64/libnspr4.so=../../amd64/libnspr4.so #64#s none usr/lib/mps/secv1/amd64/libplc4.so=../../amd64/libplc4.so #64#s none usr/lib/mps/secv1/amd64/libplds4.so=../../amd64/libplds4.so nspr-4.11/nspr/pkg/solaris/SUNWpr/prototype_sparc0000644000000000000000000000366012623070344020312 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package # and their location on the development machine when building the package. # Can be created via a text editor or through use of the 'pkgproto' command. #!search # where to find pkg objects #!include # include another 'prototype' file #!default # default used if not specified on entry #!= # puts parameter in pkg environment # # Include ISA independent files (prototype_com) # !include prototype_com # # # # List files which are SPARC specific here # # source locations relative to the prototype file # # # SUNWpr # d none usr/lib/mps/cpu 755 root bin d none usr/lib/mps/cpu/sparcv8plus 755 root bin d none usr/lib/mps/secv1/cpu 755 root bin d none usr/lib/mps/secv1/cpu/sparcv8plus 755 root bin f none usr/lib/mps/cpu/sparcv8plus/libnspr_flt4.so 755 root bin s none usr/lib/mps/secv1/cpu/sparcv8plus/libnspr_flt4.so=../../../cpu/sparcv8plus/libnspr_flt4.so #64#s none usr/lib/mps/64=sparcv9 #64#s none usr/lib/mps/secv1/64=sparcv9 #64#d none usr/lib/mps/sparcv9 755 root bin #64#d none usr/lib/mps/secv1/sparcv9 755 root bin #64#f none usr/lib/mps/sparcv9/libnspr4.so 755 root bin #64#f none usr/lib/mps/sparcv9/libplc4.so 755 root bin #64#f none usr/lib/mps/sparcv9/libplds4.so 755 root bin #64#s none usr/lib/mps/secv1/sparcv9/libnspr4.so=../../sparcv9/libnspr4.so #64#s none usr/lib/mps/secv1/sparcv9/libplc4.so=../../sparcv9/libplc4.so #64#s none usr/lib/mps/secv1/sparcv9/libplds4.so=../../sparcv9/libplds4.so nspr-4.11/nspr/pkg/solaris/SUNWprd/Makefile.in0000755000000000000000000000111212623070344017334 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(srcdir)/../Makefile-devl.com DATAFILES += all:: $(FILES) publish:: all pkg include $(srcdir)/../Makefile-devl.targ nspr-4.11/nspr/pkg/solaris/SUNWprd/depend0000755000000000000000000000160612623070344016461 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # $Id$ # # This package information file defines software dependencies associated # with the pkg. You can define three types of pkg dependencies with this file: # P indicates a prerequisite for installation # I indicates an incompatible package # R indicates a reverse dependency # see pkginfo(4), PKG parameter # see pkginfo(4), NAME parameter # see pkginfo(4), VERSION parameter # see pkginfo(4), ARCH parameter # # () # () # ... # # ... P SUNWpr Netscape Portable Runtime nspr-4.11/nspr/pkg/solaris/SUNWprd/pkginfo.tmpl0000755000000000000000000000223512623070344017631 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # # This required package information file describes characteristics of the # package, such as package abbreviation, full package name, package version, # and package architecture. # PKG="SUNWprd" NAME="Netscape Portable Runtime Development" ARCH="ISA" VERSION="NSPRVERS,REV=0.0.0" SUNW_PRODNAME="Netscape Portable Runtime Development" SUNW_PRODVERS="NSPRVERS" SUNW_PKGTYPE="usr" MAXINST="1000" CATEGORY="system" DESC="Netscape Portable Runtime Interface Files for Development" VENDOR="Sun Microsystems, Inc." HOTLINE="Please contact your local service provider" EMAIL="" CLASSES="none" BASEDIR=/ SUNW_PKGVERS="1.0" #VSTOCK="" #ISTATES="" #RSTATES='' #ULIMIT="" #ORDER="" #PSTAMP="" #INTONLY="" nspr-4.11/nspr/pkg/solaris/SUNWprd/prototype0000755000000000000000000000742212623070344017271 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package # and their location on the development machine when building the package. # Can be created via a text editor or through use of the 'pkgproto' command. #!search # where to find pkg objects #!include # include another 'prototype' file #!default # default used if not specified on entry #!= # puts parameter in pkg environment # packaging files i copyright i pkginfo i depend # # source locations relative to .h 0644 root bine prototype file # # SUNWprd # d none usr 0755 root sys d none usr/include 0755 root bin d none usr/include/mps 0755 root bin d none usr/include/mps/obsolete 0755 root bin d none usr/include/mps/private 0755 root bin f none usr/include/mps/obsolete/pralarm.h 0644 root bin f none usr/include/mps/obsolete/probslet.h 0644 root bin f none usr/include/mps/obsolete/protypes.h 0644 root bin f none usr/include/mps/obsolete/prsem.h 0644 root bin f none usr/include/mps/prcpucfg.h 0644 root bin f none usr/include/mps/nspr.h 0644 root bin f none usr/include/mps/pratom.h 0644 root bin f none usr/include/mps/prbit.h 0644 root bin f none usr/include/mps/prclist.h 0644 root bin f none usr/include/mps/prcmon.h 0644 root bin f none usr/include/mps/prcountr.h 0644 root bin f none usr/include/mps/prcvar.h 0644 root bin f none usr/include/mps/prdtoa.h 0644 root bin f none usr/include/mps/prenv.h 0644 root bin f none usr/include/mps/prerr.h 0644 root bin f none usr/include/mps/prerror.h 0644 root bin f none usr/include/mps/prinet.h 0644 root bin f none usr/include/mps/prinit.h 0644 root bin f none usr/include/mps/prinrval.h 0644 root bin f none usr/include/mps/prio.h 0644 root bin f none usr/include/mps/pripcsem.h 0644 root bin f none usr/include/mps/private/pprio.h 0644 root bin f none usr/include/mps/private/pprthred.h 0644 root bin f none usr/include/mps/private/prpriv.h 0644 root bin f none usr/include/mps/prlink.h 0644 root bin f none usr/include/mps/prlock.h 0644 root bin f none usr/include/mps/prlog.h 0644 root bin f none usr/include/mps/prlong.h 0644 root bin f none usr/include/mps/prmem.h 0644 root bin f none usr/include/mps/prmon.h 0644 root bin f none usr/include/mps/prmwait.h 0644 root bin f none usr/include/mps/prnetdb.h 0644 root bin f none usr/include/mps/prolock.h 0644 root bin f none usr/include/mps/prpdce.h 0644 root bin f none usr/include/mps/prprf.h 0644 root bin f none usr/include/mps/prproces.h 0644 root bin f none usr/include/mps/prrng.h 0644 root bin f none usr/include/mps/prrwlock.h 0644 root bin f none usr/include/mps/prshm.h 0644 root bin f none usr/include/mps/prshma.h 0644 root bin f none usr/include/mps/prsystem.h 0644 root bin f none usr/include/mps/prthread.h 0644 root bin f none usr/include/mps/prtime.h 0644 root bin f none usr/include/mps/prtpool.h 0644 root bin f none usr/include/mps/prtrace.h 0644 root bin f none usr/include/mps/prtypes.h 0644 root bin f none usr/include/mps/prvrsion.h 0644 root bin f none usr/include/mps/prwin16.h 0644 root bin f none usr/include/mps/plarenas.h 0644 root bin f none usr/include/mps/plarena.h 0644 root bin f none usr/include/mps/plbase64.h 0644 root bin f none usr/include/mps/plerror.h 0644 root bin f none usr/include/mps/plgetopt.h 0644 root bin f none usr/include/mps/plhash.h 0644 root bin f none usr/include/mps/plstr.h 0644 root bin nspr-4.11/nspr/pkg/solaris/bld_awk_pkginfo.ksh0000644000000000000000000000357612623070344017631 0ustar 00000000000000#!/usr/bin/ksh -p # # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # # Simple script which builds the awk_pkginfo awk script. This awk script # is used to convert the pkginfo.tmpl files into pkginfo files # for the build. # usage() { cat <<-EOF usage: bld_awk_pkginfo -p -m -o [-v ] EOF } # # Awk strings # # two VERSION patterns: one for Dewey decimal, one for Dewey plus ,REV=n # the first has one '=' the second has two or more '=' # VERSION1="VERSION=[^=]*$" VERSION2="VERSION=[^=]*=.*$" PRODVERS="^SUNW_PRODVERS=" ARCH='ARCH=\"ISA\"' # # parse command line # mach="" prodver="" awk_script="" version="NSPRVERS" while getopts o:p:m:v: c do case $c in o) awk_script=$OPTARG ;; m) mach=$OPTARG ;; p) prodver=$OPTARG ;; v) version=$OPTARG ;; \?) usage exit 1 ;; esac done if [[ ( -z $prodver ) || ( -z $mach ) || ( -z $awk_script ) ]] then usage exit 1 fi if [[ -f $awk_script ]] then rm -f $awk_script fi # # Build REV= field based on date # rev=$(date "+%Y.%m.%d.%H.%M") # # Build awk script which will process all the # pkginfo.tmpl files. # # the first VERSION pattern is replaced with a leading quotation mark # rm -f $awk_script cat << EOF > $awk_script /$VERSION1/ { sub(/\=[^=]*$/,"=\"$rev\"") print next } /$VERSION2/ { sub(/\=[^=]*$/,"=$rev\"") sub(/NSPRVERS/,"$version") print next } /$PRODVERS/ { printf "SUNW_PRODVERS=\"%s\"\n", "$prodver" next } /$ARCH/ { printf "ARCH=\"%s\"\n", "$mach" next } { print } EOF nspr-4.11/nspr/pkg/solaris/common_files/copyright0000644000000000000000000000043712623070344020400 0ustar 00000000000000Copyright 2005 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. nspr-4.11/nspr/pkg/solaris/proto64.mk0000644000000000000000000000067412623070344015644 0ustar 00000000000000# # Copyright 2005 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # #ident "$Id$" # ifeq ($(USE_64), 1) # Remove 64 tag sed_proto64='s/\#64\#//g' else # Strip 64 lines sed_proto64='/\#64\#/d' endif nspr-4.11/nspr/pr/.cvsignore0000644000000000000000000000001112623070344014143 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/Makefile.in0000644000000000000000000000060512623070344014221 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = .. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk DIRS = include src include $(topsrcdir)/config/rules.mk nspr-4.11/nspr/pr/include/.cvsignore0000644000000000000000000000001112623070344015566 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/include/Makefile.in0000644000000000000000000000117612623070344015650 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk DIRS = md private obsolete include $(topsrcdir)/config/config.mk HEADERS = $(wildcard $(srcdir)/*.h) RELEASE_HEADERS = $(HEADERS) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR) include $(topsrcdir)/config/rules.mk export:: $(RELEASE_HEADERS) $(INSTALL) -m 444 $(RELEASE_HEADERS) $(dist_includedir) nspr-4.11/nspr/pr/include/gencfg.c0000644000000000000000000001447512623070344015206 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #if defined(sgi) #ifndef IRIX error - IRIX is not defined #endif #endif #if defined(__sun) #ifndef SOLARIS error - SOLARIS is not defined #endif #endif #if defined(__hpux) #ifndef HPUX error - HPUX is not defined #endif #endif #if defined(__alpha) #if !(defined(_WIN32)) && !(defined(OSF1)) && !(defined(__linux)) && !(defined(__FreeBSD__)) error - None of OSF1, _WIN32, __linux, or __FreeBSD__ is defined #endif #endif #if defined(_IBMR2) #ifndef AIX error - AIX is not defined #endif #endif #if defined(linux) #ifndef LINUX error - LINUX is not defined #endif #endif #if defined(bsdi) #ifndef BSDI error - BSDI is not defined #endif #endif #if defined(M_UNIX) #ifndef SCO error - SCO is not defined #endif #endif #if !defined(M_UNIX) && defined(_USLC_) #ifndef UNIXWARE error - UNIXWARE is not defined #endif #endif #if defined(__APPLE__) #ifndef DARWIN error - DARWIN is not defined #endif #endif /************************************************************************/ /* Generate cpucfg.h */ #ifdef XP_PC #ifdef WIN32 #define INT64 _PRInt64 #else #define INT64 long #endif #else #if defined(HPUX) || defined(SCO) || defined(UNIXWARE) #define INT64 long #else #define INT64 long long #endif #endif struct align_short { char c; short a; }; struct align_int { char c; int a; }; struct align_long { char c; long a; }; struct align_PRInt64 { char c; INT64 a; }; struct align_fakelonglong { char c; struct { long hi, lo; } a; }; struct align_float { char c; float a; }; struct align_double { char c; double a; }; struct align_pointer { char c; void *a; }; #define ALIGN_OF(type) \ (((char*)&(((struct align_##type *)0)->a)) - ((char*)0)) int bpb; /* Used if shell doesn't support redirection. By default, assume it does. */ FILE *stream; static int Log2(int n) { int log2 = 0; if (n & (n-1)) log2++; if (n >> 16) log2 += 16, n >>= 16; if (n >> 8) log2 += 8, n >>= 8; if (n >> 4) log2 += 4, n >>= 4; if (n >> 2) log2 += 2, n >>= 2; if (n >> 1) log2++; return log2; } /* We assume that int's are 32 bits */ static void do64(void) { union { int i; char c[4]; } u; u.i = 0x01020304; if (u.c[0] == 0x01) { fprintf(stream, "#undef IS_LITTLE_ENDIAN\n"); fprintf(stream, "#define IS_BIG_ENDIAN 1\n\n"); } else { fprintf(stream, "#define IS_LITTLE_ENDIAN 1\n"); fprintf(stream, "#undef IS_BIG_ENDIAN\n\n"); } } static void do32(void) { union { long i; char c[4]; } u; u.i = 0x01020304; if (u.c[0] == 0x01) { fprintf(stream, "#undef IS_LITTLE_ENDIAN\n"); fprintf(stream, "#define IS_BIG_ENDIAN 1\n\n"); } else { fprintf(stream, "#define IS_LITTLE_ENDIAN 1\n"); fprintf(stream, "#undef IS_BIG_ENDIAN\n\n"); } } /* ** Concievably this could actually be used; but there is lots of code out ** there with and's and shift's in it that assumes a byte is 8 bits, so ** forget about porting THIS code to those non 8 bit byte machines. */ static void BitsPerByte(void) { bpb = 8; } int main(int argc, char **argv) { BitsPerByte(); /* If we got a command line argument, try to use it as the stream. */ ++argv; if(*argv) { if(!(stream = fopen ( *argv, "wt" ))) { fprintf(stderr, "Could not write to output file %s.\n", *argv); return 1; } } else { stream = stdout; } fprintf(stream, "#ifndef nspr_cpucfg___\n"); fprintf(stream, "#define nspr_cpucfg___\n\n"); fprintf(stream, "/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n"); if (sizeof(long) == 8) { do64(); } else { do32(); } fprintf(stream, "#define PR_BYTES_PER_BYTE %d\n", sizeof(char)); fprintf(stream, "#define PR_BYTES_PER_SHORT %d\n", sizeof(short)); fprintf(stream, "#define PR_BYTES_PER_INT %d\n", sizeof(int)); fprintf(stream, "#define PR_BYTES_PER_INT64 %d\n", 8); fprintf(stream, "#define PR_BYTES_PER_LONG %d\n", sizeof(long)); fprintf(stream, "#define PR_BYTES_PER_FLOAT %d\n", sizeof(float)); fprintf(stream, "#define PR_BYTES_PER_DOUBLE %d\n\n", sizeof(double)); fprintf(stream, "#define PR_BITS_PER_BYTE %d\n", bpb); fprintf(stream, "#define PR_BITS_PER_SHORT %d\n", bpb * sizeof(short)); fprintf(stream, "#define PR_BITS_PER_INT %d\n", bpb * sizeof(int)); fprintf(stream, "#define PR_BITS_PER_INT64 %d\n", bpb * 8); fprintf(stream, "#define PR_BITS_PER_LONG %d\n", bpb * sizeof(long)); fprintf(stream, "#define PR_BITS_PER_FLOAT %d\n", bpb * sizeof(float)); fprintf(stream, "#define PR_BITS_PER_DOUBLE %d\n\n", bpb * sizeof(double)); fprintf(stream, "#define PR_BITS_PER_BYTE_LOG2 %d\n", Log2(bpb)); fprintf(stream, "#define PR_BITS_PER_SHORT_LOG2 %d\n", Log2(bpb * sizeof(short))); fprintf(stream, "#define PR_BITS_PER_INT_LOG2 %d\n", Log2(bpb * sizeof(int))); fprintf(stream, "#define PR_BITS_PER_INT64_LOG2 %d\n", 6); fprintf(stream, "#define PR_BITS_PER_LONG_LOG2 %d\n", Log2(bpb * sizeof(long))); fprintf(stream, "#define PR_BITS_PER_FLOAT_LOG2 %d\n", Log2(bpb * sizeof(float))); fprintf(stream, "#define PR_BITS_PER_DOUBLE_LOG2 %d\n\n", Log2(bpb * sizeof(double))); fprintf(stream, "#define PR_ALIGN_OF_SHORT %d\n", ALIGN_OF(short)); fprintf(stream, "#define PR_ALIGN_OF_INT %d\n", ALIGN_OF(int)); fprintf(stream, "#define PR_ALIGN_OF_LONG %d\n", ALIGN_OF(long)); if (sizeof(INT64) < 8) { /* this machine doesn't actually support PRInt64's */ fprintf(stream, "#define PR_ALIGN_OF_INT64 %d\n", ALIGN_OF(fakelonglong)); } else { fprintf(stream, "#define PR_ALIGN_OF_INT64 %d\n", ALIGN_OF(PRInt64)); } fprintf(stream, "#define PR_ALIGN_OF_FLOAT %d\n", ALIGN_OF(float)); fprintf(stream, "#define PR_ALIGN_OF_DOUBLE %d\n", ALIGN_OF(double)); fprintf(stream, "#define PR_ALIGN_OF_POINTER %d\n\n", ALIGN_OF(pointer)); fprintf(stream, "#endif /* nspr_cpucfg___ */\n"); fclose(stream); return 0; } nspr-4.11/nspr/pr/include/md/.cvsignore0000644000000000000000000000001112623070344016166 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/include/md/Makefile.in0000644000000000000000000000245312623070344016247 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk # The .cfg files need to be exported and installed to support # cross-compilation. CONFIGS = $(wildcard $(srcdir)/*.cfg) include $(topsrcdir)/config/rules.mk export:: $(MDCPUCFG_H) $(INSTALL) -m 444 $(CONFIGS) $(dist_includedir)/md $(INSTALL) -m 444 $(srcdir)/$(MDCPUCFG_H) $(dist_includedir) mv -f $(dist_includedir)/$(MDCPUCFG_H) $(dist_includedir)/prcpucfg.h install:: $(NSINSTALL) -D $(DESTDIR)$(includedir)/md $(NSINSTALL) -t -m 644 $(CONFIGS) $(DESTDIR)$(includedir)/md $(NSINSTALL) -t -m 644 $(srcdir)/$(MDCPUCFG_H) $(DESTDIR)$(includedir) mv -f $(DESTDIR)$(includedir)/$(MDCPUCFG_H) $(DESTDIR)$(includedir)/prcpucfg.h release:: export @echo "Copying machine-dependent prcpucfg.h" @if test -z "$(BUILD_NUMBER)"; then \ echo "BUILD_NUMBER must be defined"; \ false; \ fi @if test ! -d $(RELEASE_INCLUDE_DIR); then \ rm -rf $(RELEASE_INCLUDE_DIR); \ $(NSINSTALL) -D $(RELEASE_INCLUDE_DIR);\ fi cp $(srcdir)/$(MDCPUCFG_H) $(RELEASE_INCLUDE_DIR)/prcpucfg.h nspr-4.11/nspr/pr/include/md/_aix.h0000644000000000000000000001360312623070344015272 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_aix_defs_h___ #define nspr_aix_defs_h___ #include #if defined(_PR_PTHREADS) || defined(PTHREADS_USER) #include #endif /* * To pick up fd_set and the poll events. */ #include #include /* * Internal configuration macros */ #define PR_LINKER_ARCH "aix" #define _PR_SI_SYSNAME "AIX" #define _PR_SI_ARCHITECTURE "rs6000" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE (2*65536L) #define _MD_MINIMUM_STACK_SIZE (2*65536L) #define _MD_MMAP_FLAGS MAP_PRIVATE #define NEED_TIME_R #undef HAVE_STACK_GROWING_UP #undef HAVE_WEAK_IO_SYMBOLS #undef HAVE_WEAK_MALLOC_SYMBOLS #define HAVE_DLL #define USE_DLFCN #define _PR_HAVE_SOCKADDR_LEN #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #ifdef _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #ifdef _AIX51 /* AIX 4.3.3 does not have AI_NUMERICHOST. */ #define _PR_HAVE_GETADDRINFO #endif #endif #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #define _PR_ACCEPT_INHERIT_NONBLOCK /* Timer operations */ #if defined(AIX_TIMERS) #define _MD_INTERVAL_INIT() extern PRIntervalTime _MD_AixGetInterval(void); #define _MD_GET_INTERVAL _MD_AixGetInterval extern PRIntervalTime _MD_AixIntervalPerSec(void); #define _MD_INTERVAL_PER_SEC _MD_AixIntervalPerSec #else /* defined(AIX_TIMERS) */ #define _MD_INTERVAL_USE_GTOD #endif /* defined(AIX_TIMERS) */ #ifdef AIX_HAVE_ATOMIC_OP_H /* The atomic operations */ #include #define _PR_HAVE_ATOMIC_OPS #ifndef IS_64 #define _PR_HAVE_ATOMIC_CAS #endif #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(val) ((PRInt32)fetch_and_add((atomic_p)val, 1) + 1) #define _MD_ATOMIC_ADD(ptr, val) ((PRInt32)fetch_and_add((atomic_p)ptr, val) + val) #define _MD_ATOMIC_DECREMENT(val) ((PRInt32)fetch_and_add((atomic_p)val, -1) - 1) #define _MD_ATOMIC_SET(val, newval) _AIX_AtomicSet(val, newval) #endif /* AIX_HAVE_ATOMIC_OP_H */ #define USE_SETJMP #include #define _MD_GET_SP(_t) (_t)->md.jb[3] #define _MD_SET_THR_SP(_t, _sp) ((_t)->md.jb[3] = (int) (_sp - 2 * 64)) #define PR_NUM_GCREGS _JBLEN #define CONTEXT(_th) ((_th)->md.jb) #define SAVE_CONTEXT(_th) _setjmp(CONTEXT(_th)) #define GOTO_CONTEXT(_th) _longjmp(CONTEXT(_th), 1) #ifdef PTHREADS_USER #include "_nspr_pthread.h" #else /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ *status = PR_TRUE; \ if (setjmp(CONTEXT(_thread))) { \ (*_main)(); \ } \ _MD_GET_SP(_thread) = (int) (_sp - 2 * 64); \ PR_END_MACRO #define _MD_SWITCH_CONTEXT(_thread) \ if (!setjmp(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ longjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { jmp_buf jb; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #if !defined(_PR_PTHREADS) #define _MD_INIT_LOCKS() #endif #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) #endif /* PTHREADS_USER */ #ifdef AIX_RENAME_SELECT #define _MD_SELECT select #define _MD_POLL poll #endif extern void _MD_aix_map_sendfile_error(int err); #endif /* nspr_aix_defs_h___ */ nspr-4.11/nspr/pr/include/md/_aix32.cfg0000644000000000000000000000657612623070344015762 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef AIX #define AIX #endif #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_AF_INET6 24 /* same as AF_INET6 */ #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 /* used by protypes.h only */ #define _PR_AIX_HAVE_BSD_INT_TYPES #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_aix64.cfg0000644000000000000000000000661412623070344015760 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef AIX #define AIX #endif #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 8 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_AF_INET6 24 /* same as AF_INET6 */ #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 /* used by protypes.h only */ #define _PR_AIX_HAVE_BSD_INT_TYPES #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_beos.cfg0000644000000000000000000000676412623070344015763 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_BEOS #define XP_BEOS #undef XP_UNIX #endif #ifndef BEOS #define BEOS #endif #define PR_AF_INET6 5 /* same as AF_INET6 */ #ifdef __powerpc__ #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #else #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #endif #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif /* * XXX These two macros need to be investigated for different architectures. */ #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_beos.h0000644000000000000000000004707012623070344015446 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_beos_defs_h___ #define nspr_beos_defs_h___ #include "prtypes.h" #include "prio.h" #include "prthread.h" #include "prproces.h" #include "prmem.h" #include "obsolete/prsem.h" #include #include #include #include /* * Internal configuration macros */ #ifdef BONE_VERSION #define _PR_HAVE_SOCKADDR_LEN #define HAVE_NETINET_TCP_H #endif #define PR_LINKER_ARCH "beos" #define _PR_SI_SYSNAME "BEOS" #ifdef __powerpc__ #define _PR_SI_ARCHITECTURE "ppc" #else #define _PR_SI_ARCHITECTURE "x86" #endif #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define _PR_NO_CLOCK_TIMER /* * The Atomic operations */ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC _MD_AtomicInit #define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement #define _MD_ATOMIC_ADD _MD_AtomicAdd #define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement #define _MD_ATOMIC_SET _MD_AtomicSet #define HAVE_CVAR_BUILT_ON_SEM #define _PR_GLOBAL_THREADS_ONLY #define _PR_BTHREADS #define _PR_NEED_FAKE_POLL #define _PR_HAVE_PEEK_BUFFER #define _PR_PEEK_BUFFER_MAX (16 * 1024) #define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) 1 #define _PR_CONNECT_DOES_NOT_BIND #define _PR_HAVE_O_APPEND /* Define threading functions and objects as native BeOS */ struct _MDThread { thread_id tid; /* BeOS thread handle */ sem_id joinSem; /* sems used to synchronzie joining */ PRBool is_joining; /* TRUE if someone is currently waiting to join this thread */ }; struct _MDThreadStack { PRInt8 notused; }; /* * Lock and Semaphore related definitions */ struct _MDLock { sem_id semaphoreID; int32 benaphoreCount; }; struct _MDCVar { sem_id sem1; sem_id sem2; int16 count; }; struct _MDSemaphore { sem_id sid; }; /* ** CPU-related definitions */ struct _MDCPU { int8 unused; }; /* ** Process-related definitions */ struct _MDProcess { pid_t pid; }; struct _MDSegment { PRInt8 notused; }; /* ** File- and directory-related definitions */ #ifndef BONE_VERSION #define BE_SOCK_SHUTDOWN_READ 0x01 #define BE_SOCK_SHUTDOWN_WRITE 0x02 #endif struct _MDFileDesc { PRInt32 osfd; PRInt32 sock_state; PRBool accepted_socket; PRNetAddr peer_addr; #ifndef BONE_VERSION PRBool connectValueValid; int connectReturnValue; int connectReturnError; #endif }; struct _MDDir { DIR *d; }; #define PR_DIRECTORY_SEPARATOR '/' #define PR_DIRECTORY_SEPARATOR_STR "/" #define PR_PATH_SEPARATOR ':' #define PR_PATH_SEPARATOR_STR ":" #define GETTIMEOFDAY(tp) gettimeofday((tp), NULL) /* --- Memory-mapped files stuff --- not implemented on BeOS */ struct _MDFileMap { PRInt8 unused; }; /* * Network related definitions. */ #ifndef BONE_VERSION #define IPPROTO_IP 0 #define AF_UNIX 2 #define TCP_NODELAY SO_NONBLOCK #define SO_LINGER -1 #define SO_ERROR 4 #endif #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 #ifndef BONE_VERSION /* these aren't actually used. if they are, we're screwed */ struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol # */ }; struct protoent* getprotobyname(const char* name); struct protoent* getprotobynumber(int number); #endif /* * malloc() related definitions. */ #undef _PR_OVERRIDE_MALLOC /* Miscellaneous */ #define _MD_ERRNO() (errno) #define _MD_CLEANUP_BEFORE_EXIT _MD_cleanup_before_exit #define _MD_EXIT _MD_exit #define _MD_GET_ENV getenv #define _MD_PUT_ENV putenv #define _MD_EARLY_INIT _MD_early_init #define _MD_FINAL_INIT _MD_final_init #define _MD_EARLY_CLEANUP() /* CPU Stuff */ #define _MD_INIT_CPUS _MD_init_cpus #define _MD_WAKEUP_CPUS _MD_wakeup_cpus #define _MD_START_INTERRUPTS _MD_start_interrupts #define _MD_STOP_INTERRUPTS _MD_stop_interrupts #define _MD_DISABLE_CLOCK_INTERRUPTS _MD_disable_clock_interrupts #define _MD_BLOCK_CLOCK_INTERRUPTS _MD_block_clock_interrupts #define _MD_UNBLOCK_CLOCK_INTERRUPTS _MD_unblock_clock_interrupts #define _MD_CLOCK_INTERRUPT _MD_clock_interrupt #define _MD_INIT_STACK _MD_init_stack #define _MD_CLEAR_STACK _MD_clear_stack // #define _MD_GET_INTSOFF _MD_get_intsoff // #define _MD_SET_INTSOFF _MD_set_intsoff #define _MD_CURRENT_CPU _MD_current_cpu #define _MD_SET_CURRENT_CPU _MD_set_current_cpu #define _MD_INIT_RUNNING_CPU _MD_init_running_cpu #define _MD_PAUSE_CPU _MD_pause_cpu /* Thread stuff */ #define _MD_CURRENT_THREAD() PR_GetCurrentThread() // #define _MD_GET_ATTACHED_THREAD _MD_get_attached_thread #define _MD_LAST_THREAD _MD_last_thread #define _MD_SET_CURRENT_THREAD _MD_set_current_THREAD #define _MD_SET_LAST_THREAD _MD_set_last_thread #define _MD_INIT_THREAD _MD_init_thread #define _MD_EXIT_THREAD _MD_exit_thread #define _MD_INIT_ATTACHED_THREAD _MD_init_attached_thread #define _MD_SUSPEND_THREAD _MD_suspend_thread #define _MD_RESUME_THREAD _MD_resume_thread #define _MD_SUSPEND_CPU _MD_suspend_cpu #define _MD_RESUME_CPU _MD_resume_cpu #define _MD_BEGIN_SUSPEND_ALL _MD_begin_suspend_all #define _MD_END_SUSPEND_ALL _MD_end_suspend_all #define _MD_BEGIN_RESUME_ALL _MD_begin_resume_all #define _MD_END_RESUME_ALL _MD_end_resume_all #define _MD_GET_SP _MD_get_sp #define _MD_CLEAN_THREAD _MD_clean_thread #define _MD_CREATE_PRIMORDIAL_USER_THREAD _MD_create_primordial_user_thread #define _MD_CREATE_USER_THREAD _MD_create_user_thread #define _MD_INIT_PRIMORDIAL_THREAD _MD_init_primordial_thread #define _MD_CREATE_THREAD _MD_create_thread #define _MD_YIELD _MD_yield #define _MD_SET_PRIORITY _MD_set_priority #define _MD_SUSPENDALL _MD_suspendall #define _MD_RESUMEALL _MD_resumeall #define _MD_SWITCH_CONTEXT _MD_switch_context #define _MD_RESTORE_CONTEXT _MD_restore_context #define _MD_WAIT _MD_wait #define _MD_WAKEUP_WAITER _MD_wakeup_waiter #define _MD_SETTHREADAFFINITYMASK _MD_setthreadaffinitymask #define _MD_GETTHREADAFFINITYMASK _MD_getthreadaffinitymask /* Thread Synchronization */ #define _MD_INIT_LOCKS _MD_init_locks #define _MD_NEW_LOCK _MD_new_lock #define _MD_FREE_LOCK _MD_free_lock #define _MD_LOCK _MD_lock #define _MD_TEST_AND_LOCK _MD_test_and_lock #define _MD_UNLOCK _MD_unlock #define _MD_IOQ_LOCK _MD_ioq_lock #define _MD_IOQ_UNLOCK _MD_ioq_unlock #define _MD_NEW_SEM _MD_new_sem #define _MD_DESTROY_SEM _MD_destroy_sem #define _MD_TIMED_WAIT_SEM _MD_timed_wait_sem #define _MD_WAIT_SEM _MD_wait_sem #define _MD_POST_SEM _MD_post_sem // #define _MD_NEW_CV _MD_new_cv // #define _MD_FREE_CV _MD_free_cv // #define _MD_WAIT_CV _MD_wait_cv // #define _MD_NOTIFY_CV _MD_notify_cv // #define _MD_NOTIFYALL_CV _MD_notifyall_cv /* File I/O */ /* don't need any I/O initializations */ #define _MD_INIT_IO() #define _MD_INIT_FILEDESC(fd) #define _MD_OPEN_DIR _MD_open_dir #define _MD_READ_DIR _MD_read_dir #define _MD_CLOSE_DIR _MD_close_dir #define _MD_MAKE_NONBLOCK _MD_make_nonblock #define _MD_SET_FD_INHERITABLE _MD_set_fd_inheritable #define _MD_INIT_FD_INHERITABLE _MD_init_fd_inheritable #define _MD_QUERY_FD_INHERITABLE _MD_query_fd_inheritable #define _MD_OPEN _MD_open #define _MD_OPEN_FILE _MD_open #define _MD_CLOSE_FILE _MD_close_file #define _MD_READ _MD_read #define _MD_WRITE _MD_write #define _MD_WRITEV _MD_writev #define _MD_LSEEK _MD_lseek #define _MD_LSEEK64 _MD_lseek64 #define _MD_FSYNC _MD_fsync #define _MD_DELETE _MD_delete #define _MD_GETFILEINFO _MD_getfileinfo #define _MD_GETFILEINFO64 _MD_getfileinfo64 #define _MD_GETOPENFILEINFO _MD_getopenfileinfo #define _MD_GETOPENFILEINFO64 _MD_getopenfileinfo64 #define _MD_RENAME _MD_rename #define _MD_ACCESS _MD_access #define _MD_STAT stat #define _MD_MKDIR _MD_mkdir #define _MD_MAKE_DIR _MD_mkdir #define _MD_RMDIR _MD_rmdir #define _MD_PR_POLL _MD_pr_poll /* Network I/O */ #define _MD_CLOSE_SOCKET _MD_close_socket #define _MD_CONNECT _MD_connect #define _MD_ACCEPT _MD_accept #define _MD_BIND _MD_bind #define _MD_LISTEN _MD_listen #define _MD_SHUTDOWN _MD_shutdown #define _MD_RECV _MD_recv #define _MD_SEND _MD_send #define _MD_ACCEPT_READ _MD_accept_read #define _MD_GETSOCKNAME _MD_getsockname #define _MD_GETPEERNAME _MD_getpeername #define _MD_GETSOCKOPT _MD_getsockopt #define _MD_SETSOCKOPT _MD_setsockopt #define _MD_RECVFROM _MD_recvfrom #define _MD_SENDTO _MD_sendto #define _MD_SOCKETPAIR _MD_socketpair #define _MD_SOCKET _MD_socket #define _MD_SOCKETAVAILABLE _MD_socketavailable #define _MD_PIPEAVAILABLE _MD_socketavailable #define _MD_GET_SOCKET_ERROR() (errno) #define _MD_GETHOSTNAME _MD_gethostname #define _MD_SELECT select /* Process management */ #define _MD_CREATE_PROCESS _MD_create_process #define _MD_DETACH_PROCESS _MD_detach_process #define _MD_WAIT_PROCESS _MD_wait_process #define _MD_KILL_PROCESS _MD_kill_process /* Atomic data operations */ // #define _MD_INIT_ATOMIC _MD_init_atomic // #define _MD_ATOMIC_INCREMENT _MD_atomic_increment // #define _MD_ATOMIC_DECREMENT _MD_atomic_decrement // #define _MD_ATOMIC_SET _MD_atomic_set /* memory management */ #define _MD_INIT_SEGS _MD_init_segs #define _MD_ALLOC_SEGMENT _MD_alloc_segment #define _MD_FREE_SEGMENT _MD_free_segment /* Memory mapped file I/O */ #define _MD_CREATE_FILE_MAP _MD_create_file_map #define _MD_GET_MEM_MAP_ALIGNMENT _MD_get_mem_map_alignment #define _MD_MEM_MAP _MD_mem_map #define _MD_MEM_UNMAP _MD_mem_unmap #define _MD_CLOSE_FILE_MAP _MD_close_file_map /* Time related */ #define _MD_NOW _MD_now #define _MD_INTERVAL_INIT _MD_interval_init #define _MD_GET_INTERVAL _MD_get_interval #define _MD_INTERVAL_PER_SEC _MD_interval_per_sec /* File locking */ #define _MD_LOCKFILE _MD_lockfile #define _MD_TLOCKFILE _MD_tlockfile #define _MD_UNLOCKFILE _MD_unlockfile /** * Prototypes for machine dependent function implementations. (Too bad * NSPR's MD system blows so much that we have to reiterate every stinking * thing we implement here in our MD header file.) */ /* Miscellaneous */ NSPR_API(void) _MD_cleanup_before_exit(void); NSPR_API(void) _MD_exit(PRIntn status); NSPR_API(char*) _MD_get_env(const char *name); NSPR_API(PRIntn) _MD_put_env(const char *name); NSPR_API(void) _MD_early_init(void); NSPR_API(void) _MD_final_init(void); /* CPU Stuff */ NSPR_API(void) _MD_init_cpus(); NSPR_API(void) _MD_wakeup_cpus(); NSPR_API(void) _MD_start_interrupts(void); NSPR_API(void) _MD_stop_interrupts(void); NSPR_API(void) _MD_disable_clock_interrupts(void); NSPR_API(void) _MD_block_clock_interrupts(void); NSPR_API(void) _MD_unblock_clock_interrupts(void); NSPR_API(void) _MD_clock_interrupt(void); // NSPR_API(void) _MD_init_stack(PRThreadStack *ts, PRIntn redzone); // NSPR_API(void) _MD_clear_stack(PRThreadStack* ts); // NSPR_API(PRInt32) _MD_get_intsoff(void); // NSPR_API(void) _MD_set_intsoff(PRInt32 _val); // NSPR_API(_PRCPU*) _MD_current_cpu(void); // NSPR_API(void) _MD_set_current_cpu(_PRCPU *cpu); // NSPR_API(void) _MD_init_running_cpu(_PRCPU *cpu); NSPR_API(PRInt32) _MD_pause_cpu(PRIntervalTime timeout); /* Thread stuff */ // NSPR_API(PRThread*) _MD_current_thread(void); NSPR_API(PRThread*) _MD_get_attached_thread(void); NSPR_API(PRThread*) _MD_last_thread(void); NSPR_API(void) _MD_set_current_thread(PRThread *thread); NSPR_API(void) _MD_set_last_thread(PRThread *thread); NSPR_API(PRStatus) _MD_init_thread(PRThread *thread); NSPR_API(void) _MD_exit_thread(PRThread *thread); NSPR_API(PRStatus) _MD_init_attached_thread(PRThread *thread); NSPR_API(void) _MD_suspend_thread(PRThread *thread); NSPR_API(void) _MD_resume_thread(PRThread *thread); // NSPR_API(void) _MD_suspend_cpu(_PRCPU *cpu); // NSPR_API(void) _MD_resume_cpu(_PRCPU *cpu); NSPR_API(void) _MD_begin_suspend_all(void); NSPR_API(void) _MD_end_suspend_all(void); NSPR_API(void) _MD_begin_resume_all(void); NSPR_API(void) _MD_end_resume_all(void); NSPR_API(void *) _MD_get_sp(PRThread *thread); NSPR_API(void) _MD_clean_thread(PRThread *thread); NSPR_API(void) _MD_create_primordial_user_thread(PRThread *); NSPR_API(PRThread*) _MD_create_user_thread(PRUint32 stacksize, void (*start)(void *), void *arg); NSPR_API(void) _MD_init_primordial_thread(PRThread *thread); NSPR_API(PRStatus) _MD_create_thread(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); NSPR_API(void) _MD_yield(void); NSPR_API(void) _MD_set_priority(struct _MDThread *md, PRThreadPriority newPri); NSPR_API(void) _MD_suspendall(void); NSPR_API(void) _MD_resumeall(void); NSPR_API(void) _MD_init_context(PRThread *thread, char *top, void (*start) (void), PRBool *status); NSPR_API(void) _MD_switch_context(PRThread *thread); NSPR_API(void) _MD_restore_context(PRThread *thread); NSPR_API(PRStatus) _MD_wait(PRThread *, PRIntervalTime timeout); NSPR_API(PRStatus) _MD_wakeup_waiter(PRThread *); NSPR_API(PRInt32) _MD_setthreadaffinitymask(PRThread *thread, PRUint32 mask ); NSPR_API(PRInt32) _MD_getthreadaffinitymask(PRThread *thread, PRUint32 *mask); /* Thread Synchronization */ NSPR_API(void) _MD_init_locks(void); NSPR_API(PRStatus) _MD_new_lock(struct _MDLock *md); NSPR_API(void) _MD_free_lock(struct _MDLock *md); NSPR_API(void) _MD_lock(struct _MDLock *md); NSPR_API(PRIntn) _MD_test_and_lock(struct _MDLock *md); NSPR_API(void) _MD_unlock(struct _MDLock *md); NSPR_API(void) _MD_ioq_lock(void); NSPR_API(void) _MD_ioq_unlock(void); NSPR_API(void) _MD_new_sem(struct _MDSemaphore *md, PRUintn value); NSPR_API(void) _MD_destroy_sem(struct _MDSemaphore *md); NSPR_API(PRStatus) _MD_timed_wait_sem(struct _MDSemaphore *md, PRIntervalTime timeout); NSPR_API(PRStatus) _MD_wait_sem(struct _MDSemaphore *md); NSPR_API(void) _MD_post_sem(struct _MDSemaphore *md); // NSPR_API(PRInt32) _MD_new_cv(struct _MDCVar *md); // NSPR_API(void) _MD_free_cv(struct _MDCVar *md); // NSPR_API(void) _MD_wait_cv(struct _MDCVar *mdCVar, struct _MDLock *mdLock, PRIntervalTime timeout); // NSPR_API(void) _MD_notify_cv(struct _MDCVar *md, struct _MDLock *lock); // NSPR_API(void) _MD_notifyall_cv(struct _MDCVar *md, struct _MDLock *lock); /* File I/O */ // NSPR_API(void) _MD_init_io(void); NSPR_API(PRStatus) _MD_open_dir(struct _MDDir *md,const char *name); NSPR_API(char *) _MD_read_dir(struct _MDDir *md, PRIntn flags); NSPR_API(PRInt32) _MD_close_dir(struct _MDDir *md); NSPR_API(void) _MD_make_nonblock(PRFileDesc *fd); NSPR_API(void) _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported); NSPR_API(void) _MD_query_fd_inheritable(PRFileDesc *fd); NSPR_API(PRInt32) _MD_open(const char *name, PRIntn osflags, PRIntn mode); NSPR_API(PRInt32) _MD_close_file(PRInt32 osfd); NSPR_API(PRInt32) _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount); NSPR_API(PRInt32) _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount); NSPR_API(PRInt32) _MD_writev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_lseek(PRFileDesc *fd, PRInt32 offset, int whence); NSPR_API(PRInt64) _MD_lseek64(PRFileDesc *fd, PRInt64 offset, int whence); NSPR_API(PRInt32) _MD_fsync(PRFileDesc *fd); NSPR_API(PRInt32) _MD_delete(const char *name); NSPR_API(PRInt32) _MD_getfileinfo(const char *fn, PRFileInfo *info); NSPR_API(PRInt32) _MD_getfileinfo64(const char *fn, PRFileInfo64 *info); NSPR_API(PRInt32) _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info); NSPR_API(PRInt32) _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info); NSPR_API(PRInt32) _MD_rename(const char *from, const char *to); NSPR_API(PRInt32) _MD_access(const char *name, PRIntn how); NSPR_API(PRInt32) _MD_stat(const char *name, struct stat *buf); NSPR_API(PRInt32) _MD_mkdir(const char *name, PRIntn mode); NSPR_API(PRInt32) _MD_rmdir(const char *name); NSPR_API(PRInt32) _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout); /* Network I/O */ NSPR_API(PRInt32) _MD_close_socket(PRInt32 osfd); NSPR_API(PRInt32) _MD_connect(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen); NSPR_API(PRInt32) _MD_listen(PRFileDesc *fd, PRIntn backlog); NSPR_API(PRInt32) _MD_shutdown(PRFileDesc *fd, PRIntn how); NSPR_API(PRInt32) _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_accept_read(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout); // NSPR_API(PRInt32) _MD_fast_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg); // NSPR_API(PRInt32) _MD_fast_accept_read(PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg); // NSPR_API(void) _MD_update_accept_context(PRInt32 s, PRInt32 ls); NSPR_API(PRStatus) _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); NSPR_API(PRStatus) _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); NSPR_API(PRStatus) _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen); NSPR_API(PRStatus) _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen); NSPR_API(PRInt32) _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); NSPR_API(PRInt32) _MD_socketpair(int af, int type, int flags, PRInt32 *osfd); NSPR_API(PRInt32) _MD_socket(int af, int type, int flags); NSPR_API(PRInt32) _MD_socketavailable(PRFileDesc *fd); // NSPR_API(PRInt32) _MD_get_socket_error(void); NSPR_API(PRStatus) _MD_gethostname(char *name, PRUint32 namelen); /* Process management */ NSPR_API(PRProcess *) _MD_create_process(const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr); NSPR_API(PRStatus) _MD_detach_process(PRProcess *process); NSPR_API(PRStatus) _MD_wait_process(PRProcess *process, PRInt32 *exitCode); NSPR_API(PRStatus) _MD_kill_process(PRProcess *process); /* Atomic data operations */ // NSPR_API(void) _MD_init_atomic(void); // NSPR_API(PRInt32) _MD_atomic_increment(PRInt32 *); // NSPR_API(PRInt32) _MD_atomic_decrement(PRInt32 *); // NSPR_API(PRInt32) _MD_atomic_set(PRInt32 *, PRInt32); /* Memory management */ NSPR_API(void) _MD_init_segs(void); NSPR_API(PRStatus) _MD_alloc_segment(PRSegment *seg, PRUint32 size, void *vaddr); NSPR_API(void) _MD_free_segment(PRSegment *seg); /* Memory mapped file I/O */ NSPR_API(PRStatus) _MD_create_file_map(PRFileMap *fmap, PRInt64 size); NSPR_API(PRInt32) _MD_get_mem_map_alignment(void); NSPR_API(void *) _MD_mem_map(PRFileMap *fmap, PRInt64 offset, PRUint32 len); NSPR_API(PRStatus) _MD_mem_unmap(void *addr, PRUint32 size); NSPR_API(PRStatus) _MD_close_file_map(PRFileMap *fmap); /* Time related */ NSPR_API(PRTime) _MD_now(void); NSPR_API(void) _MD_interval_init(void); NSPR_API(PRIntervalTime) _MD_get_interval(void); NSPR_API(PRIntervalTime) _MD_interval_per_sec(void); /* File locking */ NSPR_API(PRStatus) _MD_lockfile(PRInt32 osfd); NSPR_API(PRStatus) _MD_tlockfile(PRInt32 osfd); NSPR_API(PRStatus) _MD_unlockfile(PRInt32 osfd); #endif /* _nspr_beos_defs_h___*/ nspr-4.11/nspr/pr/include/md/_bsdi.cfg0000644000000000000000000001126312623070344015742 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef BSDI #define BSDI #endif #define PR_AF_INET6 24 /* same as AF_INET6 */ #if defined(__i386__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__sparc__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #error "Unknown CPU architecture" #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_bsdi.h0000644000000000000000000001076512623070344015440 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_bsdi_defs_h___ #define nspr_bsdi_defs_h___ /* * Internal configuration macros */ #include /* for _BSDI_VERSION */ #define PR_LINKER_ARCH "bsdi" #define _PR_SI_SYSNAME "BSDI" #if defined(__i386__) #define _PR_SI_ARCHITECTURE "x86" #elif defined(__sparc__) #define _PR_SI_ARCHITECTURE "sparc" #else #error "Unknown CPU architecture" #endif #define PR_DLL_SUFFIX ".so" #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #define HAVE_BSD_FLOCK #define NEED_TIME_R #define _PR_HAVE_SOCKADDR_LEN #define _PR_NO_LARGE_FILES #define USE_SETJMP /* BSD/OS 4.3 and newer all have IPv6 support */ #if _BSDI_VERSION >= 200105 #define _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #endif #ifndef _PR_PTHREADS #include #if defined(_PR_BSDI_JMPBUF_IS_ARRAY) #define _MD_GET_SP(_t) (_t)->md.context[2] #elif defined(_PR_BSDI_JMPBUF_IS_STRUCT) #define _MD_GET_SP(_t) (_t)->md.context[0].jb_esp #else #error "Unknown BSDI jmp_buf type" #endif #define PR_NUM_GCREGS _JBLEN #define PR_CONTEXT_TYPE jmp_buf #define CONTEXT(_th) ((_th)->md.context) #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (setjmp(CONTEXT(_thread))) { \ _main(); \ } \ _MD_GET_SP(_thread) = (int) (_sp - 64); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!setjmp(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ longjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) #endif /* ! _PR_PTHREADS */ #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #include #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv) #define _MD_INTERVAL_USE_GTOD #endif /* nspr_bsdi_defs_h___ */ nspr-4.11/nspr/pr/include/md/_darwin.cfg0000644000000000000000000001117012623070344016302 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #define PR_AF_INET6 30 /* same as AF_INET6 */ #ifdef __LITTLE_ENDIAN__ #undef IS_BIG_ENDIAN #define IS_LITTLE_ENDIAN 1 #else #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #endif #ifdef __LP64__ #define IS_64 #endif #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS 1 #ifdef IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_ALIGN_OF_DWORD 8 #else /* IS_64 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #endif /* IS_64 */ #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_darwin.h0000644000000000000000000002230712623070344015776 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_darwin_defs_h___ #define nspr_darwin_defs_h___ #include "prthread.h" #include #include #ifdef __APPLE__ #include #include #endif #define PR_LINKER_ARCH "darwin" #define _PR_SI_SYSNAME "DARWIN" #ifdef __i386__ #define _PR_SI_ARCHITECTURE "x86" #elif defined(__x86_64__) #define _PR_SI_ARCHITECTURE "x86-64" #elif defined(__ppc__) #define _PR_SI_ARCHITECTURE "ppc" #elif defined(__arm__) #define _PR_SI_ARCHITECTURE "arm" #elif defined(__aarch64__) #define _PR_SI_ARCHITECTURE "aarch64" #else #error "Unknown CPU architecture" #endif #define PR_DLL_SUFFIX ".dylib" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #if defined(__x86_64__) || TARGET_OS_IPHONE #define USE_DLFCN #else #define USE_MACH_DYLD #endif #define _PR_HAVE_SOCKADDR_LEN #define _PR_STAT_HAS_ST_ATIMESPEC #define _PR_HAVE_LARGE_OFF_T #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #define _PR_INET6 /* * I'd prefer to use getipnodebyname and getipnodebyaddr but the * getipnodebyname(3) man page on Mac OS X 10.2 says they are not * thread-safe. AI_V4MAPPED|AI_ADDRCONFIG doesn't work either. */ #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_HAVE_GETADDRINFO /* * On Mac OS X 10.2, gethostbyaddr fails with h_errno=NO_RECOVERY * if you pass an IPv4-mapped IPv6 address to it. */ #define _PR_GHBA_DISALLOW_V4MAPPED #ifdef __APPLE__ #if !defined(MAC_OS_X_VERSION_10_3) || \ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 /* * socket(AF_INET6) fails with EPROTONOSUPPORT on Mac OS X 10.1. * IPv6 under OS X 10.2 and below is not complete (see bug 222031). */ #define _PR_INET6_PROBE #endif /* DT < 10.3 */ #if defined(MAC_OS_X_VERSION_10_2) && \ MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2 /* Mac OS X 10.2 has inet_ntop and inet_pton. */ #define _PR_HAVE_INET_NTOP #endif /* DT >= 10.2 */ #endif /* __APPLE__ */ #define _PR_IPV6_V6ONLY_PROBE /* The IPV6_V6ONLY socket option is not defined on Mac OS X 10.1. */ #ifndef IPV6_V6ONLY #define IPV6_V6ONLY 27 #endif #ifdef __ppc__ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_DarwinPPC_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT(val) _PR_DarwinPPC_AtomicIncrement(val) extern PRInt32 _PR_DarwinPPC_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT(val) _PR_DarwinPPC_AtomicDecrement(val) extern PRInt32 _PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET(val, newval) _PR_DarwinPPC_AtomicSet(val, newval) extern PRInt32 _PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD(ptr, val) _PR_DarwinPPC_AtomicAdd(ptr, val) #endif /* __ppc__ */ #ifdef __i386__ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_Darwin_x86_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT(val) _PR_Darwin_x86_AtomicIncrement(val) extern PRInt32 _PR_Darwin_x86_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT(val) _PR_Darwin_x86_AtomicDecrement(val) extern PRInt32 _PR_Darwin_x86_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET(val, newval) _PR_Darwin_x86_AtomicSet(val, newval) extern PRInt32 _PR_Darwin_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD(ptr, val) _PR_Darwin_x86_AtomicAdd(ptr, val) #endif /* __i386__ */ #ifdef __x86_64__ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_Darwin_x86_64_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT(val) _PR_Darwin_x86_64_AtomicIncrement(val) extern PRInt32 _PR_Darwin_x86_64_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT(val) _PR_Darwin_x86_64_AtomicDecrement(val) extern PRInt32 _PR_Darwin_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET(val, newval) _PR_Darwin_x86_64_AtomicSet(val, newval) extern PRInt32 _PR_Darwin_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD(ptr, val) _PR_Darwin_x86_64_AtomicAdd(ptr, val) #endif /* __x86_64__ */ #if defined(__arm__) || defined(__aarch64__) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(val) OSAtomicIncrement32(val) #define _MD_ATOMIC_DECREMENT(val) OSAtomicDecrement32(val) static inline PRInt32 _MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) { PRInt32 oldval; do { oldval = *val; } while (!OSAtomicCompareAndSwap32(oldval, newval, val)); return oldval; } #define _MD_ATOMIC_ADD(ptr, val) OSAtomicAdd32(val, ptr) #endif /* __arm__ || __aarch64__ */ #define USE_SETJMP #if !defined(_PR_PTHREADS) #include #define PR_CONTEXT_TYPE jmp_buf #define CONTEXT(_th) ((_th)->md.context) #define _MD_GET_SP(_th) (((struct sigcontext *) (_th)->md.context)->sc_onstack) #define PR_NUM_GCREGS _JBLEN /* ** Initialize a thread context to run "_main()" when started */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (setjmp(CONTEXT(_thread))) { \ _main(); \ } \ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!setjmp(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ longjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() extern PRStatus _MD_InitializeThread(PRThread *thread); #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread #define _MD_RESUME_THREAD(thread) _MD_resume_thread #define _MD_CLEAN_THREAD(_thread) extern PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri); extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout); extern PRStatus _MD_WAKEUP_WAITER(PRThread *); extern void _MD_YIELD(void); #endif /* ! _PR_PTHREADS */ #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INTERVAL_INIT _PR_Mach_IntervalInit #define _MD_GET_INTERVAL _PR_Mach_GetInterval #define _MD_INTERVAL_PER_SEC _PR_Mach_TicksPerSecond extern void _MD_EarlyInit(void); extern void _PR_Mach_IntervalInit(void); extern PRIntervalTime _PR_Mach_GetInterval(void); extern PRIntervalTime _PR_Mach_TicksPerSecond(void); /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv) /* For writev() */ #include #endif /* nspr_darwin_defs_h___ */ nspr-4.11/nspr/pr/include/md/_dgux.cfg0000644000000000000000000000641612623070344015774 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef DGUX #define DGUX #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_dgux.h0000644000000000000000000001165112623070344015461 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_dgux_defs_h___ #define nspr_dgux_defs_h___ /* * Internal configuration macros */ #define PR_LINKER_ARCH "dgux" #define _PR_SI_SYSNAME "DGUX" #define _PR_SI_ARCHITECTURE "x86" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #ifndef HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_IO_SYMBOLS #endif #undef HAVE_STACK_GROWING_UP #define HAVE_NETCONFIG #define HAVE_DLL #define USE_DLFCN #define NEED_STRFTIME_LOCK #define NEED_TIME_R #define _PR_NEED_STRCASECMP #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_NO_LARGE_FILES #define _PR_STAT_HAS_ONLY_ST_ATIME #define USE_SETJMP #include #define _SETJMP setjmp #define _LONGJMP longjmp #define _PR_CONTEXT_TYPE jmp_buf #define _MD_GET_SP(_t) (_t)->md.context[4] #define _PR_NUM_GCREGS _JBLEN #define CONTEXT(_th) ((_th)->md.context) /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!_SETJMP(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _LONGJMP(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures. * Don't use SVR4 native threads (yet). */ struct _MDThread { _PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() /* * The following are copied from _sunos.h, _aix.h. This means * some of them should probably be moved into _unixos.h. But * _irix.h seems to be quite different in regard to these macros. */ #define _MD_INTERVAL_USE_GTOD #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #include #include #include extern int _select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *execptfds, struct timeval *timeout); #define _MD_SELECT _select #define _MD_POLL _poll #include #include extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout); #endif /* nspr_dgux_defs_h___ */ nspr-4.11/nspr/pr/include/md/_freebsd.cfg0000644000000000000000000003455112623070344016440 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef FREEBSD #define FREEBSD #endif #define PR_AF_INET6 28 /* same as AF_INET6 */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #if defined(__i386__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #elif defined(__alpha__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #elif defined(__sparc__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #elif defined(__ia64__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #elif defined(__amd64__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #elif defined(__powerpc64__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__powerpc__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__arm__) #if defined(__ARMEB__) || defined(__ARM_BIG_ENDIAN__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #else #undef IS_BIG_ENDIAN #define IS_LITTLE_ENDIAN 1 #endif #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__mips64__) #if defined(__MIPSEB__) || defined(_MIPSEB) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #else #undef IS_BIG_ENDIAN #define IS_LITTLE_ENDIAN 1 #endif #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__mips__) #if defined(__MIPSEB__) || defined(_MIPSEB) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #else #undef IS_BIG_ENDIAN #define IS_LITTLE_ENDIAN 1 #endif #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #error "Unknown CPU architecture" #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_freebsd.h0000644000000000000000000001503612623070344016125 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_freebsd_defs_h___ #define nspr_freebsd_defs_h___ #include "prthread.h" #if __FreeBSD__ >= 2 #include /* for __FreeBSD_version */ #endif #include #define PR_LINKER_ARCH "freebsd" #define _PR_SI_SYSNAME "FREEBSD" #if defined(__i386__) #define _PR_SI_ARCHITECTURE "x86" #elif defined(__alpha__) #define _PR_SI_ARCHITECTURE "alpha" #elif defined(__sparc__) #define _PR_SI_ARCHITECTURE "sparc" #elif defined(__ia64__) #define _PR_SI_ARCHITECTURE "ia64" #elif defined(__amd64__) #define _PR_SI_ARCHITECTURE "amd64" #elif defined(__powerpc64__) #define _PR_SI_ARCHITECTURE "powerpc64" #elif defined(__powerpc__) #define _PR_SI_ARCHITECTURE "powerpc" #elif defined(__arm__) #define _PR_SI_ARCHITECTURE "arm" #elif defined(__mips64__) #define _PR_SI_ARCHITECTURE "mips64" #elif defined(__mips__) #define _PR_SI_ARCHITECTURE "mips" #else #error "Unknown CPU architecture" #endif #if defined(__ELF__) #define PR_DLL_SUFFIX ".so" #else #define PR_DLL_SUFFIX ".so.1.0" #endif #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define USE_DLFCN #define _PR_HAVE_SOCKADDR_LEN #define _PR_STAT_HAS_ST_ATIMESPEC #define _PR_HAVE_LARGE_OFF_T #if defined(_PR_PTHREADS) #if __FreeBSD_version >= 400008 /* * libc_r before this version of FreeBSD doesn't have poll(). * Although libc has poll(), it is not thread-safe so we can't * use it in the pthreads version. */ #define _PR_POLL_AVAILABLE #endif #else #if __FreeBSD_version >= 300000 #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #endif #endif #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #if __FreeBSD_version >= 400014 #define _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #define _PR_IPV6_V6ONLY_PROBE #endif #define USE_SETJMP #ifndef _PR_PTHREADS #include #define PR_CONTEXT_TYPE sigjmp_buf #define CONTEXT(_th) ((_th)->md.context) #define _MD_GET_SP(_th) (_th)->md.context[0]._sjb[2] #define PR_NUM_GCREGS _JBLEN /* ** Initialize a thread context to run "_main()" when started */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (sigsetjmp(CONTEXT(_thread), 1)) { \ _main(); \ } \ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!sigsetjmp(CONTEXT(_thread), 1)) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ siglongjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() extern PRStatus _MD_InitializeThread(PRThread *thread); #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread #define _MD_RESUME_THREAD(thread) _MD_resume_thread #define _MD_CLEAN_THREAD(_thread) extern PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri); extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout); extern PRStatus _MD_WAKEUP_WAITER(PRThread *); extern void _MD_YIELD(void); #endif /* ! _PR_PTHREADS */ extern void _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INTERVAL_USE_GTOD /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv) #if defined(_PR_POLL_AVAILABLE) #include #define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout) #endif /* freebsd has INADDR_LOOPBACK defined, but in /usr/include/rpc/types.h, and I didn't want to be including that.. */ #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK (u_long)0x7F000001 #endif /* For writev() */ #include #endif /* nspr_freebsd_defs_h___ */ nspr-4.11/nspr/pr/include/md/_hpux.h0000644000000000000000000001774712623070344015512 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_xhppa_defs_h___ #define nspr_xhppa_defs_h___ /* * Internal configuration macros */ #define PR_LINKER_ARCH "hpux" #define _PR_SI_SYSNAME "HPUX" #ifdef __ia64 #define _PR_SI_ARCHITECTURE "ia64" #define PR_DLL_SUFFIX ".so" #else /* * _PR_SI_ARCHITECTURE must be "hppa1.1" for backward compatibility. * It was changed to "hppa" in NSPR 4.6.2, but was changed back in * NSPR 4.6.4. */ #define _PR_SI_ARCHITECTURE "hppa1.1" #define PR_DLL_SUFFIX ".sl" #endif #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 /* * _USE_BIG_FDS increases the size of fd_set from 256 bytes to * about 7500 bytes. PR_Poll allocates three fd_sets on the * stack, so it is safer to also increase the default thread * stack size. */ #define _MD_DEFAULT_STACK_SIZE (2*65536L) #define _MD_MINIMUM_STACK_SIZE (2*65536L) #define _MD_MMAP_FLAGS MAP_PRIVATE #define NEED_TIME_R #define HAVE_STACK_GROWING_UP #undef HAVE_WEAK_IO_SYMBOLS #undef HAVE_WEAK_MALLOC_SYMBOLS #define HAVE_DLL #ifdef IS_64 #define USE_DLFCN #else #define USE_HPSHL #endif #ifndef HAVE_STRERROR #define HAVE_STRERROR #endif #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #define _PR_ACCEPT_INHERIT_NONBLOCK #if defined(__ia64) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT _PR_ia64_AtomicIncrement extern PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT _PR_ia64_AtomicDecrement extern PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD _PR_ia64_AtomicAdd extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _PR_ia64_AtomicSet #endif #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_HAVE_GETADDRINFO #ifdef _PR_INET6 #define _PR_HAVE_INET_NTOP #else #define _PR_INET6_PROBE /* for HP-UX 11.11 without IPv6 */ #ifndef AF_INET6 #define AF_INET6 22 #define AI_CANONNAME 2 #define AI_NUMERICHOST 4 #define AI_NUMERICSERV 8 #define AI_V4MAPPED 0x00000010 #define AI_ADDRCONFIG 0x00000040 #define AI_ALL 0x00000020 #define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) #define NI_NUMERICHOST 2 struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* IPPROTO_xxx for IPv4 and IPv6 */ socklen_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for host */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; #endif /* for HP-UX 11.11 without IPv6 */ #define _PR_HAVE_MD_SOCKADDR_IN6 /* isomorphic to struct in6_addr on HP-UX B.11.23 */ struct _md_in6_addr { union { PRUint8 _S6_u8[16]; PRUint16 _S6_u16[8]; PRUint32 _S6_u32[4]; PRUint32 __S6_align; } _s6_un; }; /* isomorphic to struct sockaddr_in6 on HP-UX B.11.23 */ struct _md_sockaddr_in6 { PRUint16 sin6_family; PRUint16 sin6_port; PRUint32 sin6_flowinfo; struct _md_in6_addr sin6_addr; PRUint32 sin6_scope_id; }; #endif #if !defined(_PR_PTHREADS) #include #include #define USE_SETJMP #define _MD_GET_SP(_t) (*((int *)((_t)->md.jb) + 1)) #define PR_NUM_GCREGS _JBLEN /* Caveat: This makes jmp_buf full of doubles. */ #define CONTEXT(_th) ((_th)->md.jb) /* Stack needs two frames (64 bytes) at the bottom */ \ #define _MD_SET_THR_SP(_t, _sp) ((_MD_GET_SP(_t)) = (int) (_sp + 64 *2)) #define SAVE_CONTEXT(_th) _setjmp(CONTEXT(_th)) #define GOTO_CONTEXT(_th) _longjmp(CONTEXT(_th), 1) #if !defined(PTHREADS_USER) #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *(status) = PR_TRUE; \ if (_setjmp(CONTEXT(_thread))) (*_main)(); \ /* Stack needs two frames (64 bytes) at the bottom */ \ (_MD_GET_SP(_thread)) = (int) ((_sp) + 64*2); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!_setjmp(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _longjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures. HP-UX has no native threads. */ struct _MDThread { jmp_buf jb; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread #define _MD_RESUME_THREAD(thread) _MD_resume_thread #define _MD_CLEAN_THREAD(_thread) #else /* PTHREADS_USER */ #include "_nspr_pthread.h" #endif /* PTHREADS_USER */ #endif /* !defined(_PR_PTHREADS) */ #if !defined(PTHREADS_USER) #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #endif #if defined(HPUX_LW_TIMER) extern void _PR_HPUX_LW_IntervalInit(void); extern PRIntervalTime _PR_HPUX_LW_GetInterval(void); #define _MD_INTERVAL_INIT _PR_HPUX_LW_IntervalInit #define _MD_GET_INTERVAL _PR_HPUX_LW_GetInterval #define _MD_INTERVAL_PER_SEC() 1000 #else #define _MD_INTERVAL_USE_GTOD #endif /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv) #include #define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout) #ifdef HPUX11 extern void _MD_hpux_map_sendfile_error(int err); #endif /* HPUX11 */ #endif /* nspr_xhppa_defs_h___ */ nspr-4.11/nspr/pr/include/md/_hpux32.cfg0000644000000000000000000000647712623070344016165 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef HPUX #define HPUX #endif #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_AF_INET6 22 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_hpux64.cfg0000644000000000000000000000651512623070344016163 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef HPUX #define HPUX #endif #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define IS_64 #define PR_AF_INET6 22 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_irix.h0000644000000000000000000003126612623070344015471 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_irix_defs_h___ #define nspr_irix_defs_h___ #define _PR_HAVE_ATOMIC_CAS /* * MipsPro assembler defines _LANGUAGE_ASSEMBLY */ #ifndef _LANGUAGE_ASSEMBLY #include "prclist.h" #include "prthread.h" #include /* * Internal configuration macros */ #define PR_LINKER_ARCH "irix" #define _PR_SI_SYSNAME "IRIX" #define _PR_SI_ARCHITECTURE "mips" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _PR_NUM_GCREGS 9 #define _MD_MMAP_FLAGS MAP_PRIVATE #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MIN_STACK_SIZE 16384L #undef HAVE_STACK_GROWING_UP #define HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_MALLOC_SYMBOLS #define HAVE_DLL #define USE_DLFCN #define _PR_HAVE_ATOMIC_OPS #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_STAT_HAS_ST_ATIM #define _PR_HAVE_OFF64_T #define HAVE_POINTER_LOCALTIME_R #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #define _PR_ACCEPT_INHERIT_NONBLOCK #ifdef _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_HAVE_GETADDRINFO #endif /* Initialization entry points */ NSPR_API(void) _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit NSPR_API(void) _MD_IrixInit(void); #define _MD_FINAL_INIT _MD_IrixInit #define _MD_INIT_IO() /* Timer operations */ NSPR_API(PRIntervalTime) _MD_IrixGetInterval(void); #define _MD_GET_INTERVAL _MD_IrixGetInterval NSPR_API(PRIntervalTime) _MD_IrixIntervalPerSec(void); #define _MD_INTERVAL_PER_SEC _MD_IrixIntervalPerSec /* GC operations */ NSPR_API(void *) _MD_GetSP(PRThread *thread); #define _MD_GET_SP _MD_GetSP /* The atomic operations */ #include #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(val) add_then_test((unsigned long*)val, 1) #define _MD_ATOMIC_ADD(ptr, val) add_then_test((unsigned long*)ptr, (unsigned long)val) #define _MD_ATOMIC_DECREMENT(val) add_then_test((unsigned long*)val, 0xffffffff) #define _MD_ATOMIC_SET(val, newval) test_and_set((unsigned long*)val, newval) #if defined(_PR_PTHREADS) #else /* defined(_PR_PTHREADS) */ /************************************************************************/ #include #include #include #include #include #include #include /* * Data region private to each sproc. This region is setup by calling * mmap(...,MAP_LOCAL,...). The private data is mapped at the same * address in every sproc, but every sproc gets a private mapping. * * Just make sure that this structure fits in a page, as only one page * is allocated for the private region. */ struct sproc_private_data { struct PRThread *me; struct _PRCPU *cpu; struct PRThread *last; PRUintn intsOff; int sproc_pid; }; extern char *_nspr_sproc_private; #define _PR_PRDA() ((struct sproc_private_data *) _nspr_sproc_private) #define _MD_SET_CURRENT_THREAD(_thread) _PR_PRDA()->me = (_thread) #define _MD_THIS_THREAD() (_PR_PRDA()->me) #define _MD_LAST_THREAD() (_PR_PRDA()->last) #define _MD_SET_LAST_THREAD(_thread) _PR_PRDA()->last = (_thread) #define _MD_CURRENT_CPU() (_PR_PRDA()->cpu) #define _MD_SET_CURRENT_CPU(_cpu) _PR_PRDA()->cpu = (_cpu) #define _MD_SET_INTSOFF(_val) (_PR_PRDA()->intsOff = _val) #define _MD_GET_INTSOFF() (_PR_PRDA()->intsOff) #define _MD_SET_SPROC_PID(_val) (_PR_PRDA()->sproc_pid = _val) #define _MD_GET_SPROC_PID() (_PR_PRDA()->sproc_pid) NSPR_API(struct PRThread*) _MD_get_attached_thread(void); NSPR_API(struct PRThread*) _MD_get_current_thread(void); #define _MD_GET_ATTACHED_THREAD() _MD_get_attached_thread() #define _MD_CURRENT_THREAD() _MD_get_current_thread() #define _MD_CHECK_FOR_EXIT() { \ if (_pr_irix_exit_now) { \ _PR_POST_SEM(_pr_irix_exit_sem); \ _MD_Wakeup_CPUs(); \ _exit(0); \ } \ } #define _MD_ATTACH_THREAD(threadp) #define _MD_SAVE_ERRNO(_thread) (_thread)->md.errcode = errno; #define _MD_RESTORE_ERRNO(_thread) errno = (_thread)->md.errcode; extern struct _PRCPU *_pr_primordialCPU; extern usema_t *_pr_irix_exit_sem; extern PRInt32 _pr_irix_exit_now; extern int _pr_irix_primoridal_cpu_fd[]; extern PRInt32 _pr_irix_process_exit; extern PRInt32 _pr_irix_process_exit_code; /* Thread operations */ #define _PR_LOCK_HEAP() { \ PRIntn _is; \ if (_pr_primordialCPU) { \ if (_MD_GET_ATTACHED_THREAD() && \ !_PR_IS_NATIVE_THREAD( \ _MD_GET_ATTACHED_THREAD())) \ _PR_INTSOFF(_is); \ _PR_LOCK(_pr_heapLock); \ } #define _PR_UNLOCK_HEAP() if (_pr_primordialCPU) { \ _PR_UNLOCK(_pr_heapLock); \ if (_MD_GET_ATTACHED_THREAD() && \ !_PR_IS_NATIVE_THREAD( \ _MD_GET_ATTACHED_THREAD())) \ _PR_INTSON(_is); \ } \ } #define _PR_OPEN_POLL_SEM(_sem) usopenpollsema(_sem, 0666) #define _PR_WAIT_SEM(_sem) uspsema(_sem) #define _PR_POST_SEM(_sem) usvsema(_sem) #define _MD_CVAR_POST_SEM(threadp) usvsema((threadp)->md.cvar_pollsem) #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() struct _MDLock { ulock_t lock; usptr_t *arena; }; /* * disable pre-emption for the LOCAL threads when calling the arena lock * routines */ #define _PR_LOCK(lock) { \ PRIntn _is; \ PRThread *me = _MD_GET_ATTACHED_THREAD(); \ if (me && !_PR_IS_NATIVE_THREAD(me)) \ _PR_INTSOFF(_is); \ ussetlock(lock); \ if (me && !_PR_IS_NATIVE_THREAD(me)) \ _PR_FAST_INTSON(_is); \ } #define _PR_UNLOCK(lock) { \ PRIntn _is; \ PRThread *me = _MD_GET_ATTACHED_THREAD(); \ if (me && !_PR_IS_NATIVE_THREAD(me)) \ _PR_INTSOFF(_is); \ usunsetlock(lock); \ if (me && !_PR_IS_NATIVE_THREAD(me)) \ _PR_FAST_INTSON(_is); \ } NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md); NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp); #define _MD_LOCK(_lockp) _PR_LOCK((_lockp)->lock) #define _MD_UNLOCK(_lockp) _PR_UNLOCK((_lockp)->lock) #define _MD_TEST_AND_LOCK(_lockp) (uscsetlock((_lockp)->lock, 1) == 0) extern ulock_t _pr_heapLock; struct _MDThread { jmp_buf jb; usptr_t *pollsem_arena; usema_t *cvar_pollsem; PRInt32 cvar_pollsemfd; PRInt32 cvar_pollsem_select; /* acquire sem by calling select */ PRInt32 cvar_wait; /* if 1, thread is waiting on cvar Q */ PRInt32 id; PRInt32 suspending_id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDSemaphore { usema_t *sem; }; struct _MDCVar { ulock_t mdcvar_lock; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { PRInt32 id; PRInt32 suspending_id; struct _MDCPU_Unix md_unix; }; /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ int *jb = (_thread)->md.jb; \ *status = PR_TRUE; \ (void) setjmp(jb); \ (_thread)->md.jb[JB_SP] = (int) ((_sp) - 64); \ (_thread)->md.jb[JB_PC] = (int) _main; \ _thread->no_sched = 0; \ PR_END_MACRO /* ** Switch away from the current thread context by saving its state and ** calling the thread scheduler. Reload cpu when we come back from the ** context switch because it might have changed. * * XXX RUNQ lock needed before clearing _PR_NO_SCHED flag, because the * thread may be unr RUNQ? */ #define _MD_SWITCH_CONTEXT(_thread) \ PR_BEGIN_MACRO \ PR_ASSERT(_thread->no_sched); \ if (!setjmp(_thread->md.jb)) { \ _MD_SAVE_ERRNO(_thread) \ _MD_SET_LAST_THREAD(_thread); \ _PR_Schedule(); \ } else { \ PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \ _MD_LAST_THREAD()->no_sched = 0; \ } \ PR_END_MACRO /* ** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or ** initialized by _MD_INIT_CONTEXT. */ #define _MD_RESTORE_CONTEXT(_newThread) \ PR_BEGIN_MACRO \ int *jb = (_newThread)->md.jb; \ _MD_RESTORE_ERRNO(_newThread) \ _MD_SET_CURRENT_THREAD(_newThread); \ _newThread->no_sched = 1; \ longjmp(jb, 1); \ PR_END_MACRO NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread, PRBool wakeup_parent); NSPR_API(PRStatus) _MD_InitAttachedThread(struct PRThread *thread, PRBool wakeup_parent); #define _MD_INIT_THREAD(thread) _MD_InitThread(thread, PR_TRUE) #define _MD_INIT_ATTACHED_THREAD(thread) \ _MD_InitAttachedThread(thread, PR_FALSE) NSPR_API(void) _MD_ExitThread(struct PRThread *thread); #define _MD_EXIT_THREAD _MD_ExitThread NSPR_API(void) _MD_SuspendThread(struct PRThread *thread); #define _MD_SUSPEND_THREAD _MD_SuspendThread NSPR_API(void) _MD_ResumeThread(struct PRThread *thread); #define _MD_RESUME_THREAD _MD_ResumeThread NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread); #define _MD_SUSPEND_CPU _MD_SuspendCPU NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread); #define _MD_RESUME_CPU _MD_ResumeCPU #define _MD_BEGIN_SUSPEND_ALL() #define _MD_END_SUSPEND_ALL() #define _MD_BEGIN_RESUME_ALL() #define _MD_END_RESUME_ALL() NSPR_API(void) _MD_InitLocks(void); #define _MD_INIT_LOCKS _MD_InitLocks NSPR_API(void) _MD_CleanThread(struct PRThread *thread); #define _MD_CLEAN_THREAD _MD_CleanThread #define _MD_YIELD() sginap(0) /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and * awaken a thread which is waiting on a lock or cvar. */ NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout); #define _MD_WAIT _MD_wait NSPR_API(void) _PR_MD_primordial_cpu(); NSPR_API(void) _PR_MD_WAKEUP_PRIMORDIAL_CPU(); NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *); #define _MD_WAKEUP_WAITER _MD_WakeupWaiter NSPR_API(void ) _MD_exit(PRIntn status); #define _MD_EXIT _MD_exit #include "prthread.h" NSPR_API(void) _MD_SetPriority(struct _MDThread *thread, PRThreadPriority newPri); #define _MD_SET_PRIORITY _MD_SetPriority NSPR_API(PRStatus) _MD_CreateThread( struct PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); #define _MD_CREATE_THREAD _MD_CreateThread extern void _MD_CleanupBeforeExit(void); #define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit NSPR_API(void) _PR_MD_PRE_CLEANUP(PRThread *me); /* The following defines the unwrapped versions of select() and poll(). */ extern int _select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); #define _MD_SELECT _select #include #include #define _MD_POLL _poll extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout); #define HAVE_THREAD_AFFINITY 1 NSPR_API(PRInt32) _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask); #define _MD_GETTHREADAFFINITYMASK _MD_GetThreadAffinityMask NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu); #define _MD_INIT_RUNNING_CPU _MD_InitRunningCPU #endif /* defined(_PR_PTHREADS) */ #endif /* _LANGUAGE_ASSEMBLY */ #endif /* nspr_irix_defs_h___ */ nspr-4.11/nspr/pr/include/md/_irix32.cfg0000644000000000000000000000666112623070344016147 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef _SGI_MP_SOURCE #define _SGI_MP_SOURCE #endif #ifndef XP_UNIX #define XP_UNIX #endif #ifndef IRIX #define IRIX #endif #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_AF_INET6 24 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define _PR_POLL_BACKCOMPAT #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_irix64.cfg0000644000000000000000000000664212623070344016153 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef _SGI_MP_SOURCE #define _SGI_MP_SOURCE #endif #ifndef XP_UNIX #define XP_UNIX #endif #ifndef IRIX #define IRIX #endif #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define IS_64 #define PR_AF_INET6 24 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_linux.cfg0000644000000000000000000006703412623070344016167 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file is used by not only Linux but also other glibc systems * such as GNU/Hurd and GNU/k*BSD. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #if !defined(LINUX) && defined(__linux__) #define LINUX #endif #ifdef __FreeBSD_kernel__ #define PR_AF_INET6 28 /* same as AF_INET6 */ #elif defined(__GNU__) #define PR_AF_INET6 26 /* same as AF_INET6 */ #else #define PR_AF_INET6 10 /* same as AF_INET6 */ #endif #ifdef __powerpc64__ #ifdef __LITTLE_ENDIAN__ #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #else #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #endif #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__powerpc__) #ifdef __LITTLE_ENDIAN__ #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #else #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #endif #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__alpha) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__ia64__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__x86_64__) #ifdef __ILP32__ #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #endif #elif defined(__mc68000__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 2 #define PR_ALIGN_OF_LONG 2 #define PR_ALIGN_OF_INT64 2 #define PR_ALIGN_OF_FLOAT 2 #define PR_ALIGN_OF_DOUBLE 2 #define PR_ALIGN_OF_POINTER 2 #define PR_ALIGN_OF_WORD 2 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__sparc__) && defined (__arch64__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__sparc__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__i386__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__mips__) #ifdef __MIPSEB__ #define IS_BIG_ENDIAN 1 #undef IS_LITTLE_ENDIAN #elif defined(__MIPSEL__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #else #error "Unknown MIPS endianness." #endif #if _MIPS_SIM == _ABI64 #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #else /* _ABI64 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #endif /* _ABI64 */ #elif defined(__arm__) #ifdef __ARMEB__ #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #elif defined(__ARMEL__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #else #error "Unknown ARM endianness." #endif #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__aarch64__) #ifdef __AARCH64EB__ #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #elif defined(__AARCH64EL__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #else #error "Unknown Aarch64 endianness." #endif #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__hppa__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__s390x__) #define IS_BIG_ENDIAN 1 #undef IS_LITTLE_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__s390__) #define IS_BIG_ENDIAN 1 #undef IS_LITTLE_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__sh__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__avr32__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__m32r__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__or1k__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #error "Unknown CPU architecture" #endif #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #if PR_ALIGN_OF_DOUBLE == 8 #define HAVE_ALIGNED_DOUBLES #endif #if PR_ALIGN_OF_INT64 == 8 #define HAVE_ALIGNED_LONGLONGS #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_linux.h0000644000000000000000000005273312623070344015657 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file is used by not only Linux but also other glibc systems * such as GNU/Hurd and GNU/k*BSD. */ #ifndef nspr_linux_defs_h___ #define nspr_linux_defs_h___ #include "prthread.h" /* * Internal configuration macros */ #define PR_LINKER_ARCH "linux" #define _PR_SI_SYSNAME "LINUX" #ifdef __powerpc64__ #define _PR_SI_ARCHITECTURE "ppc64" #elif defined(__powerpc__) #define _PR_SI_ARCHITECTURE "ppc" #elif defined(__alpha) #define _PR_SI_ARCHITECTURE "alpha" #elif defined(__ia64__) #define _PR_SI_ARCHITECTURE "ia64" #elif defined(__x86_64__) #define _PR_SI_ARCHITECTURE "x86-64" #elif defined(__mc68000__) #define _PR_SI_ARCHITECTURE "m68k" #elif defined(__sparc__) && defined(__arch64__) #define _PR_SI_ARCHITECTURE "sparc64" #elif defined(__sparc__) #define _PR_SI_ARCHITECTURE "sparc" #elif defined(__i386__) #define _PR_SI_ARCHITECTURE "x86" #elif defined(__mips__) #define _PR_SI_ARCHITECTURE "mips" #elif defined(__arm__) #define _PR_SI_ARCHITECTURE "arm" #elif defined(__aarch64__) #define _PR_SI_ARCHITECTURE "aarch64" #elif defined(__hppa__) #define _PR_SI_ARCHITECTURE "hppa" #elif defined(__s390x__) #define _PR_SI_ARCHITECTURE "s390x" #elif defined(__s390__) #define _PR_SI_ARCHITECTURE "s390" #elif defined(__sh__) #define _PR_SI_ARCHITECTURE "sh" #elif defined(__avr32__) #define _PR_SI_ARCHITECTURE "avr32" #elif defined(__m32r__) #define _PR_SI_ARCHITECTURE "m32r" #elif defined(__or1k__) #define _PR_SI_ARCHITECTURE "or1k" #else #error "Unknown CPU architecture" #endif #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #if defined(__aarch64__) || defined(__mips__) #define _MD_MINIMUM_STACK_SIZE 0x20000 #endif #undef HAVE_STACK_GROWING_UP /* * Elf linux supports dl* functions */ #define HAVE_DLL #define USE_DLFCN #if defined(ANDROID) #define NO_DLOPEN_NULL #endif #if defined(__FreeBSD_kernel__) || defined(__GNU__) #define _PR_HAVE_SOCKADDR_LEN #endif #if defined(__i386__) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT _PR_x86_AtomicIncrement extern PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT _PR_x86_AtomicDecrement extern PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD _PR_x86_AtomicAdd extern PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _PR_x86_AtomicSet #endif #if defined(__ia64__) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT _PR_ia64_AtomicIncrement extern PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT _PR_ia64_AtomicDecrement extern PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD _PR_ia64_AtomicAdd extern PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _PR_ia64_AtomicSet #endif #if defined(__x86_64__) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT _PR_x86_64_AtomicIncrement extern PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT _PR_x86_64_AtomicDecrement extern PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD _PR_x86_64_AtomicAdd extern PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _PR_x86_64_AtomicSet #endif #if defined(__or1k__) #if defined(__GNUC__) /* Use GCC built-in functions */ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(ptr) __sync_add_and_fetch(ptr, 1) #define _MD_ATOMIC_DECREMENT(ptr) __sync_sub_and_fetch(ptr, 1) #define _MD_ATOMIC_ADD(ptr, i) __sync_add_and_fetch(ptr, i) #define _MD_ATOMIC_SET(ptr, nv) __sync_lock_test_and_set(ptr, nv) #endif #endif #if defined(__powerpc__) && !defined(__powerpc64__) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() extern PRInt32 _PR_ppc_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT _PR_ppc_AtomicIncrement extern PRInt32 _PR_ppc_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT _PR_ppc_AtomicDecrement extern PRInt32 _PR_ppc_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD _PR_ppc_AtomicAdd extern PRInt32 _PR_ppc_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _PR_ppc_AtomicSet #endif #if defined(__powerpc64__) #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) /* Use GCC built-in functions */ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(ptr) __sync_add_and_fetch(ptr, 1) #define _MD_ATOMIC_DECREMENT(ptr) __sync_sub_and_fetch(ptr, 1) #define _MD_ATOMIC_ADD(ptr, i) __sync_add_and_fetch(ptr, i) #define _MD_ATOMIC_SET(ptr, nv) __sync_lock_test_and_set(ptr, nv) #endif #endif #if defined(__mips__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) /* Use GCC built-in functions */ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(ptr) __sync_add_and_fetch(ptr, 1) #define _MD_ATOMIC_DECREMENT(ptr) __sync_sub_and_fetch(ptr, 1) #define _MD_ATOMIC_ADD(ptr, i) __sync_add_and_fetch(ptr, i) #define _MD_ATOMIC_SET(ptr, nv) __sync_lock_test_and_set(ptr, nv) #endif #if defined(__alpha) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_ADD(ptr, i) ({ \ PRInt32 __atomic_tmp, __atomic_ret; \ __asm__ __volatile__( \ "1: ldl_l %[ret], %[val] \n" \ " addl %[ret], %[inc], %[tmp] \n" \ " addl %[ret], %[inc], %[ret] \n" \ " stl_c %[tmp], %[val] \n" \ " beq %[tmp], 2f \n" \ ".subsection 2 \n" \ "2: br 1b \n" \ ".previous" \ : [ret] "=&r" (__atomic_ret), \ [tmp] "=&r" (__atomic_tmp), \ [val] "=m" (*ptr) \ : [inc] "Ir" (i), "m" (*ptr)); \ __atomic_ret; \ }) #define _MD_ATOMIC_INCREMENT(ptr) _MD_ATOMIC_ADD(ptr, 1) #define _MD_ATOMIC_DECREMENT(ptr) ({ \ PRInt32 __atomic_tmp, __atomic_ret; \ __asm__ __volatile__( \ "1: ldl_l %[ret], %[val] \n" \ " subl %[ret], 1, %[tmp] \n" \ " subl %[ret], 1, %[ret] \n" \ " stl_c %[tmp], %[val] \n" \ " beq %[tmp], 2f \n" \ ".subsection 2 \n" \ "2: br 1b \n" \ ".previous" \ : [ret] "=&r" (__atomic_ret), \ [tmp] "=&r" (__atomic_tmp), \ [val] "=m" (*ptr) \ : "m" (*ptr)); \ __atomic_ret; \ }) #define _MD_ATOMIC_SET(ptr, n) ({ \ PRInt32 __atomic_tmp, __atomic_ret; \ __asm__ __volatile__( \ "1: ldl_l %[ret], %[val] \n" \ " mov %[newval], %[tmp] \n" \ " stl_c %[tmp], %[val] \n" \ " beq %[tmp], 2f \n" \ ".subsection 2 \n" \ "2: br 1b \n" \ ".previous" \ : [ret] "=&r" (__atomic_ret), \ [tmp] "=&r"(__atomic_tmp), \ [val] "=m" (*ptr) \ : [newval] "Ir" (n), "m" (*ptr)); \ __atomic_ret; \ }) #endif #if defined(__arm__) || defined(__aarch64__) #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) /* Use GCC built-in functions */ #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(ptr) __sync_add_and_fetch(ptr, 1) #define _MD_ATOMIC_DECREMENT(ptr) __sync_sub_and_fetch(ptr, 1) #define _MD_ATOMIC_SET(ptr, nv) __sync_lock_test_and_set(ptr, nv) #define _MD_ATOMIC_ADD(ptr, i) __sync_add_and_fetch(ptr, i) #elif defined(_PR_ARM_KUSER) #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() /* * The kernel provides this helper function at a fixed address with a fixed * ABI signature, directly callable from user space. * * Definition: * Atomically store newval in *ptr if *ptr is equal to oldval. * Return zero if *ptr was changed or non-zero if no exchange happened. */ typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr); #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) #define _MD_ATOMIC_INCREMENT(ptr) _MD_ATOMIC_ADD(ptr, 1) #define _MD_ATOMIC_DECREMENT(ptr) _MD_ATOMIC_ADD(ptr, -1) static inline PRInt32 _MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 n) { PRInt32 ov, nv; volatile PRInt32 *vp = ptr; do { ov = *vp; nv = ov + n; } while (__kernel_cmpxchg(ov, nv, vp)); return nv; } static inline PRInt32 _MD_ATOMIC_SET(PRInt32 *ptr, PRInt32 nv) { PRInt32 ov; volatile PRInt32 *vp = ptr; do { ov = *vp; } while (__kernel_cmpxchg(ov, nv, vp)); return ov; } #endif #endif /* __arm__ */ #define USE_SETJMP #if (defined(__GLIBC__) && __GLIBC__ >= 2) || defined(ANDROID) #define _PR_POLL_AVAILABLE #endif #undef _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #if defined(__alpha) || defined(__ia64__) #define _PR_HAVE_LARGE_OFF_T #elif (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) \ || defined(ANDROID) #define _PR_HAVE_OFF64_T #else #define _PR_NO_LARGE_FILES #endif #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) \ || defined(ANDROID) #define _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #endif #ifndef ANDROID #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #endif /* Android has gethostbyname_r but not gethostbyaddr_r or gethostbyname2_r. */ #if (__GLIBC__ >= 2) && defined(_PR_PTHREADS) #define _PR_HAVE_GETHOST_R #define _PR_HAVE_GETHOST_R_INT #endif #ifdef _PR_PTHREADS extern void _MD_CleanupBeforeExit(void); #define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit #else /* ! _PR_PTHREADS */ #include #define PR_CONTEXT_TYPE sigjmp_buf #define CONTEXT(_th) ((_th)->md.context) #ifdef __powerpc__ /* * PowerPC based MkLinux * * On the PowerPC, the new style jmp_buf isn't used until glibc * 2.1. */ #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_GPR1] #else #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__misc[0] #endif /* glibc 2.1 or later */ #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) /* aix = 64, macos = 70 */ #define PR_NUM_GCREGS 64 #elif defined(__alpha) /* Alpha based Linux */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_SP] #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) #define _MD_SP_TYPE long int #else #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) #define _MD_SP_TYPE __ptr_t #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ /* XXX not sure if this is correct, or maybe it should be 17? */ #define PR_NUM_GCREGS 9 #elif defined(__ia64__) #define _MD_GET_SP(_t) ((long *)((_t)->md.context[0].__jmpbuf)[0]) #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) #define _MD_SP_TYPE long int #define PR_NUM_GCREGS _JBLEN #elif defined(__mc68000__) /* m68k based Linux */ /* * On the m68k, glibc still uses the old style sigjmp_buf, even * in glibc 2.0.7. */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) #define _MD_SP_TYPE int #else #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) #define _MD_SP_TYPE __ptr_t #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ /* XXX not sure if this is correct, or maybe it should be 17? */ #define PR_NUM_GCREGS 9 #elif defined(__sparc__) /* Sparc */ #if defined(__GLIBC__) && __GLIBC__ >= 2 /* * You need glibc2-2.0.7-25 or later. The libraries that came with * Red Hat 5.1 are not new enough, but they are in 5.2. */ #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_SP] #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[JB_FP] = val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[JB_FP]) #define _MD_SP_TYPE int #else #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__fp #define _MD_SET_FP(_t, val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) ((void *) 0) #define _MD_SP_TYPE __ptr_t #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ #elif defined(__i386__) /* Intel based Linux */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[JB_SP] #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[JB_BP] = val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[JB_BP]) #define _MD_SP_TYPE int #else #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[0].__bp = val) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) &((_t)->md.context[0].__jmpbuf[0].__bp) #define _MD_SP_TYPE __ptr_t #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ #define PR_NUM_GCREGS 6 #elif defined(__mips__) /* Linux/MIPS */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__sp #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[0].__fp = (val)) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[0].__fp) #define _MD_SP_TYPE __ptr_t #else #error "Linux/MIPS pre-glibc2 not supported yet" #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ #elif defined(__arm__) /* ARM/Linux */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #ifdef __ARM_EABI__ /* EABI */ #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[8] #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[7] = (val)) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[7]) #define _MD_SP_TYPE __ptr_t #else /* __ARM_EABI__ */ /* old ABI */ #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[20] #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[19] = (val)) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[19]) #define _MD_SP_TYPE __ptr_t #endif /* __ARM_EABI__ */ #else #error "ARM/Linux pre-glibc2 not supported yet" #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ #elif defined(__sh__) /* SH/Linux */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[7] #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[6] = (val)) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[6]) #define _MD_SP_TYPE __ptr_t #else #error "SH/Linux pre-glibc2 not supported yet" #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ #elif defined(__m32r__) /* Linux/M32R */ #if defined(__GLIBC__) && __GLIBC__ >= 2 #define _MD_GET_SP(_t) (_t)->md.context[0].__jmpbuf[0].__regs[JB_SP] #define _MD_SET_FP(_t, val) ((_t)->md.context[0].__jmpbuf[0].__regs[JB_FP] = (val)) #define _MD_GET_SP_PTR(_t) &(_MD_GET_SP(_t)) #define _MD_GET_FP_PTR(_t) (&(_t)->md.context[0].__jmpbuf[0].__regs[JB_FP]) #define _MD_SP_TYPE __ptr_t #else #error "Linux/M32R pre-glibc2 not supported yet" #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ #else #error "Unknown CPU architecture" #endif /*__powerpc__*/ /* ** Initialize a thread context to run "_main()" when started */ #ifdef __powerpc__ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (sigsetjmp(CONTEXT(_thread), 1)) { \ _main(); \ } \ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 128); \ _thread->md.sp = _MD_GET_SP_PTR(_thread); \ _thread->md.fp = _MD_GET_FP_PTR(_thread); \ _MD_SET_FP(_thread, 0); \ } #elif defined(__mips__) #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ (void) sigsetjmp(CONTEXT(_thread), 1); \ _thread->md.context[0].__jmpbuf[0].__pc = (__ptr_t) _main; \ _MD_GET_SP(_thread) = (_MD_SP_TYPE) ((_sp) - 64); \ _thread->md.sp = _MD_GET_SP_PTR(_thread); \ _thread->md.fp = _MD_GET_FP_PTR(_thread); \ _MD_SET_FP(_thread, 0); \ } #else #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (sigsetjmp(CONTEXT(_thread), 1)) { \ _main(); \ } \ _MD_GET_SP(_thread) = (_MD_SP_TYPE) ((_sp) - 64); \ _thread->md.sp = _MD_GET_SP_PTR(_thread); \ _thread->md.fp = _MD_GET_FP_PTR(_thread); \ _MD_SET_FP(_thread, 0); \ } #endif /*__powerpc__*/ #define _MD_SWITCH_CONTEXT(_thread) \ if (!sigsetjmp(CONTEXT(_thread), 1)) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ siglongjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { PR_CONTEXT_TYPE context; void *sp; void *fp; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #include /* for FD_SETSIZE */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() extern PRStatus _MD_InitializeThread(PRThread *thread); #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread #define _MD_RESUME_THREAD(thread) _MD_resume_thread #define _MD_CLEAN_THREAD(_thread) extern PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRUintn newPri); extern PRStatus _MD_WAIT(PRThread *, PRIntervalTime timeout); extern PRStatus _MD_WAKEUP_WAITER(PRThread *); extern void _MD_YIELD(void); #endif /* ! _PR_PTHREADS */ extern void _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define HAVE_CLOCK_MONOTONIC /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #define _MD_SELECT __select #ifdef _PR_POLL_AVAILABLE #include extern int __syscall_poll(struct pollfd *ufds, unsigned long int nfds, int timeout); #define _MD_POLL __syscall_poll #endif /* For writev() */ #include extern void _MD_linux_map_sendfile_error(int err); #endif /* nspr_linux_defs_h___ */ nspr-4.11/nspr/pr/include/md/_netbsd.cfg0000644000000000000000000002302112623070344016273 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef NETBSD #define NETBSD #endif #define PR_AF_INET6 24 /* same as AF_INET6 */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #if defined(__i386__) || defined(__arm32__) || defined(__ARMEL__) || \ defined(__MIPSEL__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #elif defined(__sparc_v9__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #elif defined(__sparc__) || defined(__MIPSEB__) || defined(__ARMEB__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #elif defined(__alpha__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__amd64__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__powerpc__) || defined(__m68k__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #error Must define constants for type sizes here. #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_netbsd.h0000644000000000000000000001371212623070344015771 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_netbsd_defs_h___ #define nspr_netbsd_defs_h___ #include #include /* for __NetBSD_Version__ */ #define PR_LINKER_ARCH "netbsd" #define _PR_SI_SYSNAME "NetBSD" #if defined(__i386__) #define _PR_SI_ARCHITECTURE "x86" #elif defined(__alpha__) #define _PR_SI_ARCHITECTURE "alpha" #elif defined(__amd64__) #define _PR_SI_ARCHITECTURE "amd64" #elif defined(__m68k__) #define _PR_SI_ARCHITECTURE "m68k" #elif defined(__powerpc__) #define _PR_SI_ARCHITECTURE "powerpc" #elif defined(__sparc_v9__) #define _PR_SI_ARCHITECTURE "sparc64" #elif defined(__sparc__) #define _PR_SI_ARCHITECTURE "sparc" #elif defined(__mips__) #define _PR_SI_ARCHITECTURE "mips" #elif defined(__arm32__) || defined(__arm__) || defined(__armel__) \ || defined(__armeb__) #define _PR_SI_ARCHITECTURE "arm" #endif #if defined(__ELF__) #define PR_DLL_SUFFIX ".so" #else #define PR_DLL_SUFFIX ".so.1.0" #endif #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define USE_DLFCN #define _PR_HAVE_SOCKADDR_LEN #define _PR_NO_LARGE_FILES #define _PR_STAT_HAS_ST_ATIMESPEC #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #if __NetBSD_Version__ >= 105000000 #define _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #endif #define USE_SETJMP #ifndef _PR_PTHREADS #include #define PR_CONTEXT_TYPE sigjmp_buf #define CONTEXT(_th) ((_th)->md.context) #if defined(__i386__) || defined(__sparc__) || defined(__m68k__) || defined(__powerpc__) #define JB_SP_INDEX 2 #elif defined(__mips__) #define JB_SP_INDEX 4 #elif defined(__alpha__) #define JB_SP_INDEX 34 #elif defined(__arm32__) /* * On the arm32, the jmpbuf regs underwent a name change after NetBSD 1.3. */ #ifdef JMPBUF_REG_R13 #define JB_SP_INDEX JMPBUF_REG_R13 #else #define JB_SP_INDEX _JB_REG_R13 #endif #else #error "Need to define SP index in jmp_buf here" #endif #define _MD_GET_SP(_th) (_th)->md.context[JB_SP_INDEX] #define PR_NUM_GCREGS _JBLEN /* ** Initialize a thread context to run "_main()" when started */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (sigsetjmp(CONTEXT(_thread), 1)) { \ _main(); \ } \ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!sigsetjmp(CONTEXT(_thread), 1)) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ siglongjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread #define _MD_RESUME_THREAD(thread) _MD_resume_thread #define _MD_CLEAN_THREAD(_thread) #endif /* ! _PR_PTHREADS */ extern void _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INTERVAL_USE_GTOD /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv) #if defined(_PR_POLL_AVAILABLE) #include #define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout) #endif #if NetBSD1_3 == 1L typedef unsigned int nfds_t; #endif #endif /* nspr_netbsd_defs_h___ */ nspr-4.11/nspr/pr/include/md/_nspr_pthread.h0000644000000000000000000001607012623070344017203 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_pthread_defs_h___ #define nspr_pthread_defs_h___ #include #include "prthread.h" #if defined(PTHREADS_USER) /* ** Thread Local Storage */ extern pthread_key_t current_thread_key; extern pthread_key_t current_cpu_key; extern pthread_key_t last_thread_key; extern pthread_key_t intsoff_key; #define _MD_CURRENT_THREAD() \ ((struct PRThread *) pthread_getspecific(current_thread_key)) #define _MD_CURRENT_CPU() \ ((struct _PRCPU *) pthread_getspecific(current_cpu_key)) #define _MD_LAST_THREAD() \ ((struct PRThread *) pthread_getspecific(last_thread_key)) #define _MD_SET_CURRENT_THREAD(newval) \ pthread_setspecific(current_thread_key, (void *)newval) #define _MD_SET_CURRENT_CPU(newval) \ pthread_setspecific(current_cpu_key, (void *)newval) #define _MD_SET_LAST_THREAD(newval) \ pthread_setspecific(last_thread_key, (void *)newval) #define _MD_SET_INTSOFF(_val) #define _MD_GET_INTSOFF() 1 /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ *status = PR_TRUE; \ if (SAVE_CONTEXT(_thread)) { \ (*_main)(); \ } \ _MD_SET_THR_SP(_thread, _sp); \ _thread->no_sched = 0; \ PR_END_MACRO #define _MD_SWITCH_CONTEXT(_thread) \ PR_BEGIN_MACRO \ PR_ASSERT(_thread->no_sched); \ if (!SAVE_CONTEXT(_thread)) { \ (_thread)->md.errcode = errno; \ _MD_SET_LAST_THREAD(_thread); \ _PR_Schedule(); \ } else { \ (_MD_LAST_THREAD())->no_sched = 0; \ } \ PR_END_MACRO /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ PR_BEGIN_MACRO \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _thread->no_sched = 1; \ GOTO_CONTEXT(_thread); \ PR_END_MACRO /* Machine-dependent (MD) data structures */ struct _MDThread { jmp_buf jb; int id; int errcode; pthread_t pthread; pthread_mutex_t pthread_mutex; pthread_cond_t pthread_cond; int wait; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { pthread_mutex_t mutex; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { pthread_mutex_t mutex; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { jmp_buf jb; pthread_t pthread; struct _MDCPU_Unix md_unix; }; /* #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) */ extern pthread_mutex_t _pr_heapLock; #define _PR_LOCK(lock) pthread_mutex_lock(lock) #define _PR_UNLOCK(lock) pthread_mutex_unlock(lock) #define _PR_LOCK_HEAP() { \ if (_pr_primordialCPU) { \ _PR_LOCK(_pr_heapLock); \ } #define _PR_UNLOCK_HEAP() if (_pr_primordialCPU) { \ _PR_UNLOCK(_pr_heapLock); \ } \ } NSPR_API(PRStatus) _MD_NEW_LOCK(struct _MDLock *md); NSPR_API(void) _MD_FREE_LOCK(struct _MDLock *lockp); #define _MD_LOCK(_lockp) _PR_LOCK(&(_lockp)->mutex) #define _MD_UNLOCK(_lockp) _PR_UNLOCK(&(_lockp)->mutex) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_CHECK_FOR_EXIT() NSPR_API(PRStatus) _MD_InitThread(struct PRThread *thread); #define _MD_INIT_THREAD _MD_InitThread #define _MD_INIT_ATTACHED_THREAD _MD_InitThread NSPR_API(void) _MD_ExitThread(struct PRThread *thread); #define _MD_EXIT_THREAD _MD_ExitThread NSPR_API(void) _MD_SuspendThread(struct PRThread *thread); #define _MD_SUSPEND_THREAD _MD_SuspendThread NSPR_API(void) _MD_ResumeThread(struct PRThread *thread); #define _MD_RESUME_THREAD _MD_ResumeThread NSPR_API(void) _MD_SuspendCPU(struct _PRCPU *thread); #define _MD_SUSPEND_CPU _MD_SuspendCPU NSPR_API(void) _MD_ResumeCPU(struct _PRCPU *thread); #define _MD_RESUME_CPU _MD_ResumeCPU #define _MD_BEGIN_SUSPEND_ALL() #define _MD_END_SUSPEND_ALL() #define _MD_BEGIN_RESUME_ALL() #define _MD_END_RESUME_ALL() NSPR_API(void) _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit NSPR_API(void) _MD_InitLocks(void); #define _MD_INIT_LOCKS _MD_InitLocks NSPR_API(void) _MD_CleanThread(struct PRThread *thread); #define _MD_CLEAN_THREAD _MD_CleanThread NSPR_API(PRStatus) _MD_CreateThread( struct PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); #define _MD_CREATE_THREAD _MD_CreateThread extern void _MD_CleanupBeforeExit(void); #define _MD_CLEANUP_BEFORE_EXIT _MD_CleanupBeforeExit NSPR_API(void) _MD_InitRunningCPU(struct _PRCPU *cpu); #define _MD_INIT_RUNNING_CPU _MD_InitRunningCPU /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and * awaken a thread which is waiting on a lock or cvar. */ NSPR_API(PRStatus) _MD_wait(struct PRThread *, PRIntervalTime timeout); #define _MD_WAIT _MD_wait NSPR_API(PRStatus) _MD_WakeupWaiter(struct PRThread *); #define _MD_WAKEUP_WAITER _MD_WakeupWaiter NSPR_API(void) _MD_SetPriority(struct _MDThread *thread, PRThreadPriority newPri); #define _MD_SET_PRIORITY _MD_SetPriority #endif /* PTHREADS_USER */ #endif /* nspr_pthread_defs_h___ */ nspr-4.11/nspr/pr/include/md/_nto.cfg0000644000000000000000000000665412623070344015631 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef NTO #define NTO #endif #define PR_AF_INET6 24 /* same as AF_INET6 */ #ifdef __i386__ #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1L #define PR_BYTES_PER_SHORT 2L #define PR_BYTES_PER_INT 4L #define PR_BYTES_PER_INT64 8L #define PR_BYTES_PER_LONG 4L #define PR_BYTES_PER_FLOAT 4L #define PR_BYTES_PER_DOUBLE 8L #define PR_BYTES_PER_WORD 4L #define PR_BYTES_PER_DWORD 8L #define PR_BITS_PER_BYTE 8L #define PR_BITS_PER_SHORT 16L #define PR_BITS_PER_INT 32L #define PR_BITS_PER_INT64 64L #define PR_BITS_PER_LONG 32L #define PR_BITS_PER_FLOAT 32L #define PR_BITS_PER_DOUBLE 64L #define PR_BITS_PER_WORD 32L #define PR_BITS_PER_BYTE_LOG2 3L #define PR_BITS_PER_SHORT_LOG2 4L #define PR_BITS_PER_INT_LOG2 5L #define PR_BITS_PER_INT64_LOG2 6L #define PR_BITS_PER_LONG_LOG2 5L #define PR_BITS_PER_FLOAT_LOG2 5L #define PR_BITS_PER_DOUBLE_LOG2 6L #define PR_BITS_PER_WORD_LOG2 5L #define PR_ALIGN_OF_SHORT 2L #define PR_ALIGN_OF_INT 4L #define PR_ALIGN_OF_LONG 4L #define PR_ALIGN_OF_INT64 4L #define PR_ALIGN_OF_FLOAT 4L #define PR_ALIGN_OF_DOUBLE 4L #define PR_ALIGN_OF_POINTER 4L #define PR_ALIGN_OF_WORD 4L #define PR_BYTES_PER_WORD_LOG2 2L #define PR_BYTES_PER_DWORD_LOG2 3L #define PR_WORDS_PER_DWORD_LOG2 1L #else #error Undefined CPU Architecture #endif #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_nto.h0000644000000000000000000001115212623070344015306 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_nto_defs_h___ #define nspr_nto_defs_h___ /* ** Internal configuration macros */ #define PR_LINKER_ARCH "nto" #define _PR_SI_SYSNAME "NTO" #define _PR_SI_ARCHITECTURE "x86" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MINIMUM_STACK_SIZE 131072L #define _MD_MMAP_FLAGS MAP_PRIVATE #ifndef HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_IO_SYMBOLS #endif #undef _PR_POLL_AVAILABLE #undef _PR_USE_POLL #define _PR_HAVE_SOCKADDR_LEN #undef HAVE_BSD_FLOCK #define HAVE_FCNTL_FILE_LOCKING #define _PR_NO_LARGE_FILES #define _PR_STAT_HAS_ONLY_ST_ATIME #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #define _PR_HAVE_POSIX_SEMAPHORES #undef FD_SETSIZE #define FD_SETSIZE 4096 #include #include #include #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define USE_DLFCN #define NEED_STRFTIME_LOCK #define NEED_TIME_R #define _PR_NEED_STRCASECMP #ifndef HAVE_STRERROR #define HAVE_STRERROR #endif #define USE_SETJMP #include #define _SETJMP setjmp #define _LONGJMP longjmp #define _PR_CONTEXT_TYPE jmp_buf #define _PR_NUM_GCREGS _JBLEN #define _MD_GET_SP(_t) (_t)->md.context[7] #define CONTEXT(_th) ((_th)->md.context) /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!_SETJMP(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _LONGJMP(CONTEXT(_thread), 1); \ } /* ** Machine-dependent (MD) data structures. */ struct _MDThread { _PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* ** md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD], fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INTERVAL_USE_GTOD #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) /* ** We wrapped the select() call. _MD_SELECT refers to the built-in, ** unwrapped version. */ #define _MD_SELECT select #define SA_RESTART 0 #endif /* nspr_nto_defs_h___ */ nspr-4.11/nspr/pr/include/md/_openbsd.cfg0000644000000000000000000002266312623070344016461 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef OPENBSD #define OPENBSD #endif #define PR_AF_INET6 24 /* same as AF_INET6 */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #if defined(__i386__) || defined(__arm__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #elif defined(__amd64__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_ALIGN_OF_WORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #elif defined(__sparc_v9__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__sparc__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #elif defined(__alpha__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__powerpc__) || defined(__m68k__) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #error Must define constants for type sizes here. #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_openbsd.h0000644000000000000000000001263012623070344016142 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_openbsd_defs_h___ #define nspr_openbsd_defs_h___ #include #define PR_LINKER_ARCH "openbsd" #define _PR_SI_SYSNAME "OPENBSD" #if defined(__i386__) #define _PR_SI_ARCHITECTURE "x86" #elif defined(__alpha__) #define _PR_SI_ARCHITECTURE "alpha" #elif defined(__amd64__) #define _PR_SI_ARCHITECTURE "amd64" #elif defined(__m68k__) #define _PR_SI_ARCHITECTURE "m68k" #elif defined(__powerpc__) #define _PR_SI_ARCHITECTURE "powerpc" #elif defined(__sparc__) #define _PR_SI_ARCHITECTURE "sparc" #elif defined(__arm__) #define _PR_SI_ARCHITECTURE "arm" #endif #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define USE_DLFCN #define _PR_HAVE_SOCKADDR_LEN #define _PR_HAVE_LARGE_OFF_T #define _PR_STAT_HAS_ST_ATIMESPEC #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #define _PR_INET6 #define _PR_HAVE_INET_NTOP #define _PR_HAVE_GETHOSTBYNAME2 #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #define USE_SETJMP #ifndef _PR_PTHREADS #include #define PR_CONTEXT_TYPE sigjmp_buf #define CONTEXT(_th) ((_th)->md.context) #if defined(__i386__) || defined(__sparc__) || defined(__m68k__) #define JB_SP_INDEX 2 #elif defined(__powerpc__) #define JB_SP_INDEX 1 #elif defined(__alpha__) #define JB_SP_INDEX 34 #elif defined(__amd64__) #define JB_SP_INDEX 6 #elif defined(__arm__) #define JB_SP_INDEX 23 #else #error "Need to define SP index in jmp_buf here" #endif #define _MD_GET_SP(_th) (_th)->md.context[JB_SP_INDEX] #define PR_NUM_GCREGS _JBLEN /* ** Initialize a thread context to run "_main()" when started */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (sigsetjmp(CONTEXT(_thread), 1)) { \ _main(); \ } \ _MD_GET_SP(_thread) = (unsigned char*) ((_sp) - 64); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!sigsetjmp(CONTEXT(_thread), 1)) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ siglongjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) _MD_suspend_thread #define _MD_RESUME_THREAD(thread) _MD_resume_thread #define _MD_CLEAN_THREAD(_thread) #endif /* ! _PR_PTHREADS */ #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INTERVAL_USE_GTOD /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #define _MD_SELECT(nfds,r,w,e,tv) syscall(SYS_select,nfds,r,w,e,tv) #include #define _MD_POLL(fds,nfds,timeout) syscall(SYS_poll,fds,nfds,timeout) #if OpenBSD1_3 == 1L typedef unsigned int nfds_t; #endif #endif /* nspr_openbsd_defs_h___ */ nspr-4.11/nspr/pr/include/md/_os2.cfg0000644000000000000000000000710112623070344015520 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_PC #define XP_PC #endif #ifndef XP_OS2 #define XP_OS2 #endif #ifndef OS2 #define OS2 #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #ifdef NO_LONG_LONG #undef HAVE_LONG_LONG #else #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG 1 #endif #endif #define PR_AF_INET6 24 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 5 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_WORD 4 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_POINTER 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 2 #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_os2.h0000644000000000000000000004435612623070344015225 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_os2_defs_h___ #define nspr_os2_defs_h___ #ifndef NO_LONG_LONG #define INCL_LONGLONG #endif #define INCL_DOS #define INCL_DOSPROCESS #define INCL_DOSERRORS #define INCL_WIN #define INCL_WPS #include #include #include "prio.h" #include /* * Internal configuration macros */ #define PR_LINKER_ARCH "os2" #define _PR_SI_SYSNAME "OS2" #define _PR_SI_ARCHITECTURE "x86" /* XXXMB hardcode for now */ #define HAVE_DLL #define _PR_GLOBAL_THREADS_ONLY #undef HAVE_THREAD_AFFINITY #define _PR_HAVE_THREADSAFE_GETHOST #define _PR_HAVE_ATOMIC_OPS #define HAVE_NETINET_TCP_H #define HANDLE unsigned long #define HINSTANCE HMODULE /* --- Common User-Thread/Native-Thread Definitions --------------------- */ /* --- Globals --- */ extern struct PRLock *_pr_schedLock; /* --- Typedefs --- */ typedef void (*FiberFunc)(void *); #define PR_NUM_GCREGS 8 typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS]; #define GC_VMBASE 0x40000000 #define GC_VMLIMIT 0x00FFFFFF typedef int (*FARPROC)(); #define _MD_MAGIC_THREAD 0x22222222 #define _MD_MAGIC_THREADSTACK 0x33333333 #define _MD_MAGIC_SEGMENT 0x44444444 #define _MD_MAGIC_DIR 0x55555555 #define _MD_MAGIC_CV 0x66666666 struct _MDSemaphore { HEV sem; }; struct _MDCPU { int unused; }; struct _MDThread { HEV blocked_sema; /* Threads block on this when waiting * for IO or CondVar. */ PRBool inCVWaitQueue; /* PR_TRUE if the thread is in the * wait queue of some cond var. * PR_FALSE otherwise. */ TID handle; /* OS/2 thread handle */ void *sp; /* only valid when suspended */ PRUint32 magic; /* for debugging */ PR_CONTEXT_TYPE gcContext; /* Thread context for GC */ struct PRThread *prev, *next; /* used by the cvar wait queue to * chain the PRThread structures * together */ }; struct _MDThreadStack { PRUint32 magic; /* for debugging */ }; struct _MDSegment { PRUint32 magic; /* for debugging */ }; #undef PROFILE_LOCKS struct _MDDir { HDIR d_hdl; union { FILEFINDBUF3 small; FILEFINDBUF3L large; } d_entry; PRBool firstEntry; /* Is this the entry returned * by FindFirstFile()? */ PRUint32 magic; /* for debugging */ }; struct _MDCVar { PRUint32 magic; struct PRThread *waitHead, *waitTail; /* the wait queue: a doubly- * linked list of threads * waiting on this condition * variable */ PRIntn nwait; /* number of threads in the * wait queue */ }; #define _MD_CV_NOTIFIED_LENGTH 6 typedef struct _MDNotified _MDNotified; struct _MDNotified { PRIntn length; /* # of used entries in this * structure */ struct { struct _MDCVar *cv; /* the condition variable notified */ PRIntn times; /* and the number of times notified */ struct PRThread *notifyHead; /* list of threads to wake up */ } cv[_MD_CV_NOTIFIED_LENGTH]; _MDNotified *link; /* link to another of these, or NULL */ }; struct _MDLock { HMTX mutex; /* this is recursive on OS/2 */ /* * When notifying cvars, there is no point in actually * waking up the threads waiting on the cvars until we've * released the lock. So, we temporarily record the cvars. * When doing an unlock, we'll then wake up the waiting threads. */ struct _MDNotified notified; /* array of conditions notified */ #ifdef PROFILE_LOCKS PRInt32 hitcount; PRInt32 misscount; #endif }; struct _MDFileDesc { PRInt32 osfd; /* The osfd can come from one of three spaces: * - For stdin, stdout, and stderr, we are using * the libc file handle (0, 1, 2), which is an int. * - For files and pipes, we are using OS/2 handles, * which is a void*. * - For sockets, we are using int */ }; struct _MDProcess { PID pid; }; /* --- Misc stuff --- */ #define _MD_GET_SP(thread) (thread)->md.gcContext[6] /* --- IO stuff --- */ #define _MD_OPEN (_PR_MD_OPEN) #define _MD_OPEN_FILE (_PR_MD_OPEN) #define _MD_READ (_PR_MD_READ) #define _MD_WRITE (_PR_MD_WRITE) #define _MD_WRITEV (_PR_MD_WRITEV) #define _MD_LSEEK (_PR_MD_LSEEK) #define _MD_LSEEK64 (_PR_MD_LSEEK64) extern PRInt32 _MD_CloseFile(PRInt32 osfd); #define _MD_CLOSE_FILE _MD_CloseFile #define _MD_GETFILEINFO (_PR_MD_GETFILEINFO) #define _MD_GETFILEINFO64 (_PR_MD_GETFILEINFO64) #define _MD_GETOPENFILEINFO (_PR_MD_GETOPENFILEINFO) #define _MD_GETOPENFILEINFO64 (_PR_MD_GETOPENFILEINFO64) #define _MD_STAT (_PR_MD_STAT) #define _MD_RENAME (_PR_MD_RENAME) #define _MD_ACCESS (_PR_MD_ACCESS) #define _MD_DELETE (_PR_MD_DELETE) #define _MD_MKDIR (_PR_MD_MKDIR) #define _MD_MAKE_DIR (_PR_MD_MKDIR) #define _MD_RMDIR (_PR_MD_RMDIR) #define _MD_LOCKFILE (_PR_MD_LOCKFILE) #define _MD_TLOCKFILE (_PR_MD_TLOCKFILE) #define _MD_UNLOCKFILE (_PR_MD_UNLOCKFILE) /* --- Socket IO stuff --- */ /* The ones that don't map directly may need to be re-visited... */ #define _MD_EACCES EACCES #define _MD_EADDRINUSE EADDRINUSE #define _MD_EADDRNOTAVAIL EADDRNOTAVAIL #define _MD_EAFNOSUPPORT EAFNOSUPPORT #define _MD_EAGAIN EWOULDBLOCK #define _MD_EALREADY EALREADY #define _MD_EBADF EBADF #define _MD_ECONNREFUSED ECONNREFUSED #define _MD_ECONNRESET ECONNRESET #define _MD_EFAULT SOCEFAULT #define _MD_EINPROGRESS EINPROGRESS #define _MD_EINTR EINTR #define _MD_EINVAL EINVAL #define _MD_EISCONN EISCONN #define _MD_ENETUNREACH ENETUNREACH #define _MD_ENOENT ENOENT #define _MD_ENOTCONN ENOTCONN #define _MD_ENOTSOCK ENOTSOCK #define _MD_EOPNOTSUPP EOPNOTSUPP #define _MD_EWOULDBLOCK EWOULDBLOCK #define _MD_GET_SOCKET_ERROR() sock_errno() #ifndef INADDR_LOOPBACK /* For some reason this is not defined in OS2 tcpip */ /* #define INADDR_LOOPBACK INADDR_ANY */ #endif #define _MD_INIT_FILEDESC(fd) extern void _MD_MakeNonblock(PRFileDesc *f); #define _MD_MAKE_NONBLOCK _MD_MakeNonblock #define _MD_INIT_FD_INHERITABLE (_PR_MD_INIT_FD_INHERITABLE) #define _MD_QUERY_FD_INHERITABLE (_PR_MD_QUERY_FD_INHERITABLE) #define _MD_SHUTDOWN (_PR_MD_SHUTDOWN) #define _MD_LISTEN _PR_MD_LISTEN extern PRInt32 _MD_CloseSocket(PRInt32 osfd); #define _MD_CLOSE_SOCKET _MD_CloseSocket #define _MD_SENDTO (_PR_MD_SENDTO) #define _MD_RECVFROM (_PR_MD_RECVFROM) #define _MD_SOCKETPAIR (_PR_MD_SOCKETPAIR) #define _MD_GETSOCKNAME (_PR_MD_GETSOCKNAME) #define _MD_GETPEERNAME (_PR_MD_GETPEERNAME) #define _MD_GETSOCKOPT (_PR_MD_GETSOCKOPT) #define _MD_SETSOCKOPT (_PR_MD_SETSOCKOPT) #define _MD_FSYNC _PR_MD_FSYNC #define _MD_SET_FD_INHERITABLE (_PR_MD_SET_FD_INHERITABLE) #ifdef _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT #define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD #define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT #define _MD_ATOMIC_SET _PR_MD_ATOMIC_SET #endif #define _MD_INIT_IO (_PR_MD_INIT_IO) #define _MD_PR_POLL (_PR_MD_PR_POLL) #define _MD_SOCKET (_PR_MD_SOCKET) extern PRInt32 _MD_SocketAvailable(PRFileDesc *fd); #define _MD_SOCKETAVAILABLE _MD_SocketAvailable #define _MD_PIPEAVAILABLE _MD_SocketAvailable #define _MD_CONNECT (_PR_MD_CONNECT) extern PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, PRIntervalTime timeout); #define _MD_ACCEPT _MD_Accept #define _MD_BIND (_PR_MD_BIND) #define _MD_RECV (_PR_MD_RECV) #define _MD_SEND (_PR_MD_SEND) /* --- Scheduler stuff --- */ /* #define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU */ #define _MD_PAUSE_CPU /* --- DIR stuff --- */ #define PR_DIRECTORY_SEPARATOR '\\' #define PR_DIRECTORY_SEPARATOR_STR "\\" #define PR_PATH_SEPARATOR ';' #define PR_PATH_SEPARATOR_STR ";" #define _MD_ERRNO() errno #define _MD_OPEN_DIR (_PR_MD_OPEN_DIR) #define _MD_CLOSE_DIR (_PR_MD_CLOSE_DIR) #define _MD_READ_DIR (_PR_MD_READ_DIR) /* --- Segment stuff --- */ #define _MD_INIT_SEGS() #define _MD_ALLOC_SEGMENT(seg, size, vaddr) 0 #define _MD_FREE_SEGMENT(seg) /* --- Environment Stuff --- */ #define _MD_GET_ENV (_PR_MD_GET_ENV) #define _MD_PUT_ENV (_PR_MD_PUT_ENV) /* --- Threading Stuff --- */ #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_INIT_THREAD (_PR_MD_INIT_THREAD) #define _MD_INIT_ATTACHED_THREAD (_PR_MD_INIT_THREAD) #define _MD_CREATE_THREAD (_PR_MD_CREATE_THREAD) #define _MD_YIELD (_PR_MD_YIELD) #define _MD_SET_PRIORITY (_PR_MD_SET_PRIORITY) #define _MD_CLEAN_THREAD (_PR_MD_CLEAN_THREAD) #define _MD_SETTHREADAFFINITYMASK (_PR_MD_SETTHREADAFFINITYMASK) #define _MD_GETTHREADAFFINITYMASK (_PR_MD_GETTHREADAFFINITYMASK) #define _MD_EXIT_THREAD (_PR_MD_EXIT_THREAD) #define _MD_SUSPEND_THREAD (_PR_MD_SUSPEND_THREAD) #define _MD_RESUME_THREAD (_PR_MD_RESUME_THREAD) #define _MD_SUSPEND_CPU (_PR_MD_SUSPEND_CPU) #define _MD_RESUME_CPU (_PR_MD_RESUME_CPU) #define _MD_WAKEUP_CPUS (_PR_MD_WAKEUP_CPUS) #define _MD_BEGIN_SUSPEND_ALL() #define _MD_BEGIN_RESUME_ALL() #define _MD_END_SUSPEND_ALL() #define _MD_END_RESUME_ALL() /* --- Lock stuff --- */ #define _PR_LOCK _MD_LOCK #define _PR_UNLOCK _MD_UNLOCK #define _MD_NEW_LOCK (_PR_MD_NEW_LOCK) #define _MD_FREE_LOCK(lock) (DosCloseMutexSem((lock)->mutex)) #define _MD_LOCK(lock) (DosRequestMutexSem((lock)->mutex, SEM_INDEFINITE_WAIT)) #define _MD_TEST_AND_LOCK(lock) (DosRequestMutexSem((lock)->mutex, SEM_INDEFINITE_WAIT),0) #define _MD_UNLOCK (_PR_MD_UNLOCK) /* --- lock and cv waiting --- */ #define _MD_WAIT (_PR_MD_WAIT) #define _MD_WAKEUP_WAITER (_PR_MD_WAKEUP_WAITER) /* --- CVar ------------------- */ #define _MD_WAIT_CV (_PR_MD_WAIT_CV) #define _MD_NEW_CV (_PR_MD_NEW_CV) #define _MD_FREE_CV (_PR_MD_FREE_CV) #define _MD_NOTIFY_CV (_PR_MD_NOTIFY_CV ) #define _MD_NOTIFYALL_CV (_PR_MD_NOTIFYALL_CV) /* XXXMB- the IOQ stuff is certainly not working correctly yet. */ /* extern struct _MDLock _pr_ioq_lock; */ #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() /* --- Initialization stuff --- */ #define _MD_START_INTERRUPTS() #define _MD_STOP_INTERRUPTS() #define _MD_DISABLE_CLOCK_INTERRUPTS() #define _MD_ENABLE_CLOCK_INTERRUPTS() #define _MD_BLOCK_CLOCK_INTERRUPTS() #define _MD_UNBLOCK_CLOCK_INTERRUPTS() #define _MD_EARLY_INIT (_PR_MD_EARLY_INIT) #define _MD_FINAL_INIT() #define _MD_EARLY_CLEANUP() #define _MD_INIT_CPUS() #define _MD_INIT_RUNNING_CPU(cpu) struct PRProcess; struct PRProcessAttr; #define _MD_CREATE_PROCESS _PR_CreateOS2Process extern struct PRProcess * _PR_CreateOS2Process( const char *path, char *const *argv, char *const *envp, const struct PRProcessAttr *attr ); #define _MD_DETACH_PROCESS _PR_DetachOS2Process extern PRStatus _PR_DetachOS2Process(struct PRProcess *process); /* --- Wait for a child process to terminate --- */ #define _MD_WAIT_PROCESS _PR_WaitOS2Process extern PRStatus _PR_WaitOS2Process(struct PRProcess *process, PRInt32 *exitCode); #define _MD_KILL_PROCESS _PR_KillOS2Process extern PRStatus _PR_KillOS2Process(struct PRProcess *process); #define _MD_CLEANUP_BEFORE_EXIT() #define _MD_EXIT (_PR_MD_EXIT) #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ *status = PR_TRUE; \ PR_END_MACRO #define _MD_SWITCH_CONTEXT #define _MD_RESTORE_CONTEXT /* --- Intervals --- */ #define _MD_INTERVAL_INIT (_PR_MD_INTERVAL_INIT) #define _MD_GET_INTERVAL (_PR_MD_GET_INTERVAL) #define _MD_INTERVAL_PER_SEC (_PR_MD_INTERVAL_PER_SEC) #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000) #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000) /* --- Native-Thread Specific Definitions ------------------------------- */ typedef struct __NSPR_TLS { struct PRThread *_pr_thread_last_run; struct PRThread *_pr_currentThread; struct _PRCPU *_pr_currentCPU; } _NSPR_TLS; extern _NSPR_TLS* pThreadLocalStorage; NSPR_API(void) _PR_MD_ENSURE_TLS(void); #define _MD_GET_ATTACHED_THREAD() pThreadLocalStorage->_pr_currentThread extern struct PRThread * _MD_CURRENT_THREAD(void); #define _MD_SET_CURRENT_THREAD(_thread) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_currentThread = (_thread) #define _MD_LAST_THREAD() pThreadLocalStorage->_pr_thread_last_run #define _MD_SET_LAST_THREAD(_thread) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_thread_last_run = (_thread) #define _MD_CURRENT_CPU() pThreadLocalStorage->_pr_currentCPU #define _MD_SET_CURRENT_CPU(_cpu) _PR_MD_ENSURE_TLS(); pThreadLocalStorage->_pr_currentCPU = (_cpu) /* lth. #define _MD_SET_INTSOFF(_val) (_pr_ints_off = (_val)) */ /* lth. #define _MD_GET_INTSOFF() _pr_ints_off */ /* lth. #define _MD_INCREMENT_INTSOFF() (_pr_ints_off++) */ /* lth. #define _MD_DECREMENT_INTSOFF() (_pr_ints_off--) */ /* --- Scheduler stuff --- */ #define LOCK_SCHEDULER() 0 #define UNLOCK_SCHEDULER() 0 #define _PR_LockSched() 0 #define _PR_UnlockSched() 0 /* --- Initialization stuff --- */ #define _MD_INIT_LOCKS() /* --- Stack stuff --- */ #define _MD_INIT_STACK(stack, redzone) #define _MD_CLEAR_STACK(stack) /* --- Memory-mapped files stuff --- */ /* ReadOnly and WriteCopy modes are simulated on OS/2; * ReadWrite mode is not supported. */ struct _MDFileMap { PROffset64 maxExtent; }; extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size); #define _MD_CREATE_FILE_MAP _MD_CreateFileMap extern PRInt32 _MD_GetMemMapAlignment(void); #define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset, PRUint32 len); #define _MD_MEM_MAP _MD_MemMap extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size); #define _MD_MEM_UNMAP _MD_MemUnmap extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap); #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap /* Some stuff for setting up thread contexts */ typedef ULONG DWORD, *PDWORD; /* The following definitions and two structures are new in OS/2 Warp 4.0. */ #ifndef CONTEXT_CONTROL #define CONTEXT_CONTROL 0x00000001 #define CONTEXT_INTEGER 0x00000002 #define CONTEXT_SEGMENTS 0x00000004 #define CONTEXT_FLOATING_POINT 0x00000008 #define CONTEXT_FULL 0x0000000F #pragma pack(2) typedef struct _FPREG { ULONG losig; /* Low 32-bits of the significand. */ ULONG hisig; /* High 32-bits of the significand. */ USHORT signexp; /* Sign and exponent. */ } FPREG; typedef struct _CONTEXTRECORD { ULONG ContextFlags; ULONG ctx_env[7]; FPREG ctx_stack[8]; ULONG ctx_SegGs; /* GS register. */ ULONG ctx_SegFs; /* FS register. */ ULONG ctx_SegEs; /* ES register. */ ULONG ctx_SegDs; /* DS register. */ ULONG ctx_RegEdi; /* EDI register. */ ULONG ctx_RegEsi; /* ESI register. */ ULONG ctx_RegEax; /* EAX register. */ ULONG ctx_RegEbx; /* EBX register. */ ULONG ctx_RegEcx; /* ECX register. */ ULONG ctx_RegEdx; /* EDX register. */ ULONG ctx_RegEbp; /* EBP register. */ ULONG ctx_RegEip; /* EIP register. */ ULONG ctx_SegCs; /* CS register. */ ULONG ctx_EFlags; /* EFLAGS register. */ ULONG ctx_RegEsp; /* ESP register. */ ULONG ctx_SegSs; /* SS register. */ } CONTEXTRECORD, *PCONTEXTRECORD; #pragma pack() #endif extern APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD); /* #define _pr_tid (((PTIB2)_getTIBvalue(offsetof(TIB, tib_ptib2)))->tib2_ultid) #define _pr_current_Thread (_system_tls[_pr_tid-1].__pr_current_thread) */ /* Some simple mappings of Windows API's to OS/2 API's to make our lives a * little bit easier. Only add one here if it is a DIRECT mapping. We are * not emulating anything. Just mapping. */ #define FreeLibrary(x) DosFreeModule((HMODULE)x) #define OutputDebugStringA(x) extern int _MD_os2_get_nonblocking_connect_error(int osfd); #endif /* nspr_os2_defs_h___ */ nspr-4.11/nspr/pr/include/md/_os2_errors.h0000644000000000000000000001122712623070344016610 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_os2_errors_h___ #define nspr_os2_errors_h___ #include "md/_os2.h" #ifndef assert #include #endif NSPR_API(void) _MD_os2_map_default_error(PRInt32 err); #define _PR_MD_MAP_DEFAULT_ERROR _MD_os2_map_default_error NSPR_API(void) _MD_os2_map_opendir_error(PRInt32 err); #define _PR_MD_MAP_OPENDIR_ERROR _MD_os2_map_opendir_error NSPR_API(void) _MD_os2_map_closedir_error(PRInt32 err); #define _PR_MD_MAP_CLOSEDIR_ERROR _MD_os2_map_closedir_error NSPR_API(void) _MD_os2_readdir_error(PRInt32 err); #define _PR_MD_MAP_READDIR_ERROR _MD_os2_readdir_error NSPR_API(void) _MD_os2_map_delete_error(PRInt32 err); #define _PR_MD_MAP_DELETE_ERROR _MD_os2_map_delete_error NSPR_API(void) _MD_os2_map_stat_error(PRInt32 err); #define _PR_MD_MAP_STAT_ERROR _MD_os2_map_stat_error NSPR_API(void) _MD_os2_map_fstat_error(PRInt32 err); #define _PR_MD_MAP_FSTAT_ERROR _MD_os2_map_fstat_error NSPR_API(void) _MD_os2_map_rename_error(PRInt32 err); #define _PR_MD_MAP_RENAME_ERROR _MD_os2_map_rename_error NSPR_API(void) _MD_os2_map_access_error(PRInt32 err); #define _PR_MD_MAP_ACCESS_ERROR _MD_os2_map_access_error NSPR_API(void) _MD_os2_map_mkdir_error(PRInt32 err); #define _PR_MD_MAP_MKDIR_ERROR _MD_os2_map_mkdir_error NSPR_API(void) _MD_os2_map_rmdir_error(PRInt32 err); #define _PR_MD_MAP_RMDIR_ERROR _MD_os2_map_rmdir_error NSPR_API(void) _MD_os2_map_read_error(PRInt32 err); #define _PR_MD_MAP_READ_ERROR _MD_os2_map_read_error NSPR_API(void) _MD_os2_map_transmitfile_error(PRInt32 err); #define _PR_MD_MAP_TRANSMITFILE_ERROR _MD_os2_map_transmitfile_error NSPR_API(void) _MD_os2_map_write_error(PRInt32 err); #define _PR_MD_MAP_WRITE_ERROR _MD_os2_map_write_error NSPR_API(void) _MD_os2_map_lseek_error(PRInt32 err); #define _PR_MD_MAP_LSEEK_ERROR _MD_os2_map_lseek_error NSPR_API(void) _MD_os2_map_fsync_error(PRInt32 err); #define _PR_MD_MAP_FSYNC_ERROR _MD_os2_map_fsync_error NSPR_API(void) _MD_os2_map_close_error(PRInt32 err); #define _PR_MD_MAP_CLOSE_ERROR _MD_os2_map_close_error NSPR_API(void) _MD_os2_map_socket_error(PRInt32 err); #define _PR_MD_MAP_SOCKET_ERROR _MD_os2_map_socket_error NSPR_API(void) _MD_os2_map_recv_error(PRInt32 err); #define _PR_MD_MAP_RECV_ERROR _MD_os2_map_recv_error NSPR_API(void) _MD_os2_map_recvfrom_error(PRInt32 err); #define _PR_MD_MAP_RECVFROM_ERROR _MD_os2_map_recvfrom_error NSPR_API(void) _MD_os2_map_send_error(PRInt32 err); #define _PR_MD_MAP_SEND_ERROR _MD_os2_map_send_error NSPR_API(void) _MD_os2_map_sendto_error(PRInt32 err); #define _PR_MD_MAP_SENDTO_ERROR _MD_os2_map_sendto_error NSPR_API(void) _MD_os2_map_writev_error(int err); #define _PR_MD_MAP_WRITEV_ERROR _MD_os2_map_writev_error NSPR_API(void) _MD_os2_map_accept_error(PRInt32 err); #define _PR_MD_MAP_ACCEPT_ERROR _MD_os2_map_accept_error NSPR_API(void) _MD_os2_map_acceptex_error(PRInt32 err); #define _PR_MD_MAP_ACCEPTEX_ERROR _MD_os2_map_acceptex_error NSPR_API(void) _MD_os2_map_connect_error(PRInt32 err); #define _PR_MD_MAP_CONNECT_ERROR _MD_os2_map_connect_error NSPR_API(void) _MD_os2_map_bind_error(PRInt32 err); #define _PR_MD_MAP_BIND_ERROR _MD_os2_map_bind_error NSPR_API(void) _MD_os2_map_listen_error(PRInt32 err); #define _PR_MD_MAP_LISTEN_ERROR _MD_os2_map_listen_error NSPR_API(void) _MD_os2_map_shutdown_error(PRInt32 err); #define _PR_MD_MAP_SHUTDOWN_ERROR _MD_os2_map_shutdown_error NSPR_API(void) _MD_os2_map_socketpair_error(int err); #define _PR_MD_MAP_SOCKETPAIR_ERROR _MD_os2_map_socketpair_error NSPR_API(void) _MD_os2_map_getsockname_error(PRInt32 err); #define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_os2_map_getsockname_error NSPR_API(void) _MD_os2_map_getpeername_error(PRInt32 err); #define _PR_MD_MAP_GETPEERNAME_ERROR _MD_os2_map_getpeername_error NSPR_API(void) _MD_os2_map_getsockopt_error(PRInt32 err); #define _PR_MD_MAP_GETSOCKOPT_ERROR _MD_os2_map_getsockopt_error NSPR_API(void) _MD_os2_map_setsockopt_error(PRInt32 err); #define _PR_MD_MAP_SETSOCKOPT_ERROR _MD_os2_map_setsockopt_error NSPR_API(void) _MD_os2_map_open_error(PRInt32 err); #define _PR_MD_MAP_OPEN_ERROR _MD_os2_map_open_error NSPR_API(void) _MD_os2_map_gethostname_error(PRInt32 err); #define _PR_MD_MAP_GETHOSTNAME_ERROR _MD_os2_map_gethostname_error NSPR_API(void) _MD_os2_map_select_error(PRInt32 err); #define _PR_MD_MAP_SELECT_ERROR _MD_os2_map_select_error NSPR_API(void) _MD_os2_map_lockf_error(int err); #define _PR_MD_MAP_LOCKF_ERROR _MD_os2_map_lockf_error #endif /* nspr_os2_errors_h___ */ nspr-4.11/nspr/pr/include/md/_osf1.cfg0000644000000000000000000000657712623070344015705 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef OSF1 #define OSF1 #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #ifndef IS_64 #define IS_64 #endif #define PR_AF_INET6 26 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define _PR_POLL_BACKCOMPAT #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_osf1.h0000644000000000000000000001372612623070344015367 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_osf1_defs_h___ #define nspr_osf1_defs_h___ /* * Internal configuration macros */ #define PR_LINKER_ARCH "osf" #define _PR_SI_SYSNAME "OSF" #define _PR_SI_ARCHITECTURE "alpha" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 131072L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #undef HAVE_WEAK_IO_SYMBOLS #undef HAVE_WEAK_MALLOC_SYMBOLS #define HAVE_DLL #define HAVE_BSD_FLOCK #define NEED_TIME_R #define USE_DLFCN #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_LARGE_OFF_T #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #ifdef _PR_INET6 #define _PR_HAVE_INET_NTOP #else #define AF_INET6 26 #ifndef AI_CANONNAME #define AI_CANONNAME 0x00000002 struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; struct addrinfo *ai_next; }; #endif #define AI_V4MAPPED 0x00000010 #define AI_ALL 0x00000008 #define AI_ADDRCONFIG 0x00000020 #endif #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #define USE_SETJMP #include /* * A jmp_buf is actually a struct sigcontext. The sc_sp field of * struct sigcontext is the stack pointer. */ #define _MD_GET_SP(_t) (((struct sigcontext *) (_t)->md.context)->sc_sp) #define PR_NUM_GCREGS _JBLEN #define CONTEXT(_th) ((_th)->md.context) /* ** Initialize a thread context to run "_main()" when started */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (setjmp(CONTEXT(_thread))) { \ (*_main)(); \ } \ _MD_GET_SP(_thread) = (long) ((_sp) - 64); \ _MD_GET_SP(_thread) &= ~15; \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!setjmp(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ longjmp(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures */ struct _MDThread { jmp_buf context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #ifndef _PR_PTHREADS #define _MD_INIT_LOCKS() #endif #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() /* * The following are copied from _sunos.h, _aix.h. This means * some of them should probably be moved into _unixos.h. But * _irix.h seems to be quite different in regard to these macros. */ #define _MD_INTERVAL_USE_GTOD #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) /* The following defines unwrapped versions of select() and poll(). */ #include extern int __select (int, fd_set *, fd_set *, fd_set *, struct timeval *); #define _MD_SELECT __select #include #define _MD_POLL __poll extern int __poll(struct pollfd filedes[], unsigned int nfds, int timeout); /* * Atomic operations */ #ifdef OSF1_HAVE_MACHINE_BUILTINS_H #include #define _PR_HAVE_ATOMIC_OPS #define _MD_INIT_ATOMIC() #define _MD_ATOMIC_INCREMENT(val) (__ATOMIC_INCREMENT_LONG(val) + 1) #define _MD_ATOMIC_ADD(ptr, val) (__ATOMIC_ADD_LONG(ptr, val) + val) #define _MD_ATOMIC_DECREMENT(val) (__ATOMIC_DECREMENT_LONG(val) - 1) #define _MD_ATOMIC_SET(val, newval) __ATOMIC_EXCH_LONG(val, newval) #endif /* OSF1_HAVE_MACHINE_BUILTINS_H */ #endif /* nspr_osf1_defs_h___ */ nspr-4.11/nspr/pr/include/md/_pcos.h0000644000000000000000000000250612623070344015455 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prpcos_h___ #define prpcos_h___ #define PR_DLL_SUFFIX ".dll" #include #define DIRECTORY_SEPARATOR '\\' #define DIRECTORY_SEPARATOR_STR "\\" #define PATH_SEPARATOR ';' /* ** Routines for processing command line arguments */ PR_BEGIN_EXTERN_C #ifndef XP_OS2 extern char *optarg; extern int optind; extern int getopt(int argc, char **argv, char *spec); #endif PR_END_EXTERN_C /* ** Definitions of directory structures amd functions ** These definitions are from: ** */ #ifdef XP_OS2 #include #endif #include #include #include /* O_BINARY */ #ifdef OS2 extern PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen); #define _MD_GETHOSTNAME _MD_OS2GetHostName #else extern PRStatus _MD_WindowsGetHostName(char *name, PRUint32 namelen); #define _MD_GETHOSTNAME _MD_WindowsGetHostName extern PRStatus _MD_WindowsGetSysInfo(PRSysInfo cmd, char *name, PRUint32 namelen); #define _MD_GETSYSINFO _MD_WindowsGetSysInfo #endif #endif /* prpcos_h___ */ nspr-4.11/nspr/pr/include/md/_pth.h0000644000000000000000000002532312623070344015306 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_pth_defs_h_ #define nspr_pth_defs_h_ /* ** Appropriate definitions of entry points not used in a pthreads world */ #define _PR_MD_BLOCK_CLOCK_INTERRUPTS() #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS() #define _PR_MD_DISABLE_CLOCK_INTERRUPTS() #define _PR_MD_ENABLE_CLOCK_INTERRUPTS() /* In good standards fashion, the DCE threads (based on posix-4) are not * quite the same as newer posix implementations. These are mostly name * changes and small differences, so macros usually do the trick */ #ifdef _PR_DCETHREADS #define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_create #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_delete #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), a) #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (0 == pthread_mutex_trylock(&(m))) #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_create #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), a) #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_delete /* Notes about differences between DCE threads and pthreads 10: * 1. pthread_mutex_trylock returns 1 when it locks the mutex * 0 when it does not. The latest pthreads has a set of errno-like * return values. * 2. return values from pthread_cond_timedwait are different. * * * */ #elif defined(BSDI) /* * Mutex and condition attributes are not supported. The attr * argument to pthread_mutex_init() and pthread_cond_init() must * be passed as NULL. * * The memset calls in _PT_PTHREAD_MUTEX_INIT and _PT_PTHREAD_COND_INIT * are to work around BSDI's using a single bit to indicate a mutex * or condition variable is initialized. This entire BSDI section * will go away when BSDI releases updated threads libraries for * BSD/OS 3.1 and 4.0. */ #define _PT_PTHREAD_MUTEXATTR_INIT(x) 0 #define _PT_PTHREAD_MUTEXATTR_DESTROY(x) /* */ #define _PT_PTHREAD_MUTEX_INIT(m, a) (memset(&(m), 0, sizeof(m)), \ pthread_mutex_init(&(m), NULL)) #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m))) #define _PT_PTHREAD_CONDATTR_INIT(x) 0 #define _PT_PTHREAD_CONDATTR_DESTROY(x) /* */ #define _PT_PTHREAD_COND_INIT(m, a) (memset(&(m), 0, sizeof(m)), \ pthread_cond_init(&(m), NULL)) #else #define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_init #define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_destroy #define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), &(a)) #if defined(FREEBSD) #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) pt_pthread_mutex_is_locked(&(m)) #else #define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (EBUSY == pthread_mutex_trylock(&(m))) #endif #if defined(ANDROID) /* Conditional attribute init and destroy aren't implemented in bionic. */ #define _PT_PTHREAD_CONDATTR_INIT(x) 0 #define _PT_PTHREAD_CONDATTR_DESTROY(x) /* */ #else #define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_init #define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_destroy #endif #define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), &(a)) #endif /* The pthreads standard does not specify an invalid value for the * pthread_t handle. (0 is usually an invalid pthread identifier * but there are exceptions, for example, DG/UX.) These macros * define a way to set the handle to or compare the handle with an * invalid identifier. These macros are not portable and may be * more of a problem as we adapt to more pthreads implementations. * They are only used in the PRMonitor functions. Do not use them * in new code. * * Unfortunately some of our clients depend on certain properties * of our PRMonitor implementation, preventing us from replacing * it by a portable implementation. * - High-performance servers like the fact that PR_EnterMonitor * only calls PR_Lock and PR_ExitMonitor only calls PR_Unlock. * (A portable implementation would use a PRLock and a PRCondVar * to implement the recursive lock in a monitor and call both * PR_Lock and PR_Unlock in PR_EnterMonitor and PR_ExitMonitor.) * Unfortunately this forces us to read the monitor owner field * without holding a lock. * - One way to make it safe to read the monitor owner field * without holding a lock is to make that field a PRThread* * (one should be able to read a pointer with a single machine * instruction). However, PR_GetCurrentThread calls calloc if * it is called by a thread that was not created by NSPR. The * malloc tracing tools in the Mozilla client use PRMonitor for * locking in their malloc, calloc, and free functions. If * PR_EnterMonitor calls any of these functions, infinite * recursion ensues. */ #if defined(_PR_DCETHREADS) #define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \ memset(&(t), 0, sizeof(pthread_t)) #define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \ (!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t))) #define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st) #elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \ || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \ || defined(HPUX) || defined(FREEBSD) \ || defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \ || defined(NTO) || defined(DARWIN) \ || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN) #define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) (t) = 0 #define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) (t) == 0 #define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st) #else #error "pthreads is not supported for this architecture" #endif #if defined(_PR_DCETHREADS) #define _PT_PTHREAD_ATTR_INIT pthread_attr_create #define _PT_PTHREAD_ATTR_DESTROY pthread_attr_delete #define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, a, f, r) #define _PT_PTHREAD_KEY_CREATE pthread_keycreate #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setsched #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \ (*(s) = pthread_attr_getstacksize(*(a)), 0) #define _PT_PTHREAD_GETSPECIFIC(k, r) \ pthread_getspecific((k), (pthread_addr_t *) &(r)) #elif defined(_PR_PTHREADS) #define _PT_PTHREAD_ATTR_INIT pthread_attr_init #define _PT_PTHREAD_ATTR_DESTROY pthread_attr_destroy #define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, &a, f, r) #define _PT_PTHREAD_KEY_CREATE pthread_key_create #define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setschedpolicy #define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) pthread_attr_getstacksize(a, s) #define _PT_PTHREAD_GETSPECIFIC(k, r) (r) = pthread_getspecific(k) #else #error "Cannot determine pthread strategy" #endif #if defined(_PR_DCETHREADS) #define _PT_PTHREAD_EXPLICIT_SCHED _PT_PTHREAD_DEFAULT_SCHED #endif /* * pthread_mutex_trylock returns different values in DCE threads and * pthreads. */ #if defined(_PR_DCETHREADS) #define PT_TRYLOCK_SUCCESS 1 #define PT_TRYLOCK_BUSY 0 #else #define PT_TRYLOCK_SUCCESS 0 #define PT_TRYLOCK_BUSY EBUSY #endif /* * These platforms don't have sigtimedwait() */ #if (defined(AIX) && !defined(AIX4_3_PLUS)) \ || defined(LINUX) || defined(__GNU__)|| defined(__GLIBC__) \ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \ || defined(BSDI) || defined(UNIXWARE) \ || defined(DARWIN) || defined(SYMBIAN) #define PT_NO_SIGTIMEDWAIT #endif #if defined(OSF1) #define PT_PRIO_MIN PRI_OTHER_MIN #define PT_PRIO_MAX PRI_OTHER_MAX #elif defined(IRIX) #include #define PT_PRIO_MIN PX_PRIO_MIN #define PT_PRIO_MAX PX_PRIO_MAX #elif defined(AIX) #include #include #ifndef PTHREAD_CREATE_JOINABLE #define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED #endif #define PT_PRIO_MIN DEFAULT_PRIO #define PT_PRIO_MAX DEFAULT_PRIO #elif defined(HPUX) #if defined(_PR_DCETHREADS) #define PT_PRIO_MIN PRI_OTHER_MIN #define PT_PRIO_MAX PRI_OTHER_MAX #else /* defined(_PR_DCETHREADS) */ #include #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER) #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER) #endif /* defined(_PR_DCETHREADS) */ #elif defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \ || defined(FREEBSD) || defined(SYMBIAN) #define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER) #define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER) #elif defined(NTO) /* * Neutrino has functions that return the priority range but * they return invalid numbers, so I just hard coded these here * for now. Jerry.Kirk@Nexarecorp.com */ #define PT_PRIO_MIN 0 #define PT_PRIO_MAX 30 #elif defined(SOLARIS) /* * Solaris doesn't seem to have macros for the min/max priorities. * The range of 0-127 is mentioned in the pthread_setschedparam(3T) * man pages, and pthread_setschedparam indeed allows 0-127. However, * pthread_attr_setschedparam does not allow 0; it allows 1-127. */ #define PT_PRIO_MIN 1 #define PT_PRIO_MAX 127 #elif defined(OPENBSD) #define PT_PRIO_MIN 0 #define PT_PRIO_MAX 31 #elif defined(NETBSD) \ || defined(BSDI) || defined(DARWIN) || defined(UNIXWARE) \ || defined(RISCOS) /* XXX */ #define PT_PRIO_MIN 0 #define PT_PRIO_MAX 126 #else #error "pthreads is not supported for this architecture" #endif /* * The _PT_PTHREAD_YIELD function is called from a signal handler. * Needed for garbage collection -- Look at PR_Suspend/PR_Resume * implementation. */ #if defined(_PR_DCETHREADS) #define _PT_PTHREAD_YIELD() pthread_yield() #elif defined(OSF1) /* * sched_yield can't be called from a signal handler. Must use * the _np version. */ #define _PT_PTHREAD_YIELD() pthread_yield_np() #elif defined(AIX) extern int (*_PT_aix_yield_fcn)(); #define _PT_PTHREAD_YIELD() (*_PT_aix_yield_fcn)() #elif defined(IRIX) #include #define _PT_PTHREAD_YIELD() \ PR_BEGIN_MACRO \ struct timespec onemillisec = {0}; \ onemillisec.tv_nsec = 1000000L; \ nanosleep(&onemillisec,NULL); \ PR_END_MACRO #elif defined(HPUX) || defined(SOLARIS) \ || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \ || defined(BSDI) || defined(NTO) || defined(DARWIN) \ || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN) #define _PT_PTHREAD_YIELD() sched_yield() #else #error "Need to define _PT_PTHREAD_YIELD for this platform" #endif #endif /* nspr_pth_defs_h_ */ nspr-4.11/nspr/pr/include/md/_qnx.cfg0000644000000000000000000000324712623070344015632 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef QNX #define QNX #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #undef HAVE_LONG_LONG #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 1 #define PR_ALIGN_OF_INT 1 #define PR_ALIGN_OF_LONG 1 #define PR_ALIGN_OF_INT64 1 #define PR_ALIGN_OF_FLOAT 1 #define PR_ALIGN_OF_DOUBLE 1 #define PR_ALIGN_OF_POINTER 1 #define PR_ALIGN_OF_WORD 1 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_WORDS_PER_DWORD_LOG2 1 #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_qnx.h0000644000000000000000000001070012623070344015312 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_qnx_defs_h___ #define nspr_qnx_defs_h___ /* ** Internal configuration macros */ #define PR_LINKER_ARCH "qnx" #define _PR_SI_SYSNAME "QNX" #define _PR_SI_ARCHITECTURE "x86" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #ifndef HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_IO_SYMBOLS #endif #undef _PR_POLL_AVAILABLE #undef _PR_USE_POLL #define _PR_HAVE_SOCKADDR_LEN #define HAVE_BSD_FLOCK #define _PR_NO_LARGE_FILES #define _PR_STAT_HAS_ONLY_ST_ATIME #include #undef HAVE_STACK_GROWING_UP #undef HAVE_DLL #undef USE_DLFCN #define NEED_STRFTIME_LOCK #define NEED_TIME_R #define _PR_NEED_STRCASECMP #ifndef HAVE_STRERROR #define HAVE_STRERROR #endif #define USE_SETJMP #include #define _SETJMP setjmp #define _LONGJMP longjmp #define _PR_CONTEXT_TYPE jmp_buf #define _PR_NUM_GCREGS _JBLEN #define _MD_GET_SP(_t) (_t)->md.context[7] #define CONTEXT(_th) ((_th)->md.context) /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!_SETJMP(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _LONGJMP(CONTEXT(_thread), 1); \ } /* ** Machine-dependent (MD) data structures. */ struct _MDThread { _PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* ** md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD], fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INTERVAL_USE_GTOD #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) /* ** We wrapped the select() call. _MD_SELECT refers to the built-in, ** unwrapped version. */ #include #include #include #define _MD_SELECT select #define SA_RESTART 0 #endif /* nspr_qnx_defs_h___ */ nspr-4.11/nspr/pr/include/md/_riscos.cfg0000644000000000000000000000652612623070344016331 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef RISCOS #define RISCOS #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_WORDS_PER_DWORD_LOG2 1 #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_riscos.h0000644000000000000000000001047512623070344016017 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_riscos_defs_h___ #define nspr_riscos_defs_h___ /* ** Internal configuration macros */ #define PR_LINKER_ARCH "riscos" #define _PR_SI_SYSNAME "RISCOS" #define _PR_SI_ARCHITECTURE "arm" #define PR_DLL_SUFFIX ".so" #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_HAVE_SOCKADDR_LEN #undef HAVE_BSD_FLOCK #define _PR_NO_LARGE_FILES #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_HAVE_POSIX_SEMAPHORES #include #include #include #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define USE_DLFCN #define NEED_STRFTIME_LOCK #define NEED_TIME_R #define PT_NO_SIGTIMEDWAIT #ifndef HAVE_STRERROR #define HAVE_STRERROR #endif #define USE_SETJMP #include #define _SETJMP setjmp #define _LONGJMP longjmp #define _PR_CONTEXT_TYPE jmp_buf #define _PR_NUM_GCREGS _JBLEN #define _MD_GET_SP(_t) (_t)->md.context[7] #define CONTEXT(_th) ((_th)->md.context) /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!_SETJMP(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _LONGJMP(CONTEXT(_thread), 1); \ } /* ** Machine-dependent (MD) data structures. */ struct _MDThread { _PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* ** md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD], fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif }; #define _PR_IOQ(_cpu) /* */ ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INTERVAL_USE_GTOD #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) /* ** We wrapped the select() call. _MD_SELECT refers to the built-in, ** unwrapped version. */ #include #include #include #define _MD_SELECT select #endif /* nspr_riscos_defs_h___ */ nspr-4.11/nspr/pr/include/md/_scoos.cfg0000644000000000000000000000641212623070344016147 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef SCO #define SCO #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #undef HAVE_LONG_LONG #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define _PR_POLL_BACKCOMPAT #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_scoos.h0000644000000000000000000001052312623070344015635 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_scoos5_defs_h___ #define nspr_scoos5_defs_h___ /* * Internal configuration macros */ #define PR_LINKER_ARCH "scoos5" #define PR_DLL_SUFFIX ".so" #define _PR_SI_SYSNAME "SCO" #define _PR_SI_ARCHITECTURE "x86" #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #undef HAVE_STACK_GROWING_UP #define HAVE_DLL #define USE_DLFCN #if !defined (HAVE_STRERROR) #define HAVE_STRERROR #endif #ifndef HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_IO_SYMBOLS #endif #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_NO_LARGE_FILES #define _PR_STAT_HAS_ONLY_ST_ATIME #define NEED_STRFTIME_LOCK #define NEED_TIME_R #define _PR_RECV_BROKEN /* recv doesn't work on Unix Domain Sockets */ #define USE_SETJMP #ifdef _PR_LOCAL_THREADS_ONLY #include #define _MD_GET_SP(_t) (_t)->md.jb[4] #define PR_NUM_GCREGS _SIGJBLEN #define PR_CONTEXT_TYPE sigjmp_buf #define CONTEXT(_th) ((_th)->md.jb) #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if (sigsetjmp(CONTEXT(_thread),1)) { \ (*_main)(); \ } \ _MD_GET_SP(_thread) = (int) ((_sp) - 64); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!sigsetjmp(CONTEXT(_thread), 1)) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->osErrorCode; \ _MD_SET_CURRENT_THREAD(_thread); \ siglongjmp(CONTEXT(_thread), 1); \ } #endif /* _PR_LOCAL_THREADS_ONLY */ struct _MDThread { jmp_buf jb; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) #define _MD_INTERVAL_USE_GTOD #define _MD_SELECT _select #define _MD_POLL _poll #endif /* nspr_scoos5_defs_h___ */ nspr-4.11/nspr/pr/include/md/_solaris.cfg0000644000000000000000000001143012623070344016471 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef SOLARIS #define SOLARIS #endif #define PR_AF_INET6 26 /* same as AF_INET6 */ #if defined(sparc) || defined(__sparc) #undef IS_LITTLE_ENDIAN #define IS_BIG_ENDIAN 1 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_DOUBLE 8 #if defined(__sparcv9) #define IS_64 #endif #elif defined(__x86_64) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_DOUBLE 8 #define IS_64 #elif defined(i386) || defined(__i386) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_DOUBLE 4 #else #error unknown processor #endif #ifdef IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 8 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 64 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 6 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_POINTER 8 #else /* IS_64 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_POINTER 4 #endif /* IS_64 */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #define HAVE_ALIGNED_DOUBLES #define HAVE_ALIGNED_LONGLONGS #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* ifndef nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_solaris.h0000644000000000000000000003273512623070344016174 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_solaris_defs_h___ #define nspr_solaris_defs_h___ /* * Internal configuration macros */ #define PR_LINKER_ARCH "solaris" #define _PR_SI_SYSNAME "SOLARIS" #ifdef sparc #define _PR_SI_ARCHITECTURE "sparc" #elif defined(__x86_64) #define _PR_SI_ARCHITECTURE "x86-64" #elif defined(i386) #define _PR_SI_ARCHITECTURE "x86" #else #error unknown processor #endif #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE (2*65536L) #define _MD_MMAP_FLAGS MAP_SHARED #undef HAVE_STACK_GROWING_UP #ifndef HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_IO_SYMBOLS #endif #undef HAVE_WEAK_MALLOC_SYMBOLS #define HAVE_DLL #define USE_DLFCN #define NEED_STRFTIME_LOCK /* * Intel x86 has atomic instructions. * * Sparc v8 does not have instructions to efficiently implement * atomic increment/decrement operations. We use the default * atomic routine implementation in pratom.c. * * 64-bit Solaris requires sparc v9, which has atomic instructions. */ #if defined(i386) || defined(IS_64) #define _PR_HAVE_ATOMIC_OPS #endif #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_STAT_HAS_ST_ATIM #ifdef SOLARIS2_5 #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #else #define _PR_HAVE_POSIX_SEMAPHORES #define PR_HAVE_POSIX_NAMED_SHARED_MEMORY #endif #define _PR_HAVE_GETIPNODEBYNAME #define _PR_HAVE_GETIPNODEBYADDR #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #define _PR_ACCEPT_INHERIT_NONBLOCK #ifdef _PR_INET6 #define _PR_HAVE_INET_NTOP #else #define AF_INET6 26 struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; struct addrinfo *ai_next; }; #define AI_CANONNAME 0x0010 #define AI_V4MAPPED 0x0001 #define AI_ALL 0x0002 #define AI_ADDRCONFIG 0x0004 #define _PR_HAVE_MD_SOCKADDR_IN6 /* isomorphic to struct in6_addr on Solaris 8 */ struct _md_in6_addr { union { PRUint8 _S6_u8[16]; PRUint32 _S6_u32[4]; PRUint32 __S6_align; } _S6_un; }; /* isomorphic to struct sockaddr_in6 on Solaris 8 */ struct _md_sockaddr_in6 { PRUint16 sin6_family; PRUint16 sin6_port; PRUint32 sin6_flowinfo; struct _md_in6_addr sin6_addr; PRUint32 sin6_scope_id; PRUint32 __sin6_src_id; }; #endif #if defined(_PR_PTHREADS) #define _PR_HAVE_GETHOST_R #define _PR_HAVE_GETHOST_R_POINTER #endif #include "prinrval.h" #define _MD_INTERVAL_INIT() NSPR_API(PRIntervalTime) _MD_Solaris_GetInterval(void); #define _MD_GET_INTERVAL _MD_Solaris_GetInterval NSPR_API(PRIntervalTime) _MD_Solaris_TicksPerSecond(void); #define _MD_INTERVAL_PER_SEC _MD_Solaris_TicksPerSecond #if defined(_PR_HAVE_ATOMIC_OPS) /* ** Atomic Operations */ #define _MD_INIT_ATOMIC() NSPR_API(PRInt32) _MD_AtomicIncrement(PRInt32 *val); #define _MD_ATOMIC_INCREMENT _MD_AtomicIncrement NSPR_API(PRInt32) _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val); #define _MD_ATOMIC_ADD _MD_AtomicAdd NSPR_API(PRInt32) _MD_AtomicDecrement(PRInt32 *val); #define _MD_ATOMIC_DECREMENT _MD_AtomicDecrement NSPR_API(PRInt32) _MD_AtomicSet(PRInt32 *val, PRInt32 newval); #define _MD_ATOMIC_SET _MD_AtomicSet #endif /* _PR_HAVE_ATOMIC_OPS */ #if defined(_PR_PTHREADS) NSPR_API(void) _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #else /* _PR_PTHREADS */ /* * _PR_LOCAL_THREADS_ONLY implementation on Solaris */ #include "prthread.h" #include #include #include #include /* ** Initialization Related definitions */ NSPR_API(void) _MD_EarlyInit(void); NSPR_API(void) _MD_SolarisInit(); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _MD_SolarisInit #define _MD_INIT_THREAD _MD_InitializeThread #ifdef USE_SETJMP #include #define _PR_CONTEXT_TYPE jmp_buf #ifdef sparc #define _MD_GET_SP(_t) (_t)->md.context[2] #else #define _MD_GET_SP(_t) (_t)->md.context[4] #endif #define PR_NUM_GCREGS _JBLEN #define CONTEXT(_thread) (_thread)->md.context #else /* ! USE_SETJMP */ #ifdef sparc #define _PR_CONTEXT_TYPE ucontext_t #define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gregs[REG_SP] /* ** Sparc's use register windows. the _MD_GetRegisters for the sparc's ** doesn't actually store anything into the argument buffer; instead the ** register windows are homed to the stack. I assume that the stack ** always has room for the registers to spill to... */ #define PR_NUM_GCREGS 0 #else #define _PR_CONTEXT_TYPE unsigned int edi; sigset_t oldMask, blockMask; ucontext_t #define _MD_GET_SP(_t) (_t)->md.context.uc_mcontext.gregs[USP] #define PR_NUM_GCREGS _JBLEN #endif #define CONTEXT(_thread) (&(_thread)->md.context) #endif /* ! USE_SETJMP */ #include /* * Because clock_gettime() on Solaris/x86 always generates a * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(), * which is implemented using gettimeofday(). */ #ifdef i386 #define GETTIME(tt) _pr_solx86_clock_gettime(CLOCK_REALTIME, (tt)) #else #define GETTIME(tt) clock_gettime(CLOCK_REALTIME, (tt)) #endif /* i386 */ #define _MD_SAVE_ERRNO(_thread) (_thread)->md.errcode = errno; #define _MD_RESTORE_ERRNO(_thread) errno = (_thread)->md.errcode; #ifdef sparc #ifdef USE_SETJMP #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ int *context = (_thread)->md.context; \ *status = PR_TRUE; \ (void) setjmp(context); \ (_thread)->md.context[1] = (int) ((_sp) - 64); \ (_thread)->md.context[2] = (int) _main; \ (_thread)->md.context[3] = (int) _main + 4; \ _thread->no_sched = 0; \ PR_END_MACRO #define _MD_SWITCH_CONTEXT(_thread) \ if (!setjmp(CONTEXT(_thread))) { \ _MD_SAVE_ERRNO(_thread) \ _MD_SET_LAST_THREAD(_thread); \ _MD_SET_CURRENT_THREAD(_thread); \ _PR_Schedule(); \ } #define _MD_RESTORE_CONTEXT(_newThread) \ { \ _MD_RESTORE_ERRNO(_newThread) \ _MD_SET_CURRENT_THREAD(_newThread); \ longjmp(CONTEXT(_newThread), 1); \ } #else /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ ucontext_t *uc = CONTEXT(_thread); \ *status = PR_TRUE; \ getcontext(uc); \ uc->uc_stack.ss_sp = (char *) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8); \ uc->uc_stack.ss_size = _thread->stack->stackSize; \ uc->uc_stack.ss_flags = 0; /* ? */ \ uc->uc_mcontext.gregs[REG_SP] = (unsigned int) uc->uc_stack.ss_sp; \ uc->uc_mcontext.gregs[REG_PC] = (unsigned int) _main; \ uc->uc_mcontext.gregs[REG_nPC] = (unsigned int) ((char*)_main)+4; \ uc->uc_flags = UC_ALL; \ _thread->no_sched = 0; \ PR_END_MACRO /* ** Switch away from the current thread context by saving its state and ** calling the thread scheduler. Reload cpu when we come back from the ** context switch because it might have changed. */ #define _MD_SWITCH_CONTEXT(_thread) \ PR_BEGIN_MACRO \ if (!getcontext(CONTEXT(_thread))) { \ _MD_SAVE_ERRNO(_thread); \ _MD_SET_LAST_THREAD(_thread); \ _PR_Schedule(); \ } \ PR_END_MACRO /* ** Restore a thread context that was saved by _MD_SWITCH_CONTEXT or ** initialized by _MD_INIT_CONTEXT. */ #define _MD_RESTORE_CONTEXT(_newThread) \ PR_BEGIN_MACRO \ ucontext_t *uc = CONTEXT(_newThread); \ uc->uc_mcontext.gregs[11] = 1; \ _MD_RESTORE_ERRNO(_newThread); \ _MD_SET_CURRENT_THREAD(_newThread); \ setcontext(uc); \ PR_END_MACRO #endif #else /* x86 solaris */ #ifdef USE_SETJMP #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ *status = PR_TRUE; \ if (setjmp(CONTEXT(_thread))) _main(); \ _MD_GET_SP(_thread) = (int) ((_sp) - 64); \ PR_END_MACRO #define _MD_SWITCH_CONTEXT(_thread) \ if (!setjmp(CONTEXT(_thread))) { \ _MD_SAVE_ERRNO(_thread) \ _PR_Schedule(); \ } #define _MD_RESTORE_CONTEXT(_newThread) \ { \ _MD_RESTORE_ERRNO(_newThread) \ _MD_SET_CURRENT_THREAD(_newThread); \ longjmp(CONTEXT(_newThread), 1); \ } #else /* USE_SETJMP */ #define WINDOWSIZE 0 int getedi(void); void setedi(int); #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ ucontext_t *uc = CONTEXT(_thread); \ *status = PR_TRUE; \ getcontext(uc); \ /* Force sp to be double aligned! */ \ uc->uc_mcontext.gregs[USP] = (int) ((unsigned long)(_sp - WINDOWSIZE - SA(MINFRAME)) & 0xfffffff8); \ uc->uc_mcontext.gregs[PC] = (int) _main; \ (_thread)->no_sched = 0; \ PR_END_MACRO /* getcontext() may return 1, contrary to what the man page says */ #define _MD_SWITCH_CONTEXT(_thread) \ PR_BEGIN_MACRO \ ucontext_t *uc = CONTEXT(_thread); \ PR_ASSERT(_thread->no_sched); \ sigfillset(&((_thread)->md.blockMask)); \ sigprocmask(SIG_BLOCK, &((_thread)->md.blockMask), \ &((_thread)->md.oldMask)); \ (_thread)->md.edi = getedi(); \ if (! getcontext(uc)) { \ sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \ uc->uc_mcontext.gregs[EDI] = (_thread)->md.edi; \ _MD_SAVE_ERRNO(_thread) \ _MD_SET_LAST_THREAD(_thread); \ _PR_Schedule(); \ } else { \ sigprocmask(SIG_SETMASK, &((_thread)->md.oldMask), NULL); \ setedi((_thread)->md.edi); \ PR_ASSERT(_MD_LAST_THREAD() !=_MD_CURRENT_THREAD()); \ _MD_LAST_THREAD()->no_sched = 0; \ } \ PR_END_MACRO /* ** Restore a thread context, saved by _PR_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_newthread) \ PR_BEGIN_MACRO \ ucontext_t *uc = CONTEXT(_newthread); \ uc->uc_mcontext.gregs[EAX] = 1; \ _MD_RESTORE_ERRNO(_newthread) \ _MD_SET_CURRENT_THREAD(_newthread); \ (_newthread)->no_sched = 1; \ setcontext(uc); \ PR_END_MACRO #endif /* USE_SETJMP */ #endif /* sparc */ struct _MDLock { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDThread { _PR_CONTEXT_TYPE context; int errcode; int id; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) extern PRStatus _MD_WAIT(struct PRThread *, PRIntervalTime timeout); extern PRStatus _MD_WAKEUP_WAITER(struct PRThread *); extern void _MD_YIELD(void); extern PRStatus _MD_InitializeThread(PRThread *thread); extern void _MD_SET_PRIORITY(struct _MDThread *thread, PRThreadPriority newPri); extern PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); /* The following defines the unwrapped versions of select() and poll(). */ extern int _select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); #define _MD_SELECT _select #include #include #define _MD_POLL _poll extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout); PR_BEGIN_EXTERN_C /* ** Missing function prototypes */ extern int gethostname (char *name, int namelen); PR_END_EXTERN_C #endif /* _PR_PTHREADS */ extern void _MD_solaris_map_sendfile_error(int err); #endif /* nspr_solaris_defs_h___ */ nspr-4.11/nspr/pr/include/md/_symbian.cfg0000644000000000000000000001121412623070344016457 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef SYMBIAN #define SYMBIAN #endif #define PR_AF_INET6 0x0806 /* same as AF_INET6 */ #ifdef __arm__ #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_DOUBLE 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(__WINS__) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_POINTER 4 #define PR_ALIGN_OF_WORD 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else #error "Unknown CPU architecture" #endif #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #if PR_ALIGN_OF_DOUBLE == 8 #define HAVE_ALIGNED_DOUBLES #endif #if PR_ALIGN_OF_INT64 == 8 #define HAVE_ALIGNED_LONGLONGS #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_symbian.h0000644000000000000000000000224712623070344016155 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_symbian_defs_h___ #define nspr_symbian_defs_h___ #include "prthread.h" /* * Internal configuration macros */ #define _PR_SI_SYSNAME "SYMBIAN" #if defined(__WINS__) #define _PR_SI_ARCHITECTURE "i386" #elif defined(__arm__) #define _PR_SI_ARCHITECTURE "arm" #else #error "Unknown CPU architecture" #endif #define PR_DLL_SUFFIX ".dll" #undef HAVE_STACK_GROWING_UP #ifdef DYNAMIC_LIBRARY #define HAVE_DLL #define USE_DLFCN #endif #define _PR_STAT_HAS_ONLY_ST_ATIME #define _PR_NO_LARGE_FILES #define _PR_HAVE_SYSV_SEMAPHORES #define PR_HAVE_SYSV_NAMED_SHARED_MEMORY #ifndef _PR_PTHREADS #error "Classic NSPR is not implemented" #endif extern void _MD_EarlyInit(void); #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INTERVAL_USE_GTOD /* For writev() */ #include #endif /* nspr_symbian_defs_h___ */ nspr-4.11/nspr/pr/include/md/_unix_errors.h0000644000000000000000000001145312623070344017071 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prunixerrors_h___ #define prunixerrors_h___ #include #include PR_BEGIN_EXTERN_C extern void _MD_unix_map_default_error(int err); #define _PR_MD_MAP_DEFAULT_ERROR _MD_unix_map_default_error extern void _MD_unix_map_opendir_error(int err); #define _PR_MD_MAP_OPENDIR_ERROR _MD_unix_map_opendir_error extern void _MD_unix_map_closedir_error(int err); #define _PR_MD_MAP_CLOSEDIR_ERROR _MD_unix_map_closedir_error extern void _MD_unix_readdir_error(int err); #define _PR_MD_MAP_READDIR_ERROR _MD_unix_readdir_error extern void _MD_unix_map_unlink_error(int err); #define _PR_MD_MAP_UNLINK_ERROR _MD_unix_map_unlink_error extern void _MD_unix_map_stat_error(int err); #define _PR_MD_MAP_STAT_ERROR _MD_unix_map_stat_error extern void _MD_unix_map_fstat_error(int err); #define _PR_MD_MAP_FSTAT_ERROR _MD_unix_map_fstat_error extern void _MD_unix_map_rename_error(int err); #define _PR_MD_MAP_RENAME_ERROR _MD_unix_map_rename_error extern void _MD_unix_map_access_error(int err); #define _PR_MD_MAP_ACCESS_ERROR _MD_unix_map_access_error extern void _MD_unix_map_mkdir_error(int err); #define _PR_MD_MAP_MKDIR_ERROR _MD_unix_map_mkdir_error extern void _MD_unix_map_rmdir_error(int err); #define _PR_MD_MAP_RMDIR_ERROR _MD_unix_map_rmdir_error extern void _MD_unix_map_read_error(int err); #define _PR_MD_MAP_READ_ERROR _MD_unix_map_read_error extern void _MD_unix_map_write_error(int err); #define _PR_MD_MAP_WRITE_ERROR _MD_unix_map_write_error extern void _MD_unix_map_lseek_error(int err); #define _PR_MD_MAP_LSEEK_ERROR _MD_unix_map_lseek_error extern void _MD_unix_map_fsync_error(int err); #define _PR_MD_MAP_FSYNC_ERROR _MD_unix_map_fsync_error extern void _MD_unix_map_close_error(int err); #define _PR_MD_MAP_CLOSE_ERROR _MD_unix_map_close_error extern void _MD_unix_map_socket_error(int err); #define _PR_MD_MAP_SOCKET_ERROR _MD_unix_map_socket_error extern void _MD_unix_map_socketavailable_error(int err); #define _PR_MD_MAP_SOCKETAVAILABLE_ERROR _MD_unix_map_socketavailable_error extern void _MD_unix_map_recv_error(int err); #define _PR_MD_MAP_RECV_ERROR _MD_unix_map_recv_error extern void _MD_unix_map_recvfrom_error(int err); #define _PR_MD_MAP_RECVFROM_ERROR _MD_unix_map_recvfrom_error extern void _MD_unix_map_send_error(int err); #define _PR_MD_MAP_SEND_ERROR _MD_unix_map_send_error extern void _MD_unix_map_sendto_error(int err); #define _PR_MD_MAP_SENDTO_ERROR _MD_unix_map_sendto_error extern void _MD_unix_map_writev_error(int err); #define _PR_MD_MAP_WRITEV_ERROR _MD_unix_map_writev_error extern void _MD_unix_map_accept_error(int err); #define _PR_MD_MAP_ACCEPT_ERROR _MD_unix_map_accept_error extern void _MD_unix_map_connect_error(int err); #define _PR_MD_MAP_CONNECT_ERROR _MD_unix_map_connect_error extern void _MD_unix_map_bind_error(int err); #define _PR_MD_MAP_BIND_ERROR _MD_unix_map_bind_error extern void _MD_unix_map_listen_error(int err); #define _PR_MD_MAP_LISTEN_ERROR _MD_unix_map_listen_error extern void _MD_unix_map_shutdown_error(int err); #define _PR_MD_MAP_SHUTDOWN_ERROR _MD_unix_map_shutdown_error extern void _MD_unix_map_socketpair_error(int err); #define _PR_MD_MAP_SOCKETPAIR_ERROR _MD_unix_map_socketpair_error extern void _MD_unix_map_getsockname_error(int err); #define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_unix_map_getsockname_error extern void _MD_unix_map_getpeername_error(int err); #define _PR_MD_MAP_GETPEERNAME_ERROR _MD_unix_map_getpeername_error extern void _MD_unix_map_getsockopt_error(int err); #define _PR_MD_MAP_GETSOCKOPT_ERROR _MD_unix_map_getsockopt_error extern void _MD_unix_map_setsockopt_error(int err); #define _PR_MD_MAP_SETSOCKOPT_ERROR _MD_unix_map_setsockopt_error extern void _MD_unix_map_open_error(int err); #define _PR_MD_MAP_OPEN_ERROR _MD_unix_map_open_error extern void _MD_unix_map_mmap_error(int err); #define _PR_MD_MAP_MMAP_ERROR _MD_unix_map_mmap_error extern void _MD_unix_map_gethostname_error(int err); #define _PR_MD_MAP_GETHOSTNAME_ERROR _MD_unix_map_gethostname_error extern void _MD_unix_map_select_error(int err); #define _PR_MD_MAP_SELECT_ERROR _MD_unix_map_select_error extern void _MD_unix_map_poll_error(int err); #define _PR_MD_MAP_POLL_ERROR _MD_unix_map_poll_error extern void _MD_unix_map_poll_revents_error(int err); #define _PR_MD_MAP_POLL_REVENTS_ERROR _MD_unix_map_poll_revents_error extern void _MD_unix_map_flock_error(int err); #define _PR_MD_MAP_FLOCK_ERROR _MD_unix_map_flock_error extern void _MD_unix_map_lockf_error(int err); #define _PR_MD_MAP_LOCKF_ERROR _MD_unix_map_lockf_error PR_END_EXTERN_C #endif /* prunixerrors_h___ */ nspr-4.11/nspr/pr/include/md/_unixos.h0000644000000000000000000004767112623070344016052 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prunixos_h___ #define prunixos_h___ /* * If FD_SETSIZE is not defined on the command line, set the default value * before include select.h */ /* * Linux: FD_SETSIZE is defined in /usr/include/sys/select.h and should * not be redefined. */ #if !defined(LINUX) && !defined(__GNU__) && !defined(__GLIBC__) \ && !defined(DARWIN) #ifndef FD_SETSIZE #define FD_SETSIZE 4096 #endif #endif #include #include #include #include #include #include "prio.h" #include "prmem.h" #include "prclist.h" /* * For select(), fd_set, and struct timeval. * * In The Single UNIX(R) Specification, Version 2, * the header file for select() is . * In Version 3, the header file for select() is * changed to . * * fd_set is defined in . Usually * includes , but on some * older systems does not include * , so we include it explicitly. */ #include #include #if defined(AIX) || defined(SYMBIAN) #include #endif #ifndef SYMBIAN #define HAVE_NETINET_TCP_H #endif #define _PR_HAVE_O_APPEND #define PR_DIRECTORY_SEPARATOR '/' #define PR_DIRECTORY_SEPARATOR_STR "/" #define PR_PATH_SEPARATOR ':' #define PR_PATH_SEPARATOR_STR ":" typedef int (*FARPROC)(); /* * intervals at which GLOBAL threads wakeup to check for pending interrupt */ #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 extern PRIntervalTime intr_timeout_ticks; /* * The bit flags for the in_flags and out_flags fields * of _PR_UnixPollDesc */ #ifdef _PR_USE_POLL #define _PR_UNIX_POLL_READ POLLIN #define _PR_UNIX_POLL_WRITE POLLOUT #define _PR_UNIX_POLL_EXCEPT POLLPRI #define _PR_UNIX_POLL_ERR POLLERR #define _PR_UNIX_POLL_NVAL POLLNVAL #define _PR_UNIX_POLL_HUP POLLHUP #else /* _PR_USE_POLL */ #define _PR_UNIX_POLL_READ 0x1 #define _PR_UNIX_POLL_WRITE 0x2 #define _PR_UNIX_POLL_EXCEPT 0x4 #define _PR_UNIX_POLL_ERR 0x8 #define _PR_UNIX_POLL_NVAL 0x10 #define _PR_UNIX_POLL_HUP 0x20 #endif /* _PR_USE_POLL */ typedef struct _PRUnixPollDesc { PRInt32 osfd; PRInt16 in_flags; PRInt16 out_flags; } _PRUnixPollDesc; typedef struct PRPollQueue { PRCList links; /* for linking PRPollQueue's together */ _PRUnixPollDesc *pds; /* array of poll descriptors */ PRUintn npds; /* length of the array */ PRPackedBool on_ioq; /* is this on the async i/o work q? */ PRIntervalTime timeout; /* timeout, in ticks */ struct PRThread *thr; } PRPollQueue; #define _PR_POLLQUEUE_PTR(_qp) \ ((PRPollQueue*) ((char*) (_qp) - offsetof(PRPollQueue,links))) extern PRInt32 _PR_WaitForMultipleFDs( _PRUnixPollDesc *unixpds, PRInt32 pdcnt, PRIntervalTime timeout); extern void _PR_Unblock_IO_Wait(struct PRThread *thr); #if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY) #define _MD_CHECK_FOR_EXIT() #endif extern fd_set _pr_md_read_set, _pr_md_write_set, _pr_md_exception_set; extern PRInt16 _pr_md_read_cnt[], _pr_md_write_cnt[], _pr_md_exception_cnt[]; extern PRInt32 _pr_md_ioq_max_osfd; extern PRUint32 _pr_md_ioq_timeout; struct _MDFileDesc { int osfd; #if defined(LINUX) && defined(_PR_PTHREADS) int tcp_nodelay; /* used by pt_LinuxSendFile */ #endif }; struct _MDDir { DIR *d; }; struct _PRCPU; extern void _MD_unix_init_running_cpu(struct _PRCPU *cpu); /* ** Make a redzone at both ends of the stack segment. Disallow access ** to those pages of memory. It's ok if the mprotect call's don't ** work - it just means that we don't really have a functional ** redzone. */ #include #ifndef PROT_NONE #define PROT_NONE 0x0 #endif #if defined(DEBUG) && !defined(DARWIN) #if !defined(SOLARIS) #include /* for memset() */ #define _MD_INIT_STACK(ts,REDZONE) \ PR_BEGIN_MACRO \ (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_NONE); \ (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\ REDZONE, PROT_NONE); \ /* \ ** Fill stack memory with something that turns into an illegal \ ** pointer value. This will sometimes find runtime references to \ ** uninitialized pointers. We don't do this for solaris because we \ ** can use purify instead. \ */ \ if (_pr_debugStacks) { \ memset(ts->allocBase + REDZONE, 0xf7, ts->stackSize); \ } \ PR_END_MACRO #else /* !SOLARIS */ #define _MD_INIT_STACK(ts,REDZONE) \ PR_BEGIN_MACRO \ (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_NONE); \ (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\ REDZONE, PROT_NONE); \ PR_END_MACRO #endif /* !SOLARIS */ /* * _MD_CLEAR_STACK * Allow access to the redzone pages; the access was turned off in * _MD_INIT_STACK. */ #define _MD_CLEAR_STACK(ts) \ PR_BEGIN_MACRO \ (void) mprotect((void*)ts->seg->vaddr, REDZONE, PROT_READ|PROT_WRITE);\ (void) mprotect((void*) ((char*)ts->seg->vaddr + REDZONE + ts->stackSize),\ REDZONE, PROT_READ|PROT_WRITE); \ PR_END_MACRO #else /* DEBUG */ #define _MD_INIT_STACK(ts,REDZONE) #define _MD_CLEAR_STACK(ts) #endif /* DEBUG */ #if !defined(SOLARIS) #define PR_SET_INTSOFF(newval) #endif /************************************************************************/ extern void _PR_UnixInit(void); extern void _PR_UnixCleanup(void); #define _MD_EARLY_CLEANUP _PR_UnixCleanup /************************************************************************/ struct _MDProcess { pid_t pid; }; struct PRProcess; struct PRProcessAttr; /* Create a new process (fork() + exec()) */ #define _MD_CREATE_PROCESS _MD_CreateUnixProcess extern struct PRProcess * _MD_CreateUnixProcess( const char *path, char *const *argv, char *const *envp, const struct PRProcessAttr *attr ); #define _MD_DETACH_PROCESS _MD_DetachUnixProcess extern PRStatus _MD_DetachUnixProcess(struct PRProcess *process); /* Wait for a child process to terminate */ #define _MD_WAIT_PROCESS _MD_WaitUnixProcess extern PRStatus _MD_WaitUnixProcess(struct PRProcess *process, PRInt32 *exitCode); #define _MD_KILL_PROCESS _MD_KillUnixProcess extern PRStatus _MD_KillUnixProcess(struct PRProcess *process); /************************************************************************/ extern void _MD_EnableClockInterrupts(void); extern void _MD_DisableClockInterrupts(void); #define _MD_START_INTERRUPTS _MD_StartInterrupts #define _MD_STOP_INTERRUPTS _MD_StopInterrupts #define _MD_DISABLE_CLOCK_INTERRUPTS _MD_DisableClockInterrupts #define _MD_ENABLE_CLOCK_INTERRUPTS _MD_EnableClockInterrupts #define _MD_BLOCK_CLOCK_INTERRUPTS _MD_BlockClockInterrupts #define _MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UnblockClockInterrupts /************************************************************************/ extern void _MD_InitCPUS(void); #define _MD_INIT_CPUS _MD_InitCPUS extern void _MD_Wakeup_CPUs(void); #define _MD_WAKEUP_CPUS _MD_Wakeup_CPUs #define _MD_PAUSE_CPU _MD_PauseCPU #if defined(_PR_LOCAL_THREADS_ONLY) || defined(_PR_GLOBAL_THREADS_ONLY) #define _MD_CLEANUP_BEFORE_EXIT() #endif #ifndef IRIX #define _MD_EXIT(status) _exit(status) #endif /************************************************************************/ #define _MD_GET_ENV getenv #define _MD_PUT_ENV putenv /************************************************************************/ #define _MD_INIT_FILEDESC(fd) extern void _MD_MakeNonblock(PRFileDesc *fd); #define _MD_MAKE_NONBLOCK _MD_MakeNonblock /************************************************************************/ #if !defined(_PR_PTHREADS) extern void _MD_InitSegs(void); extern PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr); extern void _MD_FreeSegment(PRSegment *seg); #define _MD_INIT_SEGS _MD_InitSegs #define _MD_ALLOC_SEGMENT _MD_AllocSegment #define _MD_FREE_SEGMENT _MD_FreeSegment #endif /* !defined(_PR_PTHREADS) */ /************************************************************************/ #ifdef _MD_INTERVAL_USE_GTOD extern PRIntervalTime _PR_UNIX_GetInterval(void); extern PRIntervalTime _PR_UNIX_TicksPerSecond(void); #define _MD_INTERVAL_INIT() #define _MD_GET_INTERVAL _PR_UNIX_GetInterval #define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond #endif #ifdef HAVE_CLOCK_MONOTONIC extern PRIntervalTime _PR_UNIX_GetInterval2(void); extern PRIntervalTime _PR_UNIX_TicksPerSecond2(void); #define _MD_INTERVAL_INIT() #define _MD_GET_INTERVAL _PR_UNIX_GetInterval2 #define _MD_INTERVAL_PER_SEC _PR_UNIX_TicksPerSecond2 #endif #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000) #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000) /************************************************************************/ #define _MD_ERRNO() (errno) #define _MD_GET_SOCKET_ERROR() (errno) /************************************************************************/ extern PRInt32 _MD_AvailableSocket(PRInt32 osfd); extern void _MD_StartInterrupts(void); extern void _MD_StopInterrupts(void); extern void _MD_DisableClockInterrupts(void); extern void _MD_BlockClockInterrupts(void); extern void _MD_UnblockClockInterrupts(void); extern void _MD_PauseCPU(PRIntervalTime timeout); extern PRStatus _MD_open_dir(struct _MDDir *, const char *); extern PRInt32 _MD_close_dir(struct _MDDir *); extern char * _MD_read_dir(struct _MDDir *, PRIntn); extern PRInt32 _MD_open(const char *name, PRIntn osflags, PRIntn mode); extern PRInt32 _MD_delete(const char *name); extern PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info); extern PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info); extern PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info); extern PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info); extern PRInt32 _MD_rename(const char *from, const char *to); extern PRInt32 _MD_access(const char *name, PRAccessHow how); extern PRInt32 _MD_mkdir(const char *name, PRIntn mode); extern PRInt32 _MD_rmdir(const char *name); extern PRInt32 _MD_accept_read(PRInt32 sock, PRInt32 *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount); extern PRInt32 _PR_UnixSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout); extern PRStatus _MD_LockFile(PRInt32 osfd); extern PRStatus _MD_TLockFile(PRInt32 osfd); extern PRStatus _MD_UnlockFile(PRInt32 osfd); #define _MD_OPEN_DIR(dir, name) _MD_open_dir(dir, name) #define _MD_CLOSE_DIR(dir) _MD_close_dir(dir) #define _MD_READ_DIR(dir, flags) _MD_read_dir(dir, flags) #define _MD_OPEN(name, osflags, mode) _MD_open(name, osflags, mode) #define _MD_OPEN_FILE(name, osflags, mode) _MD_open(name, osflags, mode) extern PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount); #define _MD_READ(fd,buf,amount) _MD_read(fd,buf,amount) extern PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount); #define _MD_WRITE(fd,buf,amount) _MD_write(fd,buf,amount) #define _MD_DELETE(name) _MD_delete(name) #define _MD_GETFILEINFO(fn, info) _MD_getfileinfo(fn, info) #define _MD_GETFILEINFO64(fn, info) _MD_getfileinfo64(fn, info) #define _MD_GETOPENFILEINFO(fd, info) _MD_getopenfileinfo(fd, info) #define _MD_GETOPENFILEINFO64(fd, info) _MD_getopenfileinfo64(fd, info) #define _MD_RENAME(from, to) _MD_rename(from, to) #define _MD_ACCESS(name, how) _MD_access(name, how) #define _MD_MKDIR(name, mode) _MD_mkdir(name, mode) #define _MD_MAKE_DIR(name, mode) _MD_mkdir(name, mode) #define _MD_RMDIR(name) _MD_rmdir(name) #define _MD_ACCEPT_READ(sock, newSock, raddr, buf, amount) _MD_accept_read(sock, newSock, raddr, buf, amount) #define _MD_LOCKFILE _MD_LockFile #define _MD_TLOCKFILE _MD_TLockFile #define _MD_UNLOCKFILE _MD_UnlockFile extern PRInt32 _MD_socket(int af, int type, int flags); #define _MD_SOCKET _MD_socket extern PRInt32 _MD_connect(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); #define _MD_CONNECT _MD_connect extern PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); #define _MD_ACCEPT _MD_accept extern PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen); #define _MD_BIND _MD_bind extern PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog); #define _MD_LISTEN _MD_listen extern PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how); #define _MD_SHUTDOWN _MD_shutdown extern PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); #define _MD_RECV _MD_recv extern PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); #define _MD_SEND _MD_send extern PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); #define _MD_RECVFROM _MD_recvfrom extern PRInt32 _MD_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); #define _MD_SENDTO _MD_sendto extern PRInt32 _MD_writev(PRFileDesc *fd, const struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); #define _MD_WRITEV _MD_writev extern PRInt32 _MD_socketavailable(PRFileDesc *fd); #define _MD_SOCKETAVAILABLE _MD_socketavailable extern PRInt64 _MD_socketavailable64(PRFileDesc *fd); #define _MD_SOCKETAVAILABLE64 _MD_socketavailable64 #define _MD_PIPEAVAILABLE _MD_socketavailable extern PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout); #define _MD_PR_POLL _MD_pr_poll extern PRInt32 _MD_close(PRInt32 osfd); #define _MD_CLOSE_FILE _MD_close extern PRInt32 _MD_lseek(PRFileDesc*, PRInt32, PRSeekWhence); #define _MD_LSEEK _MD_lseek extern PRInt64 _MD_lseek64(PRFileDesc*, PRInt64, PRSeekWhence); #define _MD_LSEEK64 _MD_lseek64 extern PRInt32 _MD_fsync(PRFileDesc *fd); #define _MD_FSYNC _MD_fsync extern PRInt32 _MD_socketpair(int af, int type, int flags, PRInt32 *osfd); #define _MD_SOCKETPAIR _MD_socketpair #define _MD_CLOSE_SOCKET _MD_close #ifndef NO_NSPR_10_SUPPORT #define _MD_STAT stat #endif extern PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); #define _MD_GETPEERNAME _MD_getpeername extern PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); #define _MD_GETSOCKNAME _MD_getsockname extern PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen); #define _MD_GETSOCKOPT _MD_getsockopt extern PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen); #define _MD_SETSOCKOPT _MD_setsockopt extern PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable); #define _MD_SET_FD_INHERITABLE _MD_set_fd_inheritable extern void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported); #define _MD_INIT_FD_INHERITABLE _MD_init_fd_inheritable extern void _MD_query_fd_inheritable(PRFileDesc *fd); #define _MD_QUERY_FD_INHERITABLE _MD_query_fd_inheritable extern PRStatus _MD_gethostname(char *name, PRUint32 namelen); #define _MD_GETHOSTNAME _MD_gethostname extern PRStatus _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen); #define _MD_GETSYSINFO _MD_getsysinfo extern int _MD_unix_get_nonblocking_connect_error(int osfd); /* Memory-mapped files */ struct _MDFileMap { PRIntn prot; PRIntn flags; PRBool isAnonFM; /* when true, PR_CloseFileMap() must close the related fd */ }; extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size); #define _MD_CREATE_FILE_MAP _MD_CreateFileMap #define _MD_GET_MEM_MAP_ALIGNMENT() PR_GetPageSize() extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset, PRUint32 len); #define _MD_MEM_MAP _MD_MemMap extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size); #define _MD_MEM_UNMAP _MD_MemUnmap extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap); #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap extern PRStatus _MD_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len); #define _MD_SYNC_MEM_MAP _MD_SyncMemMap /* * The standard (XPG4) gettimeofday() (from BSD) takes two arguments. * On some SVR4 derivatives, gettimeofday() takes only one argument. * The GETTIMEOFDAY macro is intended to hide this difference. */ #ifdef HAVE_SVID_GETTOD #define GETTIMEOFDAY(tp) gettimeofday(tp) #else #define GETTIMEOFDAY(tp) gettimeofday((tp), NULL) #endif #if defined(_PR_PTHREADS) && !defined(_PR_POLL_AVAILABLE) #define _PR_NEED_FAKE_POLL #endif #if defined(_PR_NEED_FAKE_POLL) /* * Some platforms don't have poll(), but our pthreads code calls poll(). * As a temporary measure, I implemented a fake poll() using select(). * Here are the struct and macro definitions copied from sys/poll.h * on Solaris 2.5. */ struct pollfd { int fd; short events; short revents; }; /* poll events */ #define POLLIN 0x0001 /* fd is readable */ #define POLLPRI 0x0002 /* high priority info at fd */ #define POLLOUT 0x0004 /* fd is writeable (won't block) */ #define POLLRDNORM 0x0040 /* normal data is readable */ #define POLLWRNORM POLLOUT #define POLLRDBAND 0x0080 /* out-of-band data is readable */ #define POLLWRBAND 0x0100 /* out-of-band data is writeable */ #define POLLNORM POLLRDNORM #define POLLERR 0x0008 /* fd has error condition */ #define POLLHUP 0x0010 /* fd has been hung up on */ #define POLLNVAL 0x0020 /* invalid pollfd entry */ extern int poll(struct pollfd *, unsigned long, int); #endif /* _PR_NEED_FAKE_POLL */ /* ** A vector of the UNIX I/O calls we use. These are here to smooth over ** the rough edges needed for large files. All of NSPR's implmentaions ** go through this vector using syntax of the form ** result = _md_iovector.xxx64(args); */ #if defined(SOLARIS2_5) /* ** Special case: Solaris 2.5.1 ** Solaris starts to have 64-bit file I/O in 2.6. We build on Solaris ** 2.5.1 so that we can use the same binaries on both Solaris 2.5.1 and ** 2.6. At run time, we detect whether 64-bit file I/O is available by ** looking up the 64-bit file function symbols in libc. At build time, ** we need to define the 64-bit file I/O datatypes that are compatible ** with their definitions on Solaris 2.6. */ typedef PRInt64 off64_t; typedef PRUint64 ino64_t; typedef PRInt64 blkcnt64_t; struct stat64 { dev_t st_dev; long st_pad1[3]; ino64_t st_ino; mode_t st_mode; nlink_t st_nlink; uid_t st_uid; gid_t st_gid; dev_t st_rdev; long t_pad2[2]; off64_t st_size; timestruc_t st_atim; timestruc_t st_mtim; timestruc_t st_ctim; long st_blksize; blkcnt64_t st_blocks; char st_fstype[_ST_FSTYPSZ]; long st_pad4[8]; }; typedef struct stat64 _MDStat64; typedef off64_t _MDOff64_t; #elif defined(_PR_HAVE_OFF64_T) typedef struct stat64 _MDStat64; typedef off64_t _MDOff64_t; #elif defined(_PR_HAVE_LARGE_OFF_T) typedef struct stat _MDStat64; typedef off_t _MDOff64_t; #elif defined(_PR_NO_LARGE_FILES) typedef struct stat _MDStat64; typedef PRInt64 _MDOff64_t; #else #error "I don't know yet" #endif typedef PRIntn (*_MD_Fstat64)(PRIntn osfd, _MDStat64 *buf); typedef PRIntn (*_MD_Open64)(const char *path, int oflag, ...); typedef PRIntn (*_MD_Stat64)(const char *path, _MDStat64 *buf); typedef _MDOff64_t (*_MD_Lseek64)(PRIntn osfd, _MDOff64_t, PRIntn whence); typedef void* (*_MD_Mmap64)( void *addr, PRSize len, PRIntn prot, PRIntn flags, PRIntn fildes, _MDOff64_t offset); struct _MD_IOVector { _MD_Open64 _open64; _MD_Mmap64 _mmap64; _MD_Stat64 _stat64; _MD_Fstat64 _fstat64; _MD_Lseek64 _lseek64; }; extern struct _MD_IOVector _md_iovector; #endif /* prunixos_h___ */ nspr-4.11/nspr/pr/include/md/_unixware.cfg0000644000000000000000000000642412623070344016666 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef UNIXWARE #define UNIXWARE #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #undef HAVE_LONG_LONG #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define _PR_POLL_BACKCOMPAT #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_unixware.h0000644000000000000000000001151312623070344016351 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_unixware_defs_h___ #define nspr_unixware_defs_h___ /* * Internal configuration macros */ #define PR_LINKER_ARCH "unixware" #define _PR_SI_SYSNAME "UnixWare" #define _PR_SI_ARCHITECTURE "x86" #define PR_DLL_SUFFIX ".so" #define _PR_VMBASE 0x30000000 #define _PR_STACK_VMBASE 0x50000000 #define _MD_DEFAULT_STACK_SIZE 65536L #define _MD_MMAP_FLAGS MAP_PRIVATE #ifndef HAVE_WEAK_IO_SYMBOLS #define HAVE_WEAK_IO_SYMBOLS #endif #define _PR_POLL_AVAILABLE #define _PR_USE_POLL #define _PR_STAT_HAS_ST_ATIM_UNION #undef HAVE_STACK_GROWING_UP #define HAVE_NETCONFIG #define HAVE_DLL #define USE_DLFCN #define HAVE_STRERROR #define NEED_STRFTIME_LOCK #define NEED_TIME_R #define _PR_NEED_STRCASECMP #define USE_SETJMP #include #define _SETJMP setjmp #define _LONGJMP longjmp #define _PR_CONTEXT_TYPE jmp_buf #define _MD_GET_SP(_t) (_t)->md.context[4] #define _PR_NUM_GCREGS _JBLEN #define CONTEXT(_th) ((_th)->md.context) /* ** Initialize the thread context preparing it to execute _main. */ #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ { \ *status = PR_TRUE; \ if(_SETJMP(CONTEXT(_thread))) (*_main)(); \ _MD_GET_SP(_thread) = (int) ((_sp) - 128); \ } #define _MD_SWITCH_CONTEXT(_thread) \ if (!_SETJMP(CONTEXT(_thread))) { \ (_thread)->md.errcode = errno; \ _PR_Schedule(); \ } /* ** Restore a thread context, saved by _MD_SWITCH_CONTEXT */ #define _MD_RESTORE_CONTEXT(_thread) \ { \ errno = (_thread)->md.errcode; \ _MD_SET_CURRENT_THREAD(_thread); \ _LONGJMP(CONTEXT(_thread), 1); \ } /* Machine-dependent (MD) data structures. * Don't use SVR4 native threads (yet). */ struct _MDThread { _PR_CONTEXT_TYPE context; int id; int errcode; }; struct _MDThreadStack { PRInt8 notused; }; struct _MDLock { PRInt8 notused; }; struct _MDSemaphore { PRInt8 notused; }; struct _MDCVar { PRInt8 notused; }; struct _MDSegment { PRInt8 notused; }; /* * md-specific cpu structure field */ #define _PR_MD_MAX_OSFD FD_SETSIZE struct _MDCPU_Unix { PRCList ioQ; PRUint32 ioq_timeout; PRInt32 ioq_max_osfd; PRInt32 ioq_osfd_cnt; #ifndef _PR_USE_POLL fd_set fd_read_set, fd_write_set, fd_exception_set; PRInt16 fd_read_cnt[_PR_MD_MAX_OSFD],fd_write_cnt[_PR_MD_MAX_OSFD], fd_exception_cnt[_PR_MD_MAX_OSFD]; #else struct pollfd *ioq_pollfds; int ioq_pollfds_size; #endif /* _PR_USE_POLL */ }; #define _PR_IOQ(_cpu) ((_cpu)->md.md_unix.ioQ) #define _PR_ADD_TO_IOQ(_pq, _cpu) PR_APPEND_LINK(&_pq.links, &_PR_IOQ(_cpu)) #define _PR_FD_READ_SET(_cpu) ((_cpu)->md.md_unix.fd_read_set) #define _PR_FD_READ_CNT(_cpu) ((_cpu)->md.md_unix.fd_read_cnt) #define _PR_FD_WRITE_SET(_cpu) ((_cpu)->md.md_unix.fd_write_set) #define _PR_FD_WRITE_CNT(_cpu) ((_cpu)->md.md_unix.fd_write_cnt) #define _PR_FD_EXCEPTION_SET(_cpu) ((_cpu)->md.md_unix.fd_exception_set) #define _PR_FD_EXCEPTION_CNT(_cpu) ((_cpu)->md.md_unix.fd_exception_cnt) #define _PR_IOQ_TIMEOUT(_cpu) ((_cpu)->md.md_unix.ioq_timeout) #define _PR_IOQ_MAX_OSFD(_cpu) ((_cpu)->md.md_unix.ioq_max_osfd) #define _PR_IOQ_OSFD_CNT(_cpu) ((_cpu)->md.md_unix.ioq_osfd_cnt) #define _PR_IOQ_POLLFDS(_cpu) ((_cpu)->md.md_unix.ioq_pollfds) #define _PR_IOQ_POLLFDS_SIZE(_cpu) ((_cpu)->md.md_unix.ioq_pollfds_size) #define _PR_IOQ_MIN_POLLFDS_SIZE(_cpu) 32 struct _MDCPU { struct _MDCPU_Unix md_unix; }; #define _MD_INIT_LOCKS() #define _MD_NEW_LOCK(lock) PR_SUCCESS #define _MD_FREE_LOCK(lock) #define _MD_LOCK(lock) #define _MD_UNLOCK(lock) #define _MD_INIT_IO() #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() /* * The following are copied from _sunos.h, _aix.h. This means * some of them should probably be moved into _unixos.h. But * _irix.h seems to be quite different in regard to these macros. */ #define _MD_INTERVAL_USE_GTOD #define _MD_EARLY_INIT _MD_EarlyInit #define _MD_FINAL_INIT _PR_UnixInit #define _MD_INIT_RUNNING_CPU(cpu) _MD_unix_init_running_cpu(cpu) #define _MD_INIT_THREAD _MD_InitializeThread #define _MD_EXIT_THREAD(thread) #define _MD_SUSPEND_THREAD(thread) #define _MD_RESUME_THREAD(thread) #define _MD_CLEAN_THREAD(_thread) /* * We wrapped the select() call. _MD_SELECT refers to the built-in, * unwrapped version. */ #include #include #include extern int _select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *execptfds, struct timeval *timeout); #define _MD_SELECT _select #define _MD_POLL _poll extern int _poll(struct pollfd *fds, unsigned long nfds, int timeout); #endif /* nspr_unixware_defs_h___ */ nspr-4.11/nspr/pr/include/md/_unixware7.cfg0000644000000000000000000000654312623070344016757 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_UNIX #define XP_UNIX #endif #ifndef UNIXWARE #define UNIXWARE #endif #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #undef HAVE_ALIGNED_DOUBLES #undef HAVE_ALIGNED_LONGLONGS #define PR_AF_INET6 27 /* same as AF_INET6 */ #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_DOUBLE 8 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_BITS_PER_WORD_LOG2 5 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 4 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define _PR_POLL_BACKCOMPAT #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_win32_errors.h0000644000000000000000000001073112623070344017046 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_win32_errors_h___ #define nspr_win32_errors_h___ #include #include #include extern void _MD_win32_map_default_error(PRInt32 err); #define _PR_MD_MAP_DEFAULT_ERROR _MD_win32_map_default_error extern void _MD_win32_map_opendir_error(PRInt32 err); #define _PR_MD_MAP_OPENDIR_ERROR _MD_win32_map_opendir_error extern void _MD_win32_map_closedir_error(PRInt32 err); #define _PR_MD_MAP_CLOSEDIR_ERROR _MD_win32_map_closedir_error extern void _MD_unix_readdir_error(PRInt32 err); #define _PR_MD_MAP_READDIR_ERROR _MD_unix_readdir_error extern void _MD_win32_map_delete_error(PRInt32 err); #define _PR_MD_MAP_DELETE_ERROR _MD_win32_map_delete_error extern void _MD_win32_map_stat_error(PRInt32 err); #define _PR_MD_MAP_STAT_ERROR _MD_win32_map_stat_error extern void _MD_win32_map_fstat_error(PRInt32 err); #define _PR_MD_MAP_FSTAT_ERROR _MD_win32_map_fstat_error extern void _MD_win32_map_rename_error(PRInt32 err); #define _PR_MD_MAP_RENAME_ERROR _MD_win32_map_rename_error extern void _MD_win32_map_access_error(PRInt32 err); #define _PR_MD_MAP_ACCESS_ERROR _MD_win32_map_access_error extern void _MD_win32_map_mkdir_error(PRInt32 err); #define _PR_MD_MAP_MKDIR_ERROR _MD_win32_map_mkdir_error extern void _MD_win32_map_rmdir_error(PRInt32 err); #define _PR_MD_MAP_RMDIR_ERROR _MD_win32_map_rmdir_error extern void _MD_win32_map_read_error(PRInt32 err); #define _PR_MD_MAP_READ_ERROR _MD_win32_map_read_error extern void _MD_win32_map_transmitfile_error(PRInt32 err); #define _PR_MD_MAP_TRANSMITFILE_ERROR _MD_win32_map_transmitfile_error extern void _MD_win32_map_write_error(PRInt32 err); #define _PR_MD_MAP_WRITE_ERROR _MD_win32_map_write_error extern void _MD_win32_map_lseek_error(PRInt32 err); #define _PR_MD_MAP_LSEEK_ERROR _MD_win32_map_lseek_error extern void _MD_win32_map_fsync_error(PRInt32 err); #define _PR_MD_MAP_FSYNC_ERROR _MD_win32_map_fsync_error extern void _MD_win32_map_close_error(PRInt32 err); #define _PR_MD_MAP_CLOSE_ERROR _MD_win32_map_close_error extern void _MD_win32_map_socket_error(PRInt32 err); #define _PR_MD_MAP_SOCKET_ERROR _MD_win32_map_socket_error extern void _MD_win32_map_recv_error(PRInt32 err); #define _PR_MD_MAP_RECV_ERROR _MD_win32_map_recv_error extern void _MD_win32_map_recvfrom_error(PRInt32 err); #define _PR_MD_MAP_RECVFROM_ERROR _MD_win32_map_recvfrom_error extern void _MD_win32_map_send_error(PRInt32 err); #define _PR_MD_MAP_SEND_ERROR _MD_win32_map_send_error extern void _MD_win32_map_sendto_error(PRInt32 err); #define _PR_MD_MAP_SENDTO_ERROR _MD_win32_map_sendto_error extern void _MD_win32_map_accept_error(PRInt32 err); #define _PR_MD_MAP_ACCEPT_ERROR _MD_win32_map_accept_error extern void _MD_win32_map_acceptex_error(PRInt32 err); #define _PR_MD_MAP_ACCEPTEX_ERROR _MD_win32_map_acceptex_error extern PRInt32 _MD_win32_map_connect_error(PRInt32 err); #define _PR_MD_MAP_CONNECT_ERROR _MD_win32_map_connect_error extern void _MD_win32_map_bind_error(PRInt32 err); #define _PR_MD_MAP_BIND_ERROR _MD_win32_map_bind_error extern void _MD_win32_map_listen_error(PRInt32 err); #define _PR_MD_MAP_LISTEN_ERROR _MD_win32_map_listen_error extern void _MD_win32_map_shutdown_error(PRInt32 err); #define _PR_MD_MAP_SHUTDOWN_ERROR _MD_win32_map_shutdown_error extern void _MD_win32_map_getsockname_error(PRInt32 err); #define _PR_MD_MAP_GETSOCKNAME_ERROR _MD_win32_map_getsockname_error extern void _MD_win32_map_getpeername_error(PRInt32 err); #define _PR_MD_MAP_GETPEERNAME_ERROR _MD_win32_map_getpeername_error extern void _MD_win32_map_getsockopt_error(PRInt32 err); #define _PR_MD_MAP_GETSOCKOPT_ERROR _MD_win32_map_getsockopt_error extern void _MD_win32_map_setsockopt_error(PRInt32 err); #define _PR_MD_MAP_SETSOCKOPT_ERROR _MD_win32_map_setsockopt_error extern void _MD_win32_map_open_error(PRInt32 err); #define _PR_MD_MAP_OPEN_ERROR _MD_win32_map_open_error extern void _MD_win32_map_gethostname_error(PRInt32 err); #define _PR_MD_MAP_GETHOSTNAME_ERROR _MD_win32_map_gethostname_error extern void _MD_win32_map_select_error(PRInt32 err); #define _PR_MD_MAP_SELECT_ERROR _MD_win32_map_select_error extern void _MD_win32_map_lockf_error(int err); #define _PR_MD_MAP_LOCKF_ERROR _MD_win32_map_lockf_error #endif /* nspr_win32_errors_h___ */ nspr-4.11/nspr/pr/include/md/_win95.cfg0000644000000000000000000001674012623070344016001 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_PC #define XP_PC #endif #ifndef WIN32 #define WIN32 #endif #ifndef WIN95 #define WIN95 #endif #define PR_AF_INET6 23 /* same as AF_INET6 */ #if defined(_M_IX86) || defined(_X86_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 5 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 4 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 8 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(_M_IA64) || defined(_IA64_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 8 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(_M_ARM) || defined(_ARM_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 5 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 4 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 3 #else /* defined(_M_IX86) || defined(_X86_) */ #error unknown processor architecture #endif /* defined(_M_IX86) || defined(_X86_) */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_win95.h0000644000000000000000000004667312623070344015501 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_win95_defs_h___ #define nspr_win95_defs_h___ #include "prio.h" #include #include #include /* * Internal configuration macros */ #define PR_LINKER_ARCH "win32" #define _PR_SI_SYSNAME "WIN95" #if defined(_M_IX86) || defined(_X86_) #define _PR_SI_ARCHITECTURE "x86" #elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) #define _PR_SI_ARCHITECTURE "x86-64" #elif defined(_M_IA64) || defined(_IA64_) #define _PR_SI_ARCHITECTURE "ia64" #elif defined(_M_ARM) || defined(_ARM_) #define _PR_SI_ARCHITECTURE "arm" #else #error unknown processor architecture #endif #define HAVE_DLL #undef HAVE_THREAD_AFFINITY #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #ifndef _PR_INET6 #define AF_INET6 23 /* newer ws2tcpip.h provides these */ #ifndef AI_CANONNAME #define AI_CANONNAME 0x2 #define AI_NUMERICHOST 0x4 #define NI_NUMERICHOST 0x02 struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; struct addrinfo *ai_next; }; #endif #define _PR_HAVE_MD_SOCKADDR_IN6 /* isomorphic to struct in6_addr on Windows */ struct _md_in6_addr { union { PRUint8 _S6_u8[16]; PRUint16 _S6_u16[8]; } _S6_un; }; /* isomorphic to struct sockaddr_in6 on Windows */ struct _md_sockaddr_in6 { PRInt16 sin6_family; PRUint16 sin6_port; PRUint32 sin6_flowinfo; struct _md_in6_addr sin6_addr; PRUint32 sin6_scope_id; }; #endif #define _PR_HAVE_THREADSAFE_GETHOST #define _PR_HAVE_ATOMIC_OPS #define PR_HAVE_WIN32_NAMED_SHARED_MEMORY /* --- Common User-Thread/Native-Thread Definitions --------------------- */ /* --- Globals --- */ extern struct PRLock *_pr_schedLock; /* --- Typedefs --- */ typedef void (*FiberFunc)(void *); #define PR_NUM_GCREGS 8 typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS]; #define GC_VMBASE 0x40000000 #define GC_VMLIMIT 0x00FFFFFF #define _MD_MAGIC_THREAD 0x22222222 #define _MD_MAGIC_THREADSTACK 0x33333333 #define _MD_MAGIC_SEGMENT 0x44444444 #define _MD_MAGIC_DIR 0x55555555 #define _MD_MAGIC_CV 0x66666666 struct _MDCPU { int unused; }; struct _MDThread { HANDLE blocked_sema; /* Threads block on this when waiting * for IO or CondVar. */ PRBool inCVWaitQueue; /* PR_TRUE if the thread is in the * wait queue of some cond var. * PR_FALSE otherwise. */ HANDLE handle; /* Win32 thread handle */ PRUint32 id; void *sp; /* only valid when suspended */ PRUint32 magic; /* for debugging */ PR_CONTEXT_TYPE gcContext; /* Thread context for GC */ struct PRThread *prev, *next; /* used by the cvar wait queue to * chain the PRThread structures * together */ void (*start)(void *); /* used by _PR_MD_CREATE_THREAD to * pass its 'start' argument to * pr_root. */ }; struct _MDThreadStack { PRUint32 magic; /* for debugging */ }; struct _MDSegment { PRUint32 magic; /* for debugging */ }; #undef PROFILE_LOCKS struct _MDDir { HANDLE d_hdl; WIN32_FIND_DATAA d_entry; PRBool firstEntry; /* Is this the entry returned * by FindFirstFile()? */ PRUint32 magic; /* for debugging */ }; #ifdef MOZ_UNICODE struct _MDDirUTF16 { HANDLE d_hdl; WIN32_FIND_DATAW d_entry; PRBool firstEntry; /* Is this the entry returned * by FindFirstFileW()? */ PRUint32 magic; /* for debugging */ }; #endif /* MOZ_UNICODE */ struct _MDCVar { PRUint32 magic; struct PRThread *waitHead, *waitTail; /* the wait queue: a doubly- * linked list of threads * waiting on this condition * variable */ PRIntn nwait; /* number of threads in the * wait queue */ }; #define _MD_CV_NOTIFIED_LENGTH 6 typedef struct _MDNotified _MDNotified; struct _MDNotified { PRIntn length; /* # of used entries in this * structure */ struct { struct _MDCVar *cv; /* the condition variable notified */ PRIntn times; /* and the number of times notified */ struct PRThread *notifyHead; /* list of threads to wake up */ } cv[_MD_CV_NOTIFIED_LENGTH]; _MDNotified *link; /* link to another of these, or NULL */ }; struct _MDLock { CRITICAL_SECTION mutex; /* this is recursive on NT */ /* * When notifying cvars, there is no point in actually * waking up the threads waiting on the cvars until we've * released the lock. So, we temporarily record the cvars. * When doing an unlock, we'll then wake up the waiting threads. */ struct _MDNotified notified; /* array of conditions notified */ #ifdef PROFILE_LOCKS PRInt32 hitcount; PRInt32 misscount; #endif }; struct _MDSemaphore { HANDLE sem; }; struct _MDFileDesc { PROsfd osfd; /* The osfd can come from one of three spaces: * - For stdin, stdout, and stderr, we are using * the libc file handle (0, 1, 2), which is an int. * - For files and pipes, we are using Win32 HANDLE, * which is a void*. * - For sockets, we are using Winsock SOCKET, which * is a u_int. */ }; struct _MDProcess { HANDLE handle; DWORD id; }; /* --- Misc stuff --- */ #define _MD_GET_SP(thread) (thread)->md.gcContext[6] /* --- NT security stuff --- */ extern void _PR_NT_InitSids(void); extern void _PR_NT_FreeSids(void); extern PRStatus _PR_NT_MakeSecurityDescriptorACL( PRIntn mode, DWORD accessTable[], PSECURITY_DESCRIPTOR *resultSD, PACL *resultACL ); extern void _PR_NT_FreeSecurityDescriptorACL( PSECURITY_DESCRIPTOR pSD, PACL pACL); /* --- IO stuff --- */ #define _MD_OPEN _PR_MD_OPEN #define _MD_OPEN_FILE _PR_MD_OPEN_FILE #define _MD_READ _PR_MD_READ #define _MD_WRITE _PR_MD_WRITE #define _MD_WRITEV _PR_MD_WRITEV #define _MD_LSEEK _PR_MD_LSEEK #define _MD_LSEEK64 _PR_MD_LSEEK64 extern PRInt32 _MD_CloseFile(PROsfd osfd); #define _MD_CLOSE_FILE _MD_CloseFile #define _MD_GETFILEINFO _PR_MD_GETFILEINFO #define _MD_GETFILEINFO64 _PR_MD_GETFILEINFO64 #define _MD_GETOPENFILEINFO _PR_MD_GETOPENFILEINFO #define _MD_GETOPENFILEINFO64 _PR_MD_GETOPENFILEINFO64 #define _MD_STAT _PR_MD_STAT #define _MD_RENAME _PR_MD_RENAME #define _MD_ACCESS _PR_MD_ACCESS #define _MD_DELETE _PR_MD_DELETE #define _MD_MKDIR _PR_MD_MKDIR #define _MD_MAKE_DIR _PR_MD_MAKE_DIR #define _MD_RMDIR _PR_MD_RMDIR #define _MD_LOCKFILE _PR_MD_LOCKFILE #define _MD_TLOCKFILE _PR_MD_TLOCKFILE #define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE /* --- UTF16 IO stuff --- */ #ifdef MOZ_UNICODE #define _MD_OPEN_FILE_UTF16 _PR_MD_OPEN_FILE_UTF16 #define _MD_OPEN_DIR_UTF16 _PR_MD_OPEN_DIR_UTF16 #define _MD_READ_DIR_UTF16 _PR_MD_READ_DIR_UTF16 #define _MD_CLOSE_DIR_UTF16 _PR_MD_CLOSE_DIR_UTF16 #define _MD_GETFILEINFO64_UTF16 _PR_MD_GETFILEINFO64_UTF16 #endif /* MOZ_UNICODE */ /* --- Socket IO stuff --- */ extern void _PR_MD_InitSockets(void); extern void _PR_MD_CleanupSockets(void); #define _MD_EACCES WSAEACCES #define _MD_EADDRINUSE WSAEADDRINUSE #define _MD_EADDRNOTAVAIL WSAEADDRNOTAVAIL #define _MD_EAFNOSUPPORT WSAEAFNOSUPPORT #define _MD_EAGAIN WSAEWOULDBLOCK #define _MD_EALREADY WSAEALREADY #define _MD_EBADF WSAEBADF #define _MD_ECONNREFUSED WSAECONNREFUSED #define _MD_ECONNRESET WSAECONNRESET #define _MD_EFAULT WSAEFAULT #define _MD_EINPROGRESS WSAEINPROGRESS #define _MD_EINTR WSAEINTR #define _MD_EINVAL EINVAL #define _MD_EISCONN WSAEISCONN #define _MD_ENETUNREACH WSAENETUNREACH #define _MD_ENOENT ENOENT #define _MD_ENOTCONN WSAENOTCONN #define _MD_ENOTSOCK WSAENOTSOCK #define _MD_EOPNOTSUPP WSAEOPNOTSUPP #define _MD_EWOULDBLOCK WSAEWOULDBLOCK #define _MD_GET_SOCKET_ERROR() WSAGetLastError() #define _MD_SET_SOCKET_ERROR(_err) WSASetLastError(_err) #define _MD_INIT_FILEDESC(fd) extern void _MD_MakeNonblock(PRFileDesc *f); #define _MD_MAKE_NONBLOCK _MD_MakeNonblock #define _MD_INIT_FD_INHERITABLE _PR_MD_INIT_FD_INHERITABLE #define _MD_QUERY_FD_INHERITABLE _PR_MD_QUERY_FD_INHERITABLE #define _MD_SHUTDOWN _PR_MD_SHUTDOWN #define _MD_LISTEN _PR_MD_LISTEN extern PRInt32 _MD_CloseSocket(PROsfd osfd); #define _MD_CLOSE_SOCKET _MD_CloseSocket #define _MD_SENDTO _PR_MD_SENDTO #define _MD_RECVFROM _PR_MD_RECVFROM #define _MD_SOCKETPAIR(s, type, proto, sv) -1 #define _MD_GETSOCKNAME _PR_MD_GETSOCKNAME #define _MD_GETPEERNAME _PR_MD_GETPEERNAME #define _MD_GETSOCKOPT _PR_MD_GETSOCKOPT #define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT #define _MD_SET_FD_INHERITABLE _PR_MD_SET_FD_INHERITABLE #define _MD_SELECT select #define _MD_FSYNC _PR_MD_FSYNC #define READ_FD 1 #define WRITE_FD 2 #define _MD_INIT_ATOMIC() #if defined(_M_IX86) || defined(_X86_) #define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT #define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD #define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT #else /* non-x86 processors */ #define _MD_ATOMIC_INCREMENT(x) InterlockedIncrement((PLONG)x) #define _MD_ATOMIC_ADD(ptr,val) (InterlockedExchangeAdd((PLONG)ptr, (LONG)val) + val) #define _MD_ATOMIC_DECREMENT(x) InterlockedDecrement((PLONG)x) #endif /* x86 */ #define _MD_ATOMIC_SET(x,y) InterlockedExchange((PLONG)x, (LONG)y) #define _MD_INIT_IO _PR_MD_INIT_IO /* win95 doesn't have async IO */ #define _MD_SOCKET _PR_MD_SOCKET extern PRInt32 _MD_SocketAvailable(PRFileDesc *fd); #define _MD_SOCKETAVAILABLE _MD_SocketAvailable #define _MD_PIPEAVAILABLE _PR_MD_PIPEAVAILABLE #define _MD_CONNECT _PR_MD_CONNECT extern PROsfd _MD_Accept(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, PRIntervalTime timeout); #define _MD_ACCEPT _MD_Accept #define _MD_BIND _PR_MD_BIND #define _MD_RECV _PR_MD_RECV #define _MD_SEND _PR_MD_SEND #define _MD_PR_POLL _PR_MD_PR_POLL /* --- Scheduler stuff --- */ // #define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU #define _MD_PAUSE_CPU /* --- DIR stuff --- */ #define PR_DIRECTORY_SEPARATOR '\\' #define PR_DIRECTORY_SEPARATOR_STR "\\" #define PR_PATH_SEPARATOR ';' #define PR_PATH_SEPARATOR_STR ";" #define _MD_ERRNO() GetLastError() #define _MD_OPEN_DIR _PR_MD_OPEN_DIR #define _MD_CLOSE_DIR _PR_MD_CLOSE_DIR #define _MD_READ_DIR _PR_MD_READ_DIR /* --- Segment stuff --- */ #define _MD_INIT_SEGS() #define _MD_ALLOC_SEGMENT(seg, size, vaddr) 0 #define _MD_FREE_SEGMENT(seg) /* --- Environment Stuff --- */ #define _MD_GET_ENV _PR_MD_GET_ENV #define _MD_PUT_ENV _PR_MD_PUT_ENV /* --- Threading Stuff --- */ #define _MD_DEFAULT_STACK_SIZE 0 #define _MD_INIT_THREAD _PR_MD_INIT_THREAD #define _MD_INIT_ATTACHED_THREAD _PR_MD_INIT_THREAD #define _MD_CREATE_THREAD _PR_MD_CREATE_THREAD #define _MD_YIELD _PR_MD_YIELD #define _MD_SET_PRIORITY _PR_MD_SET_PRIORITY #define _MD_SET_CURRENT_THREAD_NAME _PR_MD_SET_CURRENT_THREAD_NAME #define _MD_CLEAN_THREAD _PR_MD_CLEAN_THREAD #define _MD_SETTHREADAFFINITYMASK _PR_MD_SETTHREADAFFINITYMASK #define _MD_GETTHREADAFFINITYMASK _PR_MD_GETTHREADAFFINITYMASK #define _MD_EXIT_THREAD _PR_MD_EXIT_THREAD #define _MD_EXIT _PR_MD_EXIT #define _MD_SUSPEND_THREAD _PR_MD_SUSPEND_THREAD #define _MD_RESUME_THREAD _PR_MD_RESUME_THREAD #define _MD_SUSPEND_CPU _PR_MD_SUSPEND_CPU #define _MD_RESUME_CPU _PR_MD_RESUME_CPU #define _MD_BEGIN_SUSPEND_ALL() #define _MD_BEGIN_RESUME_ALL() #define _MD_END_SUSPEND_ALL() #define _MD_END_RESUME_ALL() /* --- Lock stuff --- */ #define _PR_LOCK _MD_LOCK #define _PR_UNLOCK _MD_UNLOCK #define _MD_NEW_LOCK _PR_MD_NEW_LOCK #define _MD_FREE_LOCK(lock) DeleteCriticalSection(&((lock)->mutex)) #define _MD_LOCK(lock) EnterCriticalSection(&((lock)->mutex)) #define _MD_TEST_AND_LOCK(lock) (EnterCriticalSection(&((lock)->mutex)),0) #define _MD_UNLOCK _PR_MD_UNLOCK /* --- lock and cv waiting --- */ #define _MD_WAIT _PR_MD_WAIT #define _MD_WAKEUP_WAITER _PR_MD_WAKEUP_WAITER /* --- CVar ------------------- */ #define _MD_WAIT_CV _PR_MD_WAIT_CV #define _MD_NEW_CV _PR_MD_NEW_CV #define _MD_FREE_CV _PR_MD_FREE_CV #define _MD_NOTIFY_CV _PR_MD_NOTIFY_CV #define _MD_NOTIFYALL_CV _PR_MD_NOTIFYALL_CV /* XXXMB- the IOQ stuff is certainly not working correctly yet. */ // extern struct _MDLock _pr_ioq_lock; #define _MD_IOQ_LOCK() #define _MD_IOQ_UNLOCK() /* --- Initialization stuff --- */ #define _MD_START_INTERRUPTS() #define _MD_STOP_INTERRUPTS() #define _MD_DISABLE_CLOCK_INTERRUPTS() #define _MD_ENABLE_CLOCK_INTERRUPTS() #define _MD_BLOCK_CLOCK_INTERRUPTS() #define _MD_UNBLOCK_CLOCK_INTERRUPTS() #define _MD_EARLY_INIT _PR_MD_EARLY_INIT #define _MD_FINAL_INIT() #define _MD_EARLY_CLEANUP() #define _MD_INIT_CPUS() #define _MD_INIT_RUNNING_CPU(cpu) struct PRProcess; struct PRProcessAttr; #define _MD_CREATE_PROCESS _PR_CreateWindowsProcess extern struct PRProcess * _PR_CreateWindowsProcess( const char *path, char *const *argv, char *const *envp, const struct PRProcessAttr *attr ); #define _MD_DETACH_PROCESS _PR_DetachWindowsProcess extern PRStatus _PR_DetachWindowsProcess(struct PRProcess *process); /* --- Wait for a child process to terminate --- */ #define _MD_WAIT_PROCESS _PR_WaitWindowsProcess extern PRStatus _PR_WaitWindowsProcess(struct PRProcess *process, PRInt32 *exitCode); #define _MD_KILL_PROCESS _PR_KillWindowsProcess extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process); #define _MD_CLEANUP_BEFORE_EXIT _PR_MD_CLEANUP_BEFORE_EXIT #define _MD_INIT_CONTEXT(_thread, _sp, _main, status) \ PR_BEGIN_MACRO \ *status = PR_TRUE; \ PR_END_MACRO #define _MD_SWITCH_CONTEXT #define _MD_RESTORE_CONTEXT /* --- Intervals --- */ #define _MD_INTERVAL_INIT _PR_MD_INTERVAL_INIT #define _MD_GET_INTERVAL _PR_MD_GET_INTERVAL #define _MD_INTERVAL_PER_SEC _PR_MD_INTERVAL_PER_SEC #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000) #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000) /* --- Time --- */ extern void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm); #ifdef WINCE extern void _MD_InitTime(void); extern void _MD_CleanupTime(void); #endif /* --- Native-Thread Specific Definitions ------------------------------- */ extern struct PRThread * _MD_CURRENT_THREAD(void); #ifdef _PR_USE_STATIC_TLS extern __declspec(thread) struct PRThread *_pr_currentThread; #define _MD_GET_ATTACHED_THREAD() _pr_currentThread #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread)) extern __declspec(thread) struct PRThread *_pr_thread_last_run; #define _MD_LAST_THREAD() _pr_thread_last_run #define _MD_SET_LAST_THREAD(_thread) (_pr_thread_last_run = 0) extern __declspec(thread) struct _PRCPU *_pr_currentCPU; #define _MD_CURRENT_CPU() _pr_currentCPU #define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = 0) #else /* _PR_USE_STATIC_TLS */ extern DWORD _pr_currentThreadIndex; #define _MD_GET_ATTACHED_THREAD() ((PRThread *) TlsGetValue(_pr_currentThreadIndex)) #define _MD_SET_CURRENT_THREAD(_thread) TlsSetValue(_pr_currentThreadIndex, (_thread)) extern DWORD _pr_lastThreadIndex; #define _MD_LAST_THREAD() ((PRThread *) TlsGetValue(_pr_lastThreadIndex)) #define _MD_SET_LAST_THREAD(_thread) TlsSetValue(_pr_lastThreadIndex, 0) extern DWORD _pr_currentCPUIndex; #define _MD_CURRENT_CPU() ((struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex)) #define _MD_SET_CURRENT_CPU(_cpu) TlsSetValue(_pr_currentCPUIndex, 0) #endif /* _PR_USE_STATIC_TLS */ /* --- Scheduler stuff --- */ #define LOCK_SCHEDULER() 0 #define UNLOCK_SCHEDULER() 0 #define _PR_LockSched() 0 #define _PR_UnlockSched() 0 /* --- Initialization stuff --- */ #define _MD_INIT_LOCKS _PR_MD_INIT_LOCKS /* --- Stack stuff --- */ #define _MD_INIT_STACK(stack, redzone) #define _MD_CLEAR_STACK(stack) /* --- Memory-mapped files stuff --- */ struct _MDFileMap { HANDLE hFileMap; DWORD dwAccess; }; extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size); #define _MD_CREATE_FILE_MAP _MD_CreateFileMap extern PRInt32 _MD_GetMemMapAlignment(void); #define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset, PRUint32 len); #define _MD_MEM_MAP _MD_MemMap extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size); #define _MD_MEM_UNMAP _MD_MemUnmap extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap); #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap extern PRStatus _MD_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len); #define _MD_SYNC_MEM_MAP _MD_SyncMemMap /* --- Named semaphores stuff --- */ #define _PR_HAVE_NAMED_SEMAPHORES #define _MD_OPEN_SEMAPHORE _PR_MD_OPEN_SEMAPHORE #define _MD_WAIT_SEMAPHORE _PR_MD_WAIT_SEMAPHORE #define _MD_POST_SEMAPHORE _PR_MD_POST_SEMAPHORE #define _MD_CLOSE_SEMAPHORE _PR_MD_CLOSE_SEMAPHORE #define _MD_DELETE_SEMAPHORE(name) PR_SUCCESS /* no op */ #endif /* nspr_win32_defs_h___ */ nspr-4.11/nspr/pr/include/md/_winnt.cfg0000644000000000000000000001436212623070344016163 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_cpucfg___ #define nspr_cpucfg___ #ifndef XP_PC #define XP_PC #endif #ifndef WIN32 #define WIN32 #endif #ifndef WINNT #define WINNT #endif #define PR_AF_INET6 23 /* same as AF_INET6 */ #if defined(_M_IX86) || defined(_X86_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 4 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 32 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 5 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 4 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 4 #define PR_ALIGN_OF_POINTER 4 #define PR_BYTES_PER_WORD_LOG2 2 #define PR_BYTES_PER_DWORD_LOG2 2 #elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 8 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #elif defined(_M_IA64) || defined(_IA64_) #define IS_LITTLE_ENDIAN 1 #undef IS_BIG_ENDIAN #define IS_64 #define PR_BYTES_PER_BYTE 1 #define PR_BYTES_PER_SHORT 2 #define PR_BYTES_PER_INT 4 #define PR_BYTES_PER_INT64 8 #define PR_BYTES_PER_LONG 4 #define PR_BYTES_PER_FLOAT 4 #define PR_BYTES_PER_WORD 8 #define PR_BYTES_PER_DWORD 8 #define PR_BYTES_PER_DOUBLE 8 #define PR_BITS_PER_BYTE 8 #define PR_BITS_PER_SHORT 16 #define PR_BITS_PER_INT 32 #define PR_BITS_PER_INT64 64 #define PR_BITS_PER_LONG 32 #define PR_BITS_PER_FLOAT 32 #define PR_BITS_PER_WORD 64 #define PR_BITS_PER_DWORD 64 #define PR_BITS_PER_DOUBLE 64 #define PR_BITS_PER_BYTE_LOG2 3 #define PR_BITS_PER_SHORT_LOG2 4 #define PR_BITS_PER_INT_LOG2 5 #define PR_BITS_PER_INT64_LOG2 6 #define PR_BITS_PER_LONG_LOG2 5 #define PR_BITS_PER_FLOAT_LOG2 5 #define PR_BITS_PER_WORD_LOG2 6 #define PR_BITS_PER_DWORD_LOG2 6 #define PR_BITS_PER_DOUBLE_LOG2 6 #define PR_ALIGN_OF_SHORT 2 #define PR_ALIGN_OF_INT 4 #define PR_ALIGN_OF_LONG 4 #define PR_ALIGN_OF_INT64 8 #define PR_ALIGN_OF_FLOAT 4 #define PR_ALIGN_OF_WORD 8 #define PR_ALIGN_OF_DWORD 8 #define PR_ALIGN_OF_DOUBLE 8 #define PR_ALIGN_OF_POINTER 8 #define PR_BYTES_PER_WORD_LOG2 3 #define PR_BYTES_PER_DWORD_LOG2 3 #else /* defined(_M_IX86) || defined(_X86_) */ #error unknown processor architecture #endif /* defined(_M_IX86) || defined(_X86_) */ #ifndef HAVE_LONG_LONG #define HAVE_LONG_LONG #endif #ifndef NO_NSPR_10_SUPPORT #define BYTES_PER_BYTE PR_BYTES_PER_BYTE #define BYTES_PER_SHORT PR_BYTES_PER_SHORT #define BYTES_PER_INT PR_BYTES_PER_INT #define BYTES_PER_INT64 PR_BYTES_PER_INT64 #define BYTES_PER_LONG PR_BYTES_PER_LONG #define BYTES_PER_FLOAT PR_BYTES_PER_FLOAT #define BYTES_PER_DOUBLE PR_BYTES_PER_DOUBLE #define BYTES_PER_WORD PR_BYTES_PER_WORD #define BYTES_PER_DWORD PR_BYTES_PER_DWORD #define BITS_PER_BYTE PR_BITS_PER_BYTE #define BITS_PER_SHORT PR_BITS_PER_SHORT #define BITS_PER_INT PR_BITS_PER_INT #define BITS_PER_INT64 PR_BITS_PER_INT64 #define BITS_PER_LONG PR_BITS_PER_LONG #define BITS_PER_FLOAT PR_BITS_PER_FLOAT #define BITS_PER_DOUBLE PR_BITS_PER_DOUBLE #define BITS_PER_WORD PR_BITS_PER_WORD #define BITS_PER_BYTE_LOG2 PR_BITS_PER_BYTE_LOG2 #define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2 #define BITS_PER_INT_LOG2 PR_BITS_PER_INT_LOG2 #define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2 #define BITS_PER_LONG_LOG2 PR_BITS_PER_LONG_LOG2 #define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2 #define BITS_PER_DOUBLE_LOG2 PR_BITS_PER_DOUBLE_LOG2 #define BITS_PER_WORD_LOG2 PR_BITS_PER_WORD_LOG2 #define ALIGN_OF_SHORT PR_ALIGN_OF_SHORT #define ALIGN_OF_INT PR_ALIGN_OF_INT #define ALIGN_OF_LONG PR_ALIGN_OF_LONG #define ALIGN_OF_INT64 PR_ALIGN_OF_INT64 #define ALIGN_OF_FLOAT PR_ALIGN_OF_FLOAT #define ALIGN_OF_DOUBLE PR_ALIGN_OF_DOUBLE #define ALIGN_OF_POINTER PR_ALIGN_OF_POINTER #define ALIGN_OF_WORD PR_ALIGN_OF_WORD #define BYTES_PER_WORD_LOG2 PR_BYTES_PER_WORD_LOG2 #define BYTES_PER_DWORD_LOG2 PR_BYTES_PER_DWORD_LOG2 #define WORDS_PER_DWORD_LOG2 PR_WORDS_PER_DWORD_LOG2 #endif /* NO_NSPR_10_SUPPORT */ #endif /* nspr_cpucfg___ */ nspr-4.11/nspr/pr/include/md/_winnt.h0000644000000000000000000005241212623070344015651 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_win32_defs_h___ #define nspr_win32_defs_h___ /* Need to force service-pack 3 extensions to be defined by ** setting _WIN32_WINNT to NT 4.0 for winsock.h, winbase.h, winnt.h. */ #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #elif (_WIN32_WINNT < 0x0400) #undef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif /* _WIN32_WINNT */ #include #include #ifdef __MINGW32__ #include #endif #include #include "prio.h" #include "prclist.h" /* * Internal configuration macros */ #define PR_LINKER_ARCH "win32" #define _PR_SI_SYSNAME "WINNT" #if defined(_M_IX86) || defined(_X86_) #define _PR_SI_ARCHITECTURE "x86" #elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_) #define _PR_SI_ARCHITECTURE "x86-64" #elif defined(_M_IA64) || defined(_IA64_) #define _PR_SI_ARCHITECTURE "ia64" #else #error unknown processor architecture #endif #define HAVE_DLL #define HAVE_CUSTOM_USER_THREADS #define HAVE_THREAD_AFFINITY #define _PR_HAVE_GETADDRINFO #define _PR_INET6_PROBE #ifndef _PR_INET6 #define AF_INET6 23 /* newer ws2tcpip.h provides these */ #ifndef AI_CANONNAME #define AI_CANONNAME 0x2 #define AI_NUMERICHOST 0x4 #define NI_NUMERICHOST 0x02 struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *ai_canonname; struct sockaddr *ai_addr; struct addrinfo *ai_next; }; #endif #define _PR_HAVE_MD_SOCKADDR_IN6 /* isomorphic to struct in6_addr on Windows */ struct _md_in6_addr { union { PRUint8 _S6_u8[16]; PRUint16 _S6_u16[8]; } _S6_un; }; /* isomorphic to struct sockaddr_in6 on Windows */ struct _md_sockaddr_in6 { PRInt16 sin6_family; PRUint16 sin6_port; PRUint32 sin6_flowinfo; struct _md_in6_addr sin6_addr; PRUint32 sin6_scope_id; }; #endif #define _PR_HAVE_THREADSAFE_GETHOST #define _PR_HAVE_ATOMIC_OPS #if defined(_M_IX86) || defined(_X86_) #define _PR_HAVE_ATOMIC_CAS #endif #define PR_HAVE_WIN32_NAMED_SHARED_MEMORY #define _PR_HAVE_PEEK_BUFFER #define _PR_PEEK_BUFFER_MAX (32 * 1024) #define _PR_FD_NEED_EMULATE_MSG_PEEK(fd) \ (!(fd)->secret->nonblocking && (fd)->secret->inheritable != _PR_TRI_TRUE) #define _PR_NEED_SECRET_AF /* --- Common User-Thread/Native-Thread Definitions --------------------- */ /* --- Globals --- */ extern struct PRLock *_pr_schedLock; /* --- Typedefs --- */ typedef void (*FiberFunc)(void *); #define PR_NUM_GCREGS 8 typedef PRInt32 PR_CONTEXT_TYPE[PR_NUM_GCREGS]; #define GC_VMBASE 0x40000000 #define GC_VMLIMIT 0x00FFFFFF #define _MD_MAGIC_THREAD 0x22222222 #define _MD_MAGIC_THREADSTACK 0x33333333 #define _MD_MAGIC_SEGMENT 0x44444444 #define _MD_MAGIC_DIR 0x55555555 struct _MDCPU { int unused; }; enum _MDIOModel { _MD_BlockingIO = 0x38, _MD_MultiWaitIO = 0x49 }; typedef struct _MDOverlapped { OVERLAPPED overlapped; /* Used for async I/O */ enum _MDIOModel ioModel; /* The I/O model to implement * using overlapped I/O. */ union { struct _MDThread *mdThread; /* For blocking I/O, this structure * is embedded in the _MDThread * structure. */ struct { PRCList links; /* for group->io_ready list */ struct PRRecvWait *desc; /* For multiwait I/O, this structure * is associated with a PRRecvWait * structure. */ struct PRWaitGroup *group; struct TimerEvent *timer; DWORD error; } mw; } data; } _MDOverlapped; struct _MDThread { /* The overlapped structure must be first! */ struct _MDOverlapped overlapped; /* Used for async IO for this thread */ void *acceptex_buf; /* Used for AcceptEx() */ TRANSMIT_FILE_BUFFERS *xmit_bufs; /* Used for TransmitFile() */ HANDLE blocked_sema; /* Threads block on this when waiting * for IO or CondVar. */ PRInt32 blocked_io_status; /* Status of the completed IO */ PRInt32 blocked_io_bytes; /* Bytes transferred for completed IO */ PRInt32 blocked_io_error; /* Save error if status is FALSE */ HANDLE handle; PRUint32 id; void *sp; /* only valid when suspended */ PRUint32 magic; /* for debugging */ PR_CONTEXT_TYPE gcContext; /* Thread context for GC */ struct _PRCPU *thr_bound_cpu; /* thread bound to cpu */ PRBool interrupt_disabled;/* thread cannot be interrupted */ HANDLE thr_event; /* For native-threads-only support, thread blocks on this event */ /* The following are used only if this is a fiber */ void *fiber_id; /* flag whether or not this is a fiber*/ FiberFunc fiber_fn; /* main fiber routine */ void *fiber_arg; /* arg to main fiber routine */ PRUint32 fiber_stacksize; /* stacksize for fiber */ PRInt32 fiber_last_error; /* last error for the fiber */ void (*start)(void *); /* used by _PR_MD_CREATE_THREAD to * pass its 'start' argument to * pr_root. */ }; struct _MDThreadStack { PRUint32 magic; /* for debugging */ }; struct _MDSegment { PRUint32 magic; /* for debugging */ }; #undef PROFILE_LOCKS struct _MDLock { CRITICAL_SECTION mutex; /* this is recursive on NT */ #ifdef PROFILE_LOCKS PRInt32 hitcount; PRInt32 misscount; #endif }; struct _MDDir { HANDLE d_hdl; WIN32_FIND_DATA d_entry; PRBool firstEntry; /* Is this the entry returned * by FindFirstFile()? */ PRUint32 magic; /* for debugging */ }; struct _MDCVar { PRUint32 unused; }; struct _MDSemaphore { HANDLE sem; }; struct _MDFileDesc { PROsfd osfd; /* The osfd can come from one of three spaces: * - For stdin, stdout, and stderr, we are using * the libc file handle (0, 1, 2), which is an int. * - For files and pipes, we are using Win32 HANDLE, * which is a void*. * - For sockets, we are using Winsock SOCKET, which * is a u_int. */ PRBool io_model_committed; /* The io model (blocking or nonblocking) * for this osfd has been committed and * cannot be changed. The osfd has been * either associated with the io * completion port or made nonblocking. */ PRBool sync_file_io; /* Use synchronous file I/O on the osfd * (a file handle) */ PRBool accepted_socket; /* Is this an accepted socket (on the * server side)? */ PRNetAddr peer_addr; /* If this is an accepted socket, cache * the peer's address returned by * AcceptEx(). This is to work around * the bug that getpeername() on an * socket accepted by AcceptEx() returns * an all-zero net address. */ }; struct _MDProcess { HANDLE handle; DWORD id; }; /* --- Misc stuff --- */ #define _MD_GET_SP(thread) (thread)->md.gcContext[6] /* --- NT security stuff --- */ extern void _PR_NT_InitSids(void); extern void _PR_NT_FreeSids(void); extern PRStatus _PR_NT_MakeSecurityDescriptorACL( PRIntn mode, DWORD accessTable[], PSECURITY_DESCRIPTOR *resultSD, PACL *resultACL ); extern void _PR_NT_FreeSecurityDescriptorACL( PSECURITY_DESCRIPTOR pSD, PACL pACL); /* --- IO stuff --- */ extern PRInt32 _md_Associate(HANDLE); extern PRInt32 _PR_MD_CLOSE(PROsfd osfd, PRBool socket); #define _MD_OPEN _PR_MD_OPEN #define _MD_OPEN_FILE _PR_MD_OPEN_FILE #define _MD_READ _PR_MD_READ #define _MD_WRITE _PR_MD_WRITE #define _MD_WRITEV _PR_MD_WRITEV #define _MD_LSEEK _PR_MD_LSEEK #define _MD_LSEEK64 _PR_MD_LSEEK64 #define _MD_CLOSE_FILE(f) _PR_MD_CLOSE(f, PR_FALSE) #define _MD_GETFILEINFO _PR_MD_GETFILEINFO #define _MD_GETFILEINFO64 _PR_MD_GETFILEINFO64 #define _MD_GETOPENFILEINFO _PR_MD_GETOPENFILEINFO #define _MD_GETOPENFILEINFO64 _PR_MD_GETOPENFILEINFO64 #define _MD_STAT _PR_MD_STAT #define _MD_RENAME _PR_MD_RENAME #define _MD_ACCESS _PR_MD_ACCESS #define _MD_DELETE _PR_MD_DELETE #define _MD_MKDIR _PR_MD_MKDIR #define _MD_MAKE_DIR _PR_MD_MAKE_DIR #define _MD_RMDIR _PR_MD_RMDIR #define _MD_LOCKFILE _PR_MD_LOCKFILE #define _MD_TLOCKFILE _PR_MD_TLOCKFILE #define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE /* --- Socket IO stuff --- */ #define _MD_GET_SOCKET_ERROR() WSAGetLastError() #define _MD_SET_SOCKET_ERROR(_err) WSASetLastError(_err) #define _MD_INIT_FILEDESC(fd) #define _MD_MAKE_NONBLOCK _PR_MD_MAKE_NONBLOCK #define _MD_INIT_FD_INHERITABLE _PR_MD_INIT_FD_INHERITABLE #define _MD_QUERY_FD_INHERITABLE _PR_MD_QUERY_FD_INHERITABLE #define _MD_SHUTDOWN _PR_MD_SHUTDOWN #define _MD_LISTEN _PR_MD_LISTEN #define _MD_CLOSE_SOCKET(s) _PR_MD_CLOSE(s, PR_TRUE) #define _MD_SENDTO _PR_MD_SENDTO #define _MD_RECVFROM _PR_MD_RECVFROM #define _MD_SOCKETPAIR(s, type, proto, sv) -1 #define _MD_GETSOCKNAME _PR_MD_GETSOCKNAME #define _MD_GETPEERNAME _PR_MD_GETPEERNAME #define _MD_GETSOCKOPT _PR_MD_GETSOCKOPT #define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT #define _MD_SELECT select extern int _PR_NTFiberSafeSelect(int, fd_set *, fd_set *, fd_set *, const struct timeval *); #define _MD_FSYNC _PR_MD_FSYNC #define _MD_SOCKETAVAILABLE _PR_MD_SOCKETAVAILABLE #define _MD_PIPEAVAILABLE _PR_MD_PIPEAVAILABLE #define _MD_SET_FD_INHERITABLE _PR_MD_SET_FD_INHERITABLE #define _MD_INIT_ATOMIC() #if defined(_M_IX86) || defined(_X86_) #define _MD_ATOMIC_INCREMENT _PR_MD_ATOMIC_INCREMENT #define _MD_ATOMIC_ADD _PR_MD_ATOMIC_ADD #define _MD_ATOMIC_DECREMENT _PR_MD_ATOMIC_DECREMENT #else /* non-x86 processors */ #define _MD_ATOMIC_INCREMENT(x) InterlockedIncrement((PLONG)x) #define _MD_ATOMIC_ADD(ptr,val) (InterlockedExchangeAdd((PLONG)ptr, (LONG)val) + val) #define _MD_ATOMIC_DECREMENT(x) InterlockedDecrement((PLONG)x) #endif /* x86 */ #define _MD_ATOMIC_SET(x,y) InterlockedExchange((PLONG)x, (LONG)y) #define _MD_INIT_IO _PR_MD_INIT_IO #define _MD_SOCKET _PR_MD_SOCKET #define _MD_CONNECT _PR_MD_CONNECT #define _MD_ACCEPT(s, a, l, to) \ _MD_FAST_ACCEPT(s, a, l, to, PR_FALSE, NULL, NULL) #define _MD_FAST_ACCEPT(s, a, l, to, fast, cb, cba) \ _PR_MD_FAST_ACCEPT(s, a, l, to, fast, cb, cba) #define _MD_ACCEPT_READ(s, ns, ra, buf, l, t) \ _MD_FAST_ACCEPT_READ(s, ns, ra, buf, l, t, PR_FALSE, NULL, NULL) #define _MD_FAST_ACCEPT_READ(s, ns, ra, buf, l, t, fast, cb, cba) \ _PR_MD_FAST_ACCEPT_READ(s, ns, ra, buf, l, t, fast, cb, cba) #define _MD_UPDATE_ACCEPT_CONTEXT _PR_MD_UPDATE_ACCEPT_CONTEXT #define _MD_BIND _PR_MD_BIND #define _MD_RECV _PR_MD_RECV #define _MD_SEND _PR_MD_SEND #define _MD_SENDFILE _PR_MD_SENDFILE #define _MD_PR_POLL _PR_MD_PR_POLL /* --- Scheduler stuff --- */ #define _MD_PAUSE_CPU _PR_MD_PAUSE_CPU /* --- DIR stuff --- */ #define PR_DIRECTORY_SEPARATOR '\\' #define PR_DIRECTORY_SEPARATOR_STR "\\" #define PR_PATH_SEPARATOR ';' #define PR_PATH_SEPARATOR_STR ";" #define _MD_ERRNO() GetLastError() #define _MD_OPEN_DIR _PR_MD_OPEN_DIR #define _MD_CLOSE_DIR _PR_MD_CLOSE_DIR #define _MD_READ_DIR _PR_MD_READ_DIR /* --- Segment stuff --- */ #define _MD_INIT_SEGS() #define _MD_ALLOC_SEGMENT(seg, size, vaddr) 0 #define _MD_FREE_SEGMENT(seg) /* --- Environment Stuff --- */ #define _MD_GET_ENV _PR_MD_GET_ENV #define _MD_PUT_ENV _PR_MD_PUT_ENV /* --- Threading Stuff --- */ #define _MD_DEFAULT_STACK_SIZE 0 #define _MD_INIT_THREAD _PR_MD_INIT_THREAD #define _MD_INIT_ATTACHED_THREAD _PR_MD_INIT_THREAD #define _MD_CREATE_THREAD _PR_MD_CREATE_THREAD #define _MD_JOIN_THREAD _PR_MD_JOIN_THREAD #define _MD_END_THREAD _PR_MD_END_THREAD #define _MD_YIELD _PR_MD_YIELD #define _MD_SET_PRIORITY _PR_MD_SET_PRIORITY #define _MD_SET_CURRENT_THREAD_NAME _PR_MD_SET_CURRENT_THREAD_NAME #define _MD_CLEAN_THREAD _PR_MD_CLEAN_THREAD #define _MD_SETTHREADAFFINITYMASK _PR_MD_SETTHREADAFFINITYMASK #define _MD_GETTHREADAFFINITYMASK _PR_MD_GETTHREADAFFINITYMASK #define _MD_EXIT_THREAD _PR_MD_EXIT_THREAD #define _MD_SUSPEND_THREAD _PR_MD_SUSPEND_THREAD #define _MD_RESUME_THREAD _PR_MD_RESUME_THREAD #define _MD_SUSPEND_CPU _PR_MD_SUSPEND_CPU #define _MD_RESUME_CPU _PR_MD_RESUME_CPU #define _MD_BEGIN_SUSPEND_ALL() #define _MD_BEGIN_RESUME_ALL() #define _MD_END_SUSPEND_ALL() #define _MD_END_RESUME_ALL() extern void _PR_Unblock_IO_Wait(PRThread *thr); /* --- Lock stuff --- */ #define _MD_NEW_LOCK(lock) (InitializeCriticalSection(&((lock)->mutex)),PR_SUCCESS) #define _MD_FREE_LOCK(lock) DeleteCriticalSection(&((lock)->mutex)) #ifndef PROFILE_LOCKS #define _MD_LOCK(lock) EnterCriticalSection(&((lock)->mutex)) #define _MD_TEST_AND_LOCK(lock) (TryEnterCriticalSection(&((lock)->mutex))== FALSE) #define _MD_UNLOCK(lock) LeaveCriticalSection(&((lock)->mutex)) #else #define _MD_LOCK(lock) \ PR_BEGIN_MACRO \ BOOL rv = TryEnterCriticalSection(&((lock)->mutex)); \ if (rv == TRUE) { \ InterlockedIncrement(&((lock)->hitcount)); \ } else { \ InterlockedIncrement(&((lock)->misscount)); \ EnterCriticalSection(&((lock)->mutex)); \ } \ PR_END_MACRO #define _MD_TEST_AND_LOCK(lock) 0 /* XXXMB */ #define _MD_UNLOCK(lock) LeaveCriticalSection(&((lock)->mutex)) #endif #define _PR_LOCK _MD_LOCK #define _PR_UNLOCK _MD_UNLOCK /* --- lock and cv waiting --- */ #define _MD_WAIT _PR_MD_WAIT #define _MD_WAKEUP_WAITER _PR_MD_WAKEUP_WAITER /* XXXMB- the IOQ stuff is certainly not working correctly yet. */ extern struct _MDLock _pr_ioq_lock; #define _MD_IOQ_LOCK() _MD_LOCK(&_pr_ioq_lock) #define _MD_IOQ_UNLOCK() _MD_UNLOCK(&_pr_ioq_lock) /* --- Initialization stuff --- */ #define _MD_START_INTERRUPTS() #define _MD_STOP_INTERRUPTS() #define _MD_DISABLE_CLOCK_INTERRUPTS() #define _MD_ENABLE_CLOCK_INTERRUPTS() #define _MD_BLOCK_CLOCK_INTERRUPTS() #define _MD_UNBLOCK_CLOCK_INTERRUPTS() #define _MD_EARLY_INIT _PR_MD_EARLY_INIT #define _MD_FINAL_INIT() #define _MD_EARLY_CLEANUP() #define _MD_INIT_CPUS() #define _MD_INIT_RUNNING_CPU(cpu) struct PRProcess; struct PRProcessAttr; /* --- Create a new process --- */ #define _MD_CREATE_PROCESS _PR_CreateWindowsProcess extern struct PRProcess * _PR_CreateWindowsProcess( const char *path, char *const *argv, char *const *envp, const struct PRProcessAttr *attr ); #define _MD_DETACH_PROCESS _PR_DetachWindowsProcess extern PRStatus _PR_DetachWindowsProcess(struct PRProcess *process); /* --- Wait for a child process to terminate --- */ #define _MD_WAIT_PROCESS _PR_WaitWindowsProcess extern PRStatus _PR_WaitWindowsProcess(struct PRProcess *process, PRInt32 *exitCode); #define _MD_KILL_PROCESS _PR_KillWindowsProcess extern PRStatus _PR_KillWindowsProcess(struct PRProcess *process); /* --- User Threading stuff --- */ #define HAVE_FIBERS #define _MD_CREATE_USER_THREAD _PR_MD_CREATE_USER_THREAD #define _MD_CREATE_PRIMORDIAL_USER_THREAD _PR_MD_CREATE_PRIMORDIAL_USER_THREAD #define _MD_CLEANUP_BEFORE_EXIT _PR_MD_CLEANUP_BEFORE_EXIT #define _MD_EXIT _PR_MD_EXIT #define _MD_INIT_CONTEXT _PR_MD_INIT_CONTEXT #define _MD_SWITCH_CONTEXT _PR_MD_SWITCH_CONTEXT #define _MD_RESTORE_CONTEXT _PR_MD_RESTORE_CONTEXT /* --- Intervals --- */ #define _MD_INTERVAL_INIT _PR_MD_INTERVAL_INIT #define _MD_GET_INTERVAL _PR_MD_GET_INTERVAL #define _MD_INTERVAL_PER_SEC _PR_MD_INTERVAL_PER_SEC #define _MD_INTERVAL_PER_MILLISEC() (_PR_MD_INTERVAL_PER_SEC() / 1000) #define _MD_INTERVAL_PER_MICROSEC() (_PR_MD_INTERVAL_PER_SEC() / 1000000) /* --- Time --- */ extern void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm); /* --- Native-Thread Specific Definitions ------------------------------- */ extern BOOL _pr_use_static_tls; extern __declspec(thread) struct PRThread *_pr_current_fiber; extern DWORD _pr_currentFiberIndex; #define _MD_GET_ATTACHED_THREAD() \ (_pr_use_static_tls ? _pr_current_fiber \ : (PRThread *) TlsGetValue(_pr_currentFiberIndex)) extern struct PRThread * _MD_CURRENT_THREAD(void); #define _MD_SET_CURRENT_THREAD(_thread) \ PR_BEGIN_MACRO \ if (_pr_use_static_tls) { \ _pr_current_fiber = (_thread); \ } else { \ TlsSetValue(_pr_currentFiberIndex, (_thread)); \ } \ PR_END_MACRO extern __declspec(thread) struct PRThread *_pr_fiber_last_run; extern DWORD _pr_lastFiberIndex; #define _MD_LAST_THREAD() \ (_pr_use_static_tls ? _pr_fiber_last_run \ : (PRThread *) TlsGetValue(_pr_lastFiberIndex)) #define _MD_SET_LAST_THREAD(_thread) \ PR_BEGIN_MACRO \ if (_pr_use_static_tls) { \ _pr_fiber_last_run = (_thread); \ } else { \ TlsSetValue(_pr_lastFiberIndex, (_thread)); \ } \ PR_END_MACRO extern __declspec(thread) struct _PRCPU *_pr_current_cpu; extern DWORD _pr_currentCPUIndex; #define _MD_CURRENT_CPU() \ (_pr_use_static_tls ? _pr_current_cpu \ : (struct _PRCPU *) TlsGetValue(_pr_currentCPUIndex)) #define _MD_SET_CURRENT_CPU(_cpu) \ PR_BEGIN_MACRO \ if (_pr_use_static_tls) { \ _pr_current_cpu = (_cpu); \ } else { \ TlsSetValue(_pr_currentCPUIndex, (_cpu)); \ } \ PR_END_MACRO extern __declspec(thread) PRUintn _pr_ints_off; extern DWORD _pr_intsOffIndex; #define _MD_GET_INTSOFF() \ (_pr_use_static_tls ? _pr_ints_off \ : (PRUintn) TlsGetValue(_pr_intsOffIndex)) #define _MD_SET_INTSOFF(_val) \ PR_BEGIN_MACRO \ if (_pr_use_static_tls) { \ _pr_ints_off = (_val); \ } else { \ TlsSetValue(_pr_intsOffIndex, (LPVOID) (_val)); \ } \ PR_END_MACRO /* --- Initialization stuff --- */ #define _MD_INIT_LOCKS() /* --- Stack stuff --- */ #define _MD_INIT_STACK(stack, redzone) #define _MD_CLEAR_STACK(stack) /* --- Memory-mapped files stuff --- */ struct _MDFileMap { HANDLE hFileMap; DWORD dwAccess; }; extern PRStatus _MD_CreateFileMap(struct PRFileMap *fmap, PRInt64 size); #define _MD_CREATE_FILE_MAP _MD_CreateFileMap extern PRInt32 _MD_GetMemMapAlignment(void); #define _MD_GET_MEM_MAP_ALIGNMENT _MD_GetMemMapAlignment extern void * _MD_MemMap(struct PRFileMap *fmap, PRInt64 offset, PRUint32 len); #define _MD_MEM_MAP _MD_MemMap extern PRStatus _MD_MemUnmap(void *addr, PRUint32 size); #define _MD_MEM_UNMAP _MD_MemUnmap extern PRStatus _MD_CloseFileMap(struct PRFileMap *fmap); #define _MD_CLOSE_FILE_MAP _MD_CloseFileMap extern PRStatus _MD_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len); #define _MD_SYNC_MEM_MAP _MD_SyncMemMap /* --- Named semaphores stuff --- */ #define _PR_HAVE_NAMED_SEMAPHORES #define _MD_OPEN_SEMAPHORE _PR_MD_OPEN_SEMAPHORE #define _MD_WAIT_SEMAPHORE _PR_MD_WAIT_SEMAPHORE #define _MD_POST_SEMAPHORE _PR_MD_POST_SEMAPHORE #define _MD_CLOSE_SEMAPHORE _PR_MD_CLOSE_SEMAPHORE #define _MD_DELETE_SEMAPHORE(name) PR_SUCCESS /* no op */ #endif /* nspr_win32_defs_h___ */ nspr-4.11/nspr/pr/include/md/prosdep.h0000644000000000000000000000362112623070344016025 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prosdep_h___ #define prosdep_h___ /* ** Get OS specific header information */ #include "prtypes.h" PR_BEGIN_EXTERN_C #ifdef XP_PC #include "md/_pcos.h" #ifdef WINNT #include "md/_winnt.h" #include "md/_win32_errors.h" #elif defined(WIN95) || defined(WINCE) #include "md/_win95.h" #include "md/_win32_errors.h" #elif defined(OS2) #include "md/_os2.h" #include "md/_os2_errors.h" #else #error unknown Windows platform #endif #elif defined(XP_UNIX) #if defined(AIX) #include "md/_aix.h" #elif defined(FREEBSD) #include "md/_freebsd.h" #elif defined(NETBSD) #include "md/_netbsd.h" #elif defined(OPENBSD) #include "md/_openbsd.h" #elif defined(BSDI) #include "md/_bsdi.h" #elif defined(HPUX) #include "md/_hpux.h" #elif defined(IRIX) #include "md/_irix.h" #elif defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) #include "md/_linux.h" #elif defined(OSF1) #include "md/_osf1.h" #elif defined(DARWIN) #include "md/_darwin.h" #elif defined(SOLARIS) #include "md/_solaris.h" #elif defined(SCO) #include "md/_scoos.h" #elif defined(UNIXWARE) #include "md/_unixware.h" #elif defined(DGUX) #include "md/_dgux.h" #elif defined(QNX) #include "md/_qnx.h" #elif defined(NTO) #include "md/_nto.h" #elif defined(RISCOS) #include "md/_riscos.h" #elif defined(SYMBIAN) #include "md/_symbian.h" #else #error unknown Unix flavor #endif #include "md/_unixos.h" #include "md/_unix_errors.h" #elif defined(XP_BEOS) #include "md/_beos.h" #include "md/_unix_errors.h" #else #error "The platform is not BeOS, Unix, Windows, or Mac" #endif #ifdef _PR_PTHREADS #include "md/_pth.h" #endif PR_END_EXTERN_C #endif /* prosdep_h___ */ nspr-4.11/nspr/pr/include/nspr.h0000644000000000000000000000177012623070344014736 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nspr_h___ #define nspr_h___ #include "pratom.h" #include "prbit.h" #include "prclist.h" #include "prcmon.h" #include "prcvar.h" #include "prdtoa.h" #include "prenv.h" #include "prerror.h" #include "prinet.h" #include "prinit.h" #include "prinrval.h" #include "prio.h" #include "pripcsem.h" #include "prlink.h" #include "prlock.h" #include "prlog.h" #include "prlong.h" #include "prmem.h" #include "prmon.h" #include "prmwait.h" #include "prnetdb.h" #include "prprf.h" #include "prproces.h" #include "prrng.h" #include "prrwlock.h" #include "prshm.h" #include "prshma.h" #include "prsystem.h" #include "prthread.h" #include "prtime.h" #include "prtpool.h" #include "prtrace.h" #include "prtypes.h" #endif /* nspr_h___ */ nspr-4.11/nspr/pr/include/obsolete/.cvsignore0000644000000000000000000000001112623070344017402 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/include/obsolete/Makefile.in0000644000000000000000000000122312623070344017455 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk HEADERS = $(wildcard $(srcdir)/*.h) RELEASE_HEADERS = $(HEADERS) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/obsolete include_subdir = obsolete include $(topsrcdir)/config/rules.mk export:: $(RELEASE_HEADERS) $(INSTALL) -m 444 $(RELEASE_HEADERS) $(dist_includedir)/obsolete nspr-4.11/nspr/pr/include/obsolete/pralarm.h0000644000000000000000000001544112623070344017226 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: pralarm.h ** Description: API to periodic alarms. ** ** ** Alarms are defined to invoke some client specified function at ** a time in the future. The notification may be a one time event ** or repeated at a fixed interval. The interval at which the next ** notification takes place may be modified by the client code only ** during the respective notification. ** ** The notification is delivered on a thread that is part of the ** alarm context (PRAlarm). The thread will inherit the priority ** of the Alarm creator. ** ** Any number of periodic alarms (PRAlarmID) may be created within ** the context of a single alarm (PRAlarm). The notifications will be ** scheduled as close to the desired time as possible. ** ** Repeating periodic notifies are expected to run at a fixed rate. ** That rate is expressed as some number of notifies per period where ** the period is much larger than a PRIntervalTime (see prinrval.h). */ #if !defined(pralarm_h) #define pralarm_h #include "prtypes.h" #include "prinrval.h" PR_BEGIN_EXTERN_C /**********************************************************************/ /************************* TYPES AND CONSTANTS ************************/ /**********************************************************************/ typedef struct PRAlarm PRAlarm; typedef struct PRAlarmID PRAlarmID; typedef PRBool (PR_CALLBACK *PRPeriodicAlarmFn)( PRAlarmID *id, void *clientData, PRUint32 late); /**********************************************************************/ /****************************** FUNCTIONS *****************************/ /**********************************************************************/ /*********************************************************************** ** FUNCTION: PR_CreateAlarm ** DESCRIPTION: ** Create an alarm context. ** INPUTS: void ** OUTPUTS: None ** RETURN: PRAlarm* ** ** SIDE EFFECTS: ** This creates an alarm context, which is an object used for subsequent ** notification creations. It also creates a thread that will be used to ** deliver the notifications that are expected to be defined. The client ** is resposible for destroying the context when appropriate. ** RESTRICTIONS: ** None. ** MEMORY: The object (PRAlarm) and a thread to support notifications. ** ALGORITHM: N/A ***********************************************************************/ NSPR_API(PRAlarm*) PR_CreateAlarm(void); /*********************************************************************** ** FUNCTION: PR_DestroyAlarm ** DESCRIPTION: ** Destroys the context created by PR_CreateAlarm(). ** INPUTS: PRAlarm* ** OUTPUTS: None ** RETURN: PRStatus ** ** SIDE EFFECTS: ** This destroys the context that was created by PR_CreateAlarm(). ** If there are any active alarms (PRAlarmID), they will be cancelled. ** Once that is done, the thread that was used to deliver the alarms ** will be joined. ** RESTRICTIONS: ** None. ** MEMORY: N/A ** ALGORITHM: N/A ***********************************************************************/ NSPR_API(PRStatus) PR_DestroyAlarm(PRAlarm *alarm); /*********************************************************************** ** FUNCTION: PR_SetAlarm ** DESCRIPTION: ** Creates a periodic notifier that is to be delivered to a specified ** function at some fixed interval. ** INPUTS: PRAlarm *alarm Parent alarm context ** PRIntervalTime period Interval over which the notifies ** are delivered. ** PRUint32 rate The rate within the interval that ** the notifies will be delivered. ** PRPeriodicAlarmFn function Entry point where the notifies ** will be delivered. ** OUTPUTS: None ** RETURN: PRAlarmID* Handle to the notifier just created ** or NULL if the request failed. ** ** SIDE EFFECTS: ** A periodic notifier is created. The notifications will be delivered ** by the alarm's internal thread at a fixed interval whose rate is the ** number of interrupts per interval specified. The first notification ** will be delivered as soon as possible, and they will continue until ** the notifier routine indicates that they should cease of the alarm ** context is destroyed (PR_DestroyAlarm). ** RESTRICTIONS: ** None. ** MEMORY: Memory for the notifier object. ** ALGORITHM: The rate at which notifications are delivered are stated ** to be "'rate' notifies per 'interval'". The exact time of ** the notification is computed based on a epoch established ** when the notifier was set. Each notification is delivered ** not ealier than the epoch plus the fixed rate times the ** notification sequence number. Such notifications have the ** potential to be late by not more than 'interval'/'rate'. ** The amount of lateness of one notification is taken into ** account on the next in an attempt to avoid long term slew. ***********************************************************************/ NSPR_API(PRAlarmID*) PR_SetAlarm( PRAlarm *alarm, PRIntervalTime period, PRUint32 rate, PRPeriodicAlarmFn function, void *clientData); /*********************************************************************** ** FUNCTION: PR_ResetAlarm ** DESCRIPTION: ** Resets an existing alarm. ** INPUTS: PRAlarmID *id Identify of the notifier. ** PRIntervalTime period Interval over which the notifies ** are delivered. ** PRUint32 rate The rate within the interval that ** the notifies will be delivered. ** OUTPUTS: None ** RETURN: PRStatus Indication of completion. ** ** SIDE EFFECTS: ** An existing alarm may have its period and rate redefined. The ** additional side effect is that the notifier's epoch is recomputed. ** The first notification delivered by the newly refreshed alarm is ** defined to be 'interval'/'rate' from the time of the reset. ** RESTRICTIONS: ** This function may only be called in the notifier for that alarm. ** MEMORY: N/A. ** ALGORITHM: See PR_SetAlarm(). ***********************************************************************/ NSPR_API(PRStatus) PR_ResetAlarm( PRAlarmID *id, PRIntervalTime period, PRUint32 rate); PR_END_EXTERN_C #endif /* !defined(pralarm_h) */ /* prinrval.h */ nspr-4.11/nspr/pr/include/obsolete/probslet.h0000644000000000000000000001301212623070344017412 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** A collection of things thought to be obsolete */ #if defined(PROBSLET_H) #else #define PROBSLET_H #include "prio.h" #include "private/pprio.h" /* for PROsfd */ PR_BEGIN_EXTERN_C /* ** Yield the current thread. The proper function to use in place of ** PR_Yield() is PR_Sleep() with an argument of PR_INTERVAL_NO_WAIT. */ NSPR_API(PRStatus) PR_Yield(void); /************************************************************************/ /************* The following definitions are for select *****************/ /************************************************************************/ /* ** The following is obsolete and will be deleted in the next release! ** These are provided for compatibility, but are GUARANTEED to be slow. ** ** Override PR_MAX_SELECT_DESC if you need more space in the select set. */ #ifndef PR_MAX_SELECT_DESC #define PR_MAX_SELECT_DESC 1024 #endif typedef struct PR_fd_set { PRUint32 hsize; PRFileDesc *harray[PR_MAX_SELECT_DESC]; PRUint32 nsize; PROsfd narray[PR_MAX_SELECT_DESC]; } PR_fd_set; /* ************************************************************************* ** FUNCTION: PR_Select ** DESCRIPTION: ** ** The call returns as soon as I/O is ready on one or more of the underlying ** file/socket descriptors or an exceptional condition is pending. A count of the ** number of ready descriptors is returned unless a timeout occurs in which case ** zero is returned. On return, PR_Select replaces the given descriptor sets with ** subsets consisting of those descriptors that are ready for the requested condition. ** The total number of ready descriptors in all the sets is the return value. ** ** INPUTS: ** PRInt32 num ** This argument is unused but is provided for select(unix) interface ** compatability. All input PR_fd_set arguments are self-describing ** with its own maximum number of elements in the set. ** ** PR_fd_set *readfds ** A set describing the io descriptors for which ready for reading ** condition is of interest. ** ** PR_fd_set *writefds ** A set describing the io descriptors for which ready for writing ** condition is of interest. ** ** PR_fd_set *exceptfds ** A set describing the io descriptors for which exception pending ** condition is of interest. ** ** Any of the above readfds, writefds or exceptfds may be given as NULL ** pointers if no descriptors are of interest for that particular condition. ** ** PRIntervalTime timeout ** Amount of time the call will block waiting for I/O to become ready. ** If this time expires without any I/O becoming ready, the result will ** be zero. ** ** OUTPUTS: ** PR_fd_set *readfds ** A set describing the io descriptors which are ready for reading. ** ** PR_fd_set *writefds ** A set describing the io descriptors which are ready for writing. ** ** PR_fd_set *exceptfds ** A set describing the io descriptors which have pending exception. ** ** RETURN:PRInt32 ** Number of io descriptors with asked for conditions or zero if the function ** timed out or -1 on failure. The reason for the failure is obtained by ** calling PR_GetError(). ** XXX can we implement this on windoze and mac? ************************************************************************** */ NSPR_API(PRInt32) PR_Select( PRInt32 num, PR_fd_set *readfds, PR_fd_set *writefds, PR_fd_set *exceptfds, PRIntervalTime timeout); /* ** The following are not thread safe for two threads operating on them at the ** same time. ** ** The following routines are provided for manipulating io descriptor sets. ** PR_FD_ZERO(&fdset) initializes a descriptor set fdset to the null set. ** PR_FD_SET(fd, &fdset) includes a particular file descriptor fd in fdset. ** PR_FD_CLR(fd, &fdset) removes a file descriptor fd from fdset. ** PR_FD_ISSET(fd, &fdset) is nonzero if file descriptor fd is a member of ** fdset, zero otherwise. ** ** PR_FD_NSET(osfd, &fdset) includes a particular native file descriptor osfd ** in fdset. ** PR_FD_NCLR(osfd, &fdset) removes a native file descriptor osfd from fdset. ** PR_FD_NISSET(osfd, &fdset) is nonzero if native file descriptor osfd is a member of ** fdset, zero otherwise. */ NSPR_API(void) PR_FD_ZERO(PR_fd_set *set); NSPR_API(void) PR_FD_SET(PRFileDesc *fd, PR_fd_set *set); NSPR_API(void) PR_FD_CLR(PRFileDesc *fd, PR_fd_set *set); NSPR_API(PRInt32) PR_FD_ISSET(PRFileDesc *fd, PR_fd_set *set); NSPR_API(void) PR_FD_NSET(PROsfd osfd, PR_fd_set *set); NSPR_API(void) PR_FD_NCLR(PROsfd osfd, PR_fd_set *set); NSPR_API(PRInt32) PR_FD_NISSET(PROsfd osfd, PR_fd_set *set); /* ** The next two entry points should not be in the API, but they are ** declared here for historical reasons. */ NSPR_API(PRInt32) PR_GetSysfdTableMax(void); NSPR_API(PRInt32) PR_SetSysfdTableSize(PRIntn table_size); #ifndef NO_NSPR_10_SUPPORT #include NSPR_API(PRInt32) PR_Stat(const char *path, struct stat *buf); #endif /* NO_NSPR_10_SUPPORT */ PR_END_EXTERN_C #endif /* defined(PROBSLET_H) */ /* probslet.h */ nspr-4.11/nspr/pr/include/obsolete/protypes.h0000644000000000000000000001146212623070344017454 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This header typedefs the old 'native' types to the new PRs. * These definitions are scheduled to be eliminated at the earliest * possible time. The NSPR API is implemented and documented using * the new definitions. */ #if !defined(PROTYPES_H) #define PROTYPES_H typedef PRUintn uintn; #ifndef _XP_Core_ typedef PRIntn intn; #endif /* * It is trickier to define uint, int8, uint8, int16, uint16, * int32, uint32, int64, and uint64 because some of these int * types are defined by standard header files on some platforms. * Our strategy here is to include all such standard headers * first, and then define these int types only if they are not * defined by those standard headers. */ /* * BeOS defines all the int types below in its standard header * file SupportDefs.h. */ #ifdef XP_BEOS #include #endif /* * SVR4 typedef of uint is commonly found on UNIX machines. * * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h) * defines the types int8, int16, int32, and int64. * * On OS/2, sys/types.h defines uint. */ #if defined(XP_UNIX) || defined(XP_OS2) #include #endif /* model.h on HP-UX defines int8, int16, and int32. */ #ifdef HPUX #include #endif /* * uint */ #if !defined(XP_BEOS) && !defined(XP_OS2) && !defined(XP_UNIX) || defined(NTO) typedef PRUintn uint; #endif /* * uint64 */ #if !defined(XP_BEOS) typedef PRUint64 uint64; #endif /* * uint32 */ #if !defined(XP_BEOS) #if !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO) typedef PRUint32 uint32; #else typedef unsigned long uint32; #endif #endif /* * uint16 */ #if !defined(XP_BEOS) typedef PRUint16 uint16; #endif /* * uint8 */ #if !defined(XP_BEOS) typedef PRUint8 uint8; #endif /* * int64 */ #if !defined(XP_BEOS) && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) typedef PRInt64 int64; #endif /* * int32 */ #if !defined(XP_BEOS) && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ && !defined(HPUX) #if !defined(_WIN32) && !defined(XP_OS2) && !defined(NTO) typedef PRInt32 int32; #else typedef long int32; #endif #endif /* * int16 */ #if !defined(XP_BEOS) && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ && !defined(HPUX) typedef PRInt16 int16; #endif /* * int8 */ #if !defined(XP_BEOS) && !defined(_PR_AIX_HAVE_BSD_INT_TYPES) \ && !defined(HPUX) typedef PRInt8 int8; #endif typedef PRFloat64 float64; typedef PRUptrdiff uptrdiff_t; typedef PRUword uprword_t; typedef PRWord prword_t; /* Re: prbit.h */ #define TEST_BIT PR_TEST_BIT #define SET_BIT PR_SET_BIT #define CLEAR_BIT PR_CLEAR_BIT /* Re: prarena.h->plarena.h */ #define PRArena PLArena #define PRArenaPool PLArenaPool #define PRArenaStats PLArenaStats #define PR_ARENA_ALIGN PL_ARENA_ALIGN #define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL #define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE #define PR_ARENA_GROW PL_ARENA_GROW #define PR_ARENA_MARK PL_ARENA_MARK #define PR_CLEAR_UNUSED PL_CLEAR_UNUSED #define PR_CLEAR_ARENA PL_CLEAR_ARENA #define PR_ARENA_RELEASE PL_ARENA_RELEASE #define PR_COUNT_ARENA PL_COUNT_ARENA #define PR_ARENA_DESTROY PL_ARENA_DESTROY #define PR_InitArenaPool PL_InitArenaPool #define PR_FreeArenaPool PL_FreeArenaPool #define PR_FinishArenaPool PL_FinishArenaPool #define PR_CompactArenaPool PL_CompactArenaPool #define PR_ArenaFinish PL_ArenaFinish #define PR_ArenaAllocate PL_ArenaAllocate #define PR_ArenaGrow PL_ArenaGrow #define PR_ArenaRelease PL_ArenaRelease #define PR_ArenaCountAllocation PL_ArenaCountAllocation #define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth #define PR_ArenaCountGrowth PL_ArenaCountGrowth #define PR_ArenaCountRelease PL_ArenaCountRelease #define PR_ArenaCountRetract PL_ArenaCountRetract /* Re: prhash.h->plhash.h */ #define PRHashEntry PLHashEntry #define PRHashTable PLHashTable #define PRHashNumber PLHashNumber #define PRHashFunction PLHashFunction #define PRHashComparator PLHashComparator #define PRHashEnumerator PLHashEnumerator #define PRHashAllocOps PLHashAllocOps #define PR_NewHashTable PL_NewHashTable #define PR_HashTableDestroy PL_HashTableDestroy #define PR_HashTableRawLookup PL_HashTableRawLookup #define PR_HashTableRawAdd PL_HashTableRawAdd #define PR_HashTableRawRemove PL_HashTableRawRemove #define PR_HashTableAdd PL_HashTableAdd #define PR_HashTableRemove PL_HashTableRemove #define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries #define PR_HashTableLookup PL_HashTableLookup #define PR_HashTableDump PL_HashTableDump #define PR_HashString PL_HashString #define PR_CompareStrings PL_CompareStrings #define PR_CompareValues PL_CompareValues #endif /* !defined(PROTYPES_H) */ nspr-4.11/nspr/pr/include/obsolete/prsem.h0000644000000000000000000000401412623070344016710 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prsem_h___ #define prsem_h___ /* ** API for counting semaphores. Semaphores are counting synchronizing ** variables based on a lock and a condition variable. They are lightweight ** contention control for a given count of resources. */ #include "prtypes.h" PR_BEGIN_EXTERN_C typedef struct PRSemaphore PRSemaphore; /* ** Create a new semaphore object. */ NSPR_API(PRSemaphore*) PR_NewSem(PRUintn value); /* ** Destroy the given semaphore object. ** */ NSPR_API(void) PR_DestroySem(PRSemaphore *sem); /* ** Wait on a Semaphore. ** ** This routine allows a calling thread to wait or proceed depending upon the ** state of the semahore sem. The thread can proceed only if the counter value ** of the semaphore sem is currently greater than 0. If the value of semaphore ** sem is positive, it is decremented by one and the routine returns immediately ** allowing the calling thread to continue. If the value of semaphore sem is 0, ** the calling thread blocks awaiting the semaphore to be released by another ** thread. ** ** This routine can return PR_PENDING_INTERRUPT if the waiting thread ** has been interrupted. */ NSPR_API(PRStatus) PR_WaitSem(PRSemaphore *sem); /* ** This routine increments the counter value of the semaphore. If other threads ** are blocked for the semaphore, then the scheduler will determine which ONE ** thread will be unblocked. */ NSPR_API(void) PR_PostSem(PRSemaphore *sem); /* ** Returns the value of the semaphore referenced by sem without affecting ** the state of the semaphore. The value represents the semaphore vaule F** at the time of the call, but may not be the actual value when the ** caller inspects it. */ NSPR_API(PRUintn) PR_GetValueSem(PRSemaphore *sem); PR_END_EXTERN_C #endif /* prsem_h___ */ nspr-4.11/nspr/pr/include/pratom.h0000644000000000000000000001326312623070344015256 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* GLOBAL FUNCTIONS: ** DESCRIPTION: ** PR Atomic operations */ #ifndef pratom_h___ #define pratom_h___ #include "prtypes.h" #include "prlock.h" PR_BEGIN_EXTERN_C /* ** FUNCTION: PR_AtomicIncrement ** DESCRIPTION: ** Atomically increment a 32 bit value. ** INPUTS: ** val: a pointer to the value to increment ** RETURN: ** the returned value is the result of the increment */ NSPR_API(PRInt32) PR_AtomicIncrement(PRInt32 *val); /* ** FUNCTION: PR_AtomicDecrement ** DESCRIPTION: ** Atomically decrement a 32 bit value. ** INPUTS: ** val: a pointer to the value to decrement ** RETURN: ** the returned value is the result of the decrement */ NSPR_API(PRInt32) PR_AtomicDecrement(PRInt32 *val); /* ** FUNCTION: PR_AtomicSet ** DESCRIPTION: ** Atomically set a 32 bit value. ** INPUTS: ** val: A pointer to a 32 bit value to be set ** newval: The newvalue to assign to val ** RETURN: ** Returns the prior value */ NSPR_API(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval); /* ** FUNCTION: PR_AtomicAdd ** DESCRIPTION: ** Atomically add a 32 bit value. ** INPUTS: ** ptr: a pointer to the value to increment ** val: value to be added ** RETURN: ** the returned value is the result of the addition */ NSPR_API(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val); /* ** MACRO: PR_ATOMIC_INCREMENT ** MACRO: PR_ATOMIC_DECREMENT ** MACRO: PR_ATOMIC_SET ** MACRO: PR_ATOMIC_ADD ** DESCRIPTION: ** Macro versions of the atomic operations. They may be implemented ** as compiler intrinsics. ** ** IMPORTANT NOTE TO NSPR MAINTAINERS: ** Implement these macros with compiler intrinsics only on platforms ** where the PR_AtomicXXX functions are truly atomic (i.e., where the ** configuration macro _PR_HAVE_ATOMIC_OPS is defined). Otherwise, ** the macros and functions won't be compatible and can't be used ** interchangeably. */ #if defined(_WIN32) && !defined(_WIN32_WCE) && \ (!defined(_MSC_VER) || (_MSC_VER >= 1310)) #include #ifdef _MSC_VER #pragma intrinsic(_InterlockedIncrement) #pragma intrinsic(_InterlockedDecrement) #pragma intrinsic(_InterlockedExchange) #pragma intrinsic(_InterlockedExchangeAdd) #endif #define PR_ATOMIC_INCREMENT(val) _InterlockedIncrement((long volatile *)(val)) #define PR_ATOMIC_DECREMENT(val) _InterlockedDecrement((long volatile *)(val)) #define PR_ATOMIC_SET(val, newval) \ _InterlockedExchange((long volatile *)(val), (long)(newval)) #define PR_ATOMIC_ADD(ptr, val) \ (_InterlockedExchangeAdd((long volatile *)(ptr), (long)(val)) + (val)) #elif ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && \ ((defined(__APPLE__) && \ (defined(__ppc__) || defined(__i386__) || defined(__x86_64__))) || \ (defined(__linux__) && \ ((defined(__i386__) && \ defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \ defined(__ia64__) || defined(__x86_64__) || \ defined(__powerpc__) || \ (defined(__arm__) && \ defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \ defined(__aarch64__) || defined(__alpha) || \ (defined(__mips__) && \ defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4))))) /* * Because the GCC manual warns that some processors may support * reduced functionality of __sync_lock_test_and_set, we test for the * processors that we believe support a full atomic exchange operation. */ #define PR_ATOMIC_INCREMENT(val) __sync_add_and_fetch(val, 1) #define PR_ATOMIC_DECREMENT(val) __sync_sub_and_fetch(val, 1) #define PR_ATOMIC_SET(val, newval) __sync_lock_test_and_set(val, newval) #define PR_ATOMIC_ADD(ptr, val) __sync_add_and_fetch(ptr, val) #else #define PR_ATOMIC_INCREMENT(val) PR_AtomicIncrement(val) #define PR_ATOMIC_DECREMENT(val) PR_AtomicDecrement(val) #define PR_ATOMIC_SET(val, newval) PR_AtomicSet(val, newval) #define PR_ATOMIC_ADD(ptr, val) PR_AtomicAdd(ptr, val) #endif /* ** LIFO linked-list (stack) */ typedef struct PRStackElemStr PRStackElem; struct PRStackElemStr { PRStackElem *prstk_elem_next; /* next pointer MUST be at offset 0; assembly language code relies on this */ }; typedef struct PRStackStr PRStack; /* ** FUNCTION: PR_CreateStack ** DESCRIPTION: ** Create a stack, a LIFO linked list ** INPUTS: ** stack_name: a pointer to string containing the name of the stack ** RETURN: ** A pointer to the created stack, if successful, else NULL. */ NSPR_API(PRStack *) PR_CreateStack(const char *stack_name); /* ** FUNCTION: PR_StackPush ** DESCRIPTION: ** Push an element on the top of the stack ** INPUTS: ** stack: pointer to the stack ** stack_elem: pointer to the stack element ** RETURN: ** None */ NSPR_API(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem); /* ** FUNCTION: PR_StackPop ** DESCRIPTION: ** Remove the element on the top of the stack ** INPUTS: ** stack: pointer to the stack ** RETURN: ** A pointer to the stack element removed from the top of the stack, ** if non-empty, ** else NULL */ NSPR_API(PRStackElem *) PR_StackPop(PRStack *stack); /* ** FUNCTION: PR_DestroyStack ** DESCRIPTION: ** Destroy the stack ** INPUTS: ** stack: pointer to the stack ** RETURN: ** PR_SUCCESS - if successfully deleted ** PR_FAILURE - if the stack is not empty ** PR_GetError will return ** PR_INVALID_STATE_ERROR - stack is not empty */ NSPR_API(PRStatus) PR_DestroyStack(PRStack *stack); PR_END_EXTERN_C #endif /* pratom_h___ */ nspr-4.11/nspr/pr/include/prbit.h0000644000000000000000000001206612623070344015074 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prbit_h___ #define prbit_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** Replace compare/jump/add/shift sequence with compiler built-in/intrinsic ** functions. */ #if defined(_WIN32) && (_MSC_VER >= 1300) && \ (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM)) # include # pragma intrinsic(_BitScanForward,_BitScanReverse) __forceinline static int __prBitScanForward32(unsigned int val) { unsigned long idx; _BitScanForward(&idx, (unsigned long)val); return( (int)idx ); } __forceinline static int __prBitScanReverse32(unsigned int val) { unsigned long idx; _BitScanReverse(&idx, (unsigned long)val); return( (int)(31-idx) ); } # define pr_bitscan_ctz32(val) __prBitScanForward32(val) # define pr_bitscan_clz32(val) __prBitScanReverse32(val) # define PR_HAVE_BUILTIN_BITSCAN32 #elif ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && \ (defined(__i386__) || defined(__x86_64__) || defined(__arm__)) # define pr_bitscan_ctz32(val) __builtin_ctz(val) # define pr_bitscan_clz32(val) __builtin_clz(val) # define PR_HAVE_BUILTIN_BITSCAN32 #endif /* MSVC || GCC */ /* ** A prbitmap_t is a long integer that can be used for bitmaps */ typedef unsigned long prbitmap_t; #define PR_TEST_BIT(_map,_bit) \ ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] & (1L << ((_bit) & (PR_BITS_PER_LONG-1)))) #define PR_SET_BIT(_map,_bit) \ ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] |= (1L << ((_bit) & (PR_BITS_PER_LONG-1)))) #define PR_CLEAR_BIT(_map,_bit) \ ((_map)[(_bit)>>PR_BITS_PER_LONG_LOG2] &= ~(1L << ((_bit) & (PR_BITS_PER_LONG-1)))) /* ** Compute the log of the least power of 2 greater than or equal to n */ NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i); /* ** Compute the log of the greatest power of 2 less than or equal to n */ NSPR_API(PRIntn) PR_FloorLog2(PRUint32 i); /* ** Macro version of PR_CeilingLog2: Compute the log of the least power of ** 2 greater than or equal to _n. The result is returned in _log2. */ #ifdef PR_HAVE_BUILTIN_BITSCAN32 #define PR_CEILING_LOG2(_log2,_n) \ PR_BEGIN_MACRO \ PRUint32 j_ = (PRUint32)(_n); \ (_log2) = (j_ <= 1 ? 0 : 32 - pr_bitscan_clz32(j_ - 1)); \ PR_END_MACRO #else #define PR_CEILING_LOG2(_log2,_n) \ PR_BEGIN_MACRO \ PRUint32 j_ = (PRUint32)(_n); \ (_log2) = 0; \ if ((j_) & ((j_)-1)) \ (_log2) += 1; \ if ((j_) >> 16) \ (_log2) += 16, (j_) >>= 16; \ if ((j_) >> 8) \ (_log2) += 8, (j_) >>= 8; \ if ((j_) >> 4) \ (_log2) += 4, (j_) >>= 4; \ if ((j_) >> 2) \ (_log2) += 2, (j_) >>= 2; \ if ((j_) >> 1) \ (_log2) += 1; \ PR_END_MACRO #endif /* PR_HAVE_BUILTIN_BITSCAN32 */ /* ** Macro version of PR_FloorLog2: Compute the log of the greatest power of ** 2 less than or equal to _n. The result is returned in _log2. ** ** This is equivalent to finding the highest set bit in the word. */ #ifdef PR_HAVE_BUILTIN_BITSCAN32 #define PR_FLOOR_LOG2(_log2,_n) \ PR_BEGIN_MACRO \ PRUint32 j_ = (PRUint32)(_n); \ (_log2) = 31 - pr_bitscan_clz32((j_) | 1); \ PR_END_MACRO #else #define PR_FLOOR_LOG2(_log2,_n) \ PR_BEGIN_MACRO \ PRUint32 j_ = (PRUint32)(_n); \ (_log2) = 0; \ if ((j_) >> 16) \ (_log2) += 16, (j_) >>= 16; \ if ((j_) >> 8) \ (_log2) += 8, (j_) >>= 8; \ if ((j_) >> 4) \ (_log2) += 4, (j_) >>= 4; \ if ((j_) >> 2) \ (_log2) += 2, (j_) >>= 2; \ if ((j_) >> 1) \ (_log2) += 1; \ PR_END_MACRO #endif /* PR_HAVE_BUILTIN_BITSCAN32 */ /* ** Macros for rotate left and right. The argument 'a' must be an unsigned ** 32-bit integer type such as PRUint32. ** ** There is no rotate operation in the C Language, so the construct ** (a << 4) | (a >> 28) is frequently used instead. Most compilers convert ** this to a rotate instruction, but MSVC doesn't without a little help. ** To get MSVC to generate a rotate instruction, we have to use the _rotl ** or _rotr intrinsic and use a pragma to make it inline. ** ** Note: MSVC in VS2005 will do an inline rotate instruction on the above ** construct. */ #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \ defined(_M_X64) || defined(_M_ARM)) #include #pragma intrinsic(_rotl, _rotr) #define PR_ROTATE_LEFT32(a, bits) _rotl(a, bits) #define PR_ROTATE_RIGHT32(a, bits) _rotr(a, bits) #else #define PR_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits)))) #define PR_ROTATE_RIGHT32(a, bits) (((a) >> (bits)) | ((a) << (32 - (bits)))) #endif PR_END_EXTERN_C #endif /* prbit_h___ */ nspr-4.11/nspr/pr/include/prclist.h0000644000000000000000000000453312623070344015434 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prclist_h___ #define prclist_h___ #include "prtypes.h" typedef struct PRCListStr PRCList; /* ** Circular linked list */ struct PRCListStr { PRCList *next; PRCList *prev; }; /* ** Insert element "_e" into the list, before "_l". */ #define PR_INSERT_BEFORE(_e,_l) \ PR_BEGIN_MACRO \ (_e)->next = (_l); \ (_e)->prev = (_l)->prev; \ (_l)->prev->next = (_e); \ (_l)->prev = (_e); \ PR_END_MACRO /* ** Insert element "_e" into the list, after "_l". */ #define PR_INSERT_AFTER(_e,_l) \ PR_BEGIN_MACRO \ (_e)->next = (_l)->next; \ (_e)->prev = (_l); \ (_l)->next->prev = (_e); \ (_l)->next = (_e); \ PR_END_MACRO /* ** Return the element following element "_e" */ #define PR_NEXT_LINK(_e) \ ((_e)->next) /* ** Return the element preceding element "_e" */ #define PR_PREV_LINK(_e) \ ((_e)->prev) /* ** Append an element "_e" to the end of the list "_l" */ #define PR_APPEND_LINK(_e,_l) PR_INSERT_BEFORE(_e,_l) /* ** Insert an element "_e" at the head of the list "_l" */ #define PR_INSERT_LINK(_e,_l) PR_INSERT_AFTER(_e,_l) /* Return the head/tail of the list */ #define PR_LIST_HEAD(_l) (_l)->next #define PR_LIST_TAIL(_l) (_l)->prev /* ** Remove the element "_e" from it's circular list. */ #define PR_REMOVE_LINK(_e) \ PR_BEGIN_MACRO \ (_e)->prev->next = (_e)->next; \ (_e)->next->prev = (_e)->prev; \ PR_END_MACRO /* ** Remove the element "_e" from it's circular list. Also initializes the ** linkage. */ #define PR_REMOVE_AND_INIT_LINK(_e) \ PR_BEGIN_MACRO \ (_e)->prev->next = (_e)->next; \ (_e)->next->prev = (_e)->prev; \ (_e)->next = (_e); \ (_e)->prev = (_e); \ PR_END_MACRO /* ** Return non-zero if the given circular list "_l" is empty, zero if the ** circular list is not empty */ #define PR_CLIST_IS_EMPTY(_l) \ ((_l)->next == (_l)) /* ** Initialize a circular list */ #define PR_INIT_CLIST(_l) \ PR_BEGIN_MACRO \ (_l)->next = (_l); \ (_l)->prev = (_l); \ PR_END_MACRO #define PR_INIT_STATIC_CLIST(_l) \ {(_l), (_l)} #endif /* prclist_h___ */ nspr-4.11/nspr/pr/include/prcmon.h0000644000000000000000000000414112623070344015245 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prcmon_h___ #define prcmon_h___ /* ** Interface to cached monitors. Cached monitors use an address to find a ** given PR monitor. In this way a monitor can be associated with another ** object without preallocating a monitor for all objects. ** ** A hash table is used to quickly map addresses to individual monitors ** and the system automatically grows the hash table as needed. ** ** Cache monitors are about 5 times slower to use than uncached monitors. */ #include "prmon.h" #include "prinrval.h" PR_BEGIN_EXTERN_C /** ** Like PR_EnterMonitor except use the "address" to find a monitor in the ** monitor cache. If successful, returns the PRMonitor now associated ** with "address". Note that you must PR_CExitMonitor the address to ** release the monitor cache entry (otherwise the monitor cache will fill ** up). This call will return NULL if the monitor cache needs to be ** expanded and the system is out of memory. */ NSPR_API(PRMonitor*) PR_CEnterMonitor(void *address); /* ** Like PR_ExitMonitor except use the "address" to find a monitor in the ** monitor cache. */ NSPR_API(PRStatus) PR_CExitMonitor(void *address); /* ** Like PR_Wait except use the "address" to find a monitor in the ** monitor cache. */ NSPR_API(PRStatus) PR_CWait(void *address, PRIntervalTime timeout); /* ** Like PR_Notify except use the "address" to find a monitor in the ** monitor cache. */ NSPR_API(PRStatus) PR_CNotify(void *address); /* ** Like PR_NotifyAll except use the "address" to find a monitor in the ** monitor cache. */ NSPR_API(PRStatus) PR_CNotifyAll(void *address); /* ** Set a callback to be invoked each time a monitor is recycled from the cache ** freelist, with the monitor's cache-key passed in address. */ NSPR_API(void) PR_CSetOnMonitorRecycle(void (PR_CALLBACK *callback)(void *address)); PR_END_EXTERN_C #endif /* prcmon_h___ */ nspr-4.11/nspr/pr/include/prcountr.h0000644000000000000000000003554612623070344015640 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prcountr_h___ #define prcountr_h___ /*---------------------------------------------------------------------------- ** prcountr.h -- NSPR Instrumentation counters ** ** The NSPR Counter Feature provides a means to "count ** something." Counters can be dynamically defined, incremented, ** decremented, set, and deleted under application program ** control. ** ** The Counter Feature is intended to be used as instrumentation, ** not as operational data. If you need a counter for operational ** data, use native integral types. ** ** Counters are 32bit unsigned intergers. On overflow, a counter ** will wrap. No exception is recognized or reported. ** ** A counter can be dynamically created using a two level naming ** convention. A "handle" is returned when the counter is ** created. The counter can subsequently be addressed by its ** handle. An API is provided to get an existing counter's handle ** given the names with which it was originally created. ** Similarly, a counter's name can be retrieved given its handle. ** ** The counter naming convention is a two-level hierarchy. The ** QName is the higher level of the hierarchy; RName is the ** lower level. RNames can be thought of as existing within a ** QName. The same RName can exist within multiple QNames. QNames ** are unique. The NSPR Counter is not a near-zero overhead ** feature. Application designers should be aware of ** serialization issues when using the Counter API. Creating a ** counter locks a large asset, potentially causing a stall. This ** suggest that applications should create counters at component ** initialization, for example, and not create and destroy them ** willy-nilly. ... You have been warned. ** ** Incrementing and Adding to counters uses atomic operations. ** The performance of these operations will vary from platform ** to platform. On platforms where atomic operations are not ** supported the overhead may be substantial. ** ** When traversing the counter database with FindNext functions, ** the instantaneous values of any given counter is that at the ** moment of extraction. The state of the entire counter database ** may not be viewed as atomic. ** ** The counter interface may be disabled (No-Op'd) at compile ** time. When DEBUG is defined at compile time, the Counter ** Feature is compiled into NSPR and applications invoking it. ** When DEBUG is not defined, the counter macros compile to ** nothing. To force the Counter Feature to be compiled into an ** optimized build, define FORCE_NSPR_COUNTERS at compile time ** for both NSPR and the application intending to use it. ** ** Application designers should use the macro form of the Counter ** Feature methods to minimize performance impact in optimized ** builds. The macros normally compile to nothing on optimized ** builds. ** ** Application designers should be aware of the effects of ** debug and optimized build differences when using result of the ** Counter Feature macros in expressions. ** ** The Counter Feature is thread-safe and SMP safe. ** ** /lth. 09-Jun-1998. */ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** Opaque counter handle type. ** ... don't even think of looking in here. ** */ typedef void * PRCounterHandle; #define PRCOUNTER_NAME_MAX 31 #define PRCOUNTER_DESC_MAX 255 /* ----------------------------------------------------------------------- ** FUNCTION: PR_DEFINE_COUNTER() -- Define a PRCounterHandle ** ** DESCRIPTION: PR_DEFINE_COUNTER() is used to define a counter ** handle. ** */ #define PR_DEFINE_COUNTER(name) PRCounterHandle name /* ----------------------------------------------------------------------- ** FUNCTION: PR_INIT_COUNTER_HANDLE() -- Set the value of a PRCounterHandle ** ** DESCRIPTION: ** PR_INIT_COUNTER_HANDLE() sets the value of a PRCounterHandle ** to value. ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_INIT_COUNTER_HANDLE(handle,value)\ (handle) = (PRCounterHandle)(value) #else #define PR_INIT_COUNTER_HANDLE(handle,value) #endif /* ----------------------------------------------------------------------- ** FUNCTION: PR_CreateCounter() -- Create a counter ** ** DESCRIPTION: PR_CreateCounter() creates a counter object and ** initializes it to zero. ** ** The macro form takes as its first argument the name of the ** PRCounterHandle to receive the handle returned from ** PR_CreateCounter(). ** ** INPUTS: ** qName: The QName for the counter object. The maximum length ** of qName is defined by PRCOUNTER_NAME_MAX ** ** rName: The RName for the counter object. The maximum length ** of qName is defined by PRCOUNTER_NAME_MAX ** ** descrioption: The description of the counter object. The ** maximum length of description is defined by ** PRCOUNTER_DESC_MAX. ** ** OUTPUTS: ** ** RETURNS: ** PRCounterHandle. ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_CREATE_COUNTER(handle,qName,rName,description)\ (handle) = PR_CreateCounter((qName),(rName),(description)) #else #define PR_CREATE_COUNTER(handle,qName,rName,description) #endif NSPR_API(PRCounterHandle) PR_CreateCounter( const char *qName, const char *rName, const char *description ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_DestroyCounter() -- Destroy a counter object. ** ** DESCRIPTION: PR_DestroyCounter() removes a counter and ** unregisters its handle from the counter database. ** ** INPUTS: ** handle: the PRCounterHandle of the counter to be destroyed. ** ** OUTPUTS: ** The counter is destroyed. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_DESTROY_COUNTER(handle) PR_DestroyCounter((handle)) #else #define PR_DESTROY_COUNTER(handle) #endif NSPR_API(void) PR_DestroyCounter( PRCounterHandle handle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetCounterHandleFromName() -- Retreive a ** counter's handle give its name. ** ** DESCRIPTION: PR_GetCounterHandleFromName() retreives a ** counter's handle from the counter database, given the name ** the counter was originally created with. ** ** INPUTS: ** qName: Counter's original QName. ** rName: Counter's original RName. ** ** OUTPUTS: ** ** RETURNS: ** PRCounterHandle or PRCounterError. ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName)\ (handle) = PR_GetCounterHandleFromName((qName),(rName)) #else #define PR_GET_COUNTER_HANDLE_FROM_NAME(handle,qName,rName) #endif NSPR_API(PRCounterHandle) PR_GetCounterHandleFromName( const char *qName, const char *rName ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetCounterNameFromHandle() -- Retreive a ** counter's name, given its handle. ** ** DESCRIPTION: PR_GetCounterNameFromHandle() retreives a ** counter's name given its handle. ** ** INPUTS: ** qName: Where to store a pointer to qName. ** rName: Where to store a pointer to rName. ** description: Where to store a pointer to description. ** ** OUTPUTS: Pointers to the Counter Feature's copies of the names ** used when the counters were created. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description)\ PR_GetCounterNameFromHandle((handle),(qName),(rName),(description)) #else #define PR_GET_COUNTER_NAME_FROM_HANDLE(handle,qName,rName,description ) #endif NSPR_API(void) PR_GetCounterNameFromHandle( PRCounterHandle handle, const char **qName, const char **rName, const char **description ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_IncrementCounter() -- Add one to the referenced ** counter. ** ** DESCRIPTION: Add one to the referenced counter. ** ** INPUTS: ** handle: The PRCounterHandle of the counter to be incremented ** ** OUTPUTS: The counter is incrementd. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_INCREMENT_COUNTER(handle) PR_IncrementCounter(handle) #else #define PR_INCREMENT_COUNTER(handle) #endif NSPR_API(void) PR_IncrementCounter( PRCounterHandle handle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_DecrementCounter() -- Subtract one from the ** referenced counter ** ** DESCRIPTION: Subtract one from the referenced counter. ** ** INPUTS: ** handle: The PRCounterHandle of the coutner to be ** decremented. ** ** OUTPUTS: the counter is decremented. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_DECREMENT_COUNTER(handle) PR_DecrementCounter(handle) #else #define PR_DECREMENT_COUNTER(handle) #endif NSPR_API(void) PR_DecrementCounter( PRCounterHandle handle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_AddToCounter() -- Add a value to a counter. ** ** DESCRIPTION: Add value to the counter referenced by handle. ** ** INPUTS: ** handle: the PRCounterHandle of the counter to be added to. ** ** value: the value to be added to the counter. ** ** OUTPUTS: new value for counter. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_ADD_TO_COUNTER(handle,value)\ PR_AddToCounter((handle),(value)) #else #define PR_ADD_TO_COUNTER(handle,value) #endif NSPR_API(void) PR_AddToCounter( PRCounterHandle handle, PRUint32 value ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_SubtractFromCounter() -- A value is subtracted ** from a counter. ** ** DESCRIPTION: ** Subtract a value from a counter. ** ** INPUTS: ** handle: the PRCounterHandle of the counter to be subtracted ** from. ** ** value: the value to be subtracted from the counter. ** ** OUTPUTS: new value for counter ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_SUBTRACT_FROM_COUNTER(handle,value)\ PR_SubtractFromCounter((handle),(value)) #else #define PR_SUBTRACT_FROM_COUNTER(handle,value) #endif NSPR_API(void) PR_SubtractFromCounter( PRCounterHandle handle, PRUint32 value ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetCounter() -- Retreive the value of a counter ** ** DESCRIPTION: ** Retreive the value of a counter. ** ** INPUTS: ** handle: the PR_CounterHandle of the counter to be retreived ** ** OUTPUTS: ** ** RETURNS: The value of the referenced counter ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_GET_COUNTER(counter,handle)\ (counter) = PR_GetCounter((handle)) #else #define PR_GET_COUNTER(counter,handle) 0 #endif NSPR_API(PRUint32) PR_GetCounter( PRCounterHandle handle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_SetCounter() -- Replace the content of counter ** with value. ** ** DESCRIPTION: The contents of the referenced counter are ** replaced by value. ** ** INPUTS: ** handle: the PRCounterHandle of the counter whose contents ** are to be replaced. ** ** value: the new value of the counter. ** ** OUTPUTS: ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_SET_COUNTER(handle,value) PR_SetCounter((handle),(value)) #else #define PR_SET_COUNTER(handle,value) #endif NSPR_API(void) PR_SetCounter( PRCounterHandle handle, PRUint32 value ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_FindNextCounterQname() -- Retreive the next QName counter ** handle iterator ** ** DESCRIPTION: ** PR_FindNextCounterQname() retreives the first or next Qname ** the counter data base, depending on the value of handle. When ** handle is NULL, the function attempts to retreive the first ** QName handle in the database. When handle is a handle previosly ** retreived QName handle, then the function attempts to retreive ** the next QName handle. ** ** INPUTS: ** handle: PRCounterHandle or NULL. ** ** OUTPUTS: returned ** ** RETURNS: PRCounterHandle or NULL when no more QName counter ** handles are present. ** ** RESTRICTIONS: ** A concurrent PR_CreateCounter() or PR_DestroyCounter() may ** cause unpredictable results. ** ** A PRCounterHandle returned from this function may only be used ** in another PR_FindNextCounterQname() function call; other ** operations may cause unpredictable results. ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_FIND_NEXT_COUNTER_QNAME(next,handle)\ (next) = PR_FindNextCounterQname((handle)) #else #define PR_FIND_NEXT_COUNTER_QNAME(next,handle) NULL #endif NSPR_API(PRCounterHandle) PR_FindNextCounterQname( PRCounterHandle handle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_FindNextCounterRname() -- Retreive the next RName counter ** handle iterator ** ** DESCRIPTION: ** PR_FindNextCounterRname() retreives the first or next RNname ** handle from the counter data base, depending on the ** value of handle. When handle is NULL, the function attempts to ** retreive the first RName handle in the database. When handle is ** a handle previosly retreived RName handle, then the function ** attempts to retreive the next RName handle. ** ** INPUTS: ** handle: PRCounterHandle or NULL. ** qhandle: PRCounterHandle of a previously aquired via ** PR_FIND_NEXT_QNAME_HANDLE() ** ** OUTPUTS: returned ** ** RETURNS: PRCounterHandle or NULL when no more RName counter ** handles are present. ** ** RESTRICTIONS: ** A concurrent PR_CreateCounter() or PR_DestroyCounter() may ** cause unpredictable results. ** ** A PRCounterHandle returned from this function may only be used ** in another PR_FindNextCounterRname() function call; other ** operations may cause unpredictable results. ** */ #if defined(DEBUG) || defined(FORCE_NSPR_COUNTERS) #define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle)\ (next) = PR_FindNextCounterRname((rhandle),(qhandle)) #else #define PR_FIND_NEXT_COUNTER_RNAME(next,rhandle,qhandle) #endif NSPR_API(PRCounterHandle) PR_FindNextCounterRname( PRCounterHandle rhandle, PRCounterHandle qhandle ); PR_END_EXTERN_C #endif /* prcountr_h___ */ nspr-4.11/nspr/pr/include/prcvar.h0000644000000000000000000000701212623070344015244 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prcvar_h___ #define prcvar_h___ #include "prlock.h" #include "prinrval.h" PR_BEGIN_EXTERN_C typedef struct PRCondVar PRCondVar; /* ** Create a new condition variable. ** ** "lock" is the lock used to protect the condition variable. ** ** Condition variables are synchronization objects that threads can use ** to wait for some condition to occur. ** ** This may fail if memory is tight or if some operating system resource ** is low. In such cases, a NULL will be returned. */ NSPR_API(PRCondVar*) PR_NewCondVar(PRLock *lock); /* ** Destroy a condition variable. There must be no thread ** waiting on the condvar. The caller is responsible for guaranteeing ** that the condvar is no longer in use. ** */ NSPR_API(void) PR_DestroyCondVar(PRCondVar *cvar); /* ** The thread that waits on a condition is blocked in a "waiting on ** condition" state until another thread notifies the condition or a ** caller specified amount of time expires. The lock associated with ** the condition variable will be released, which must have be held ** prior to the call to wait. ** ** Logically a notified thread is moved from the "waiting on condition" ** state and made "ready." When scheduled, it will attempt to reacquire ** the lock that it held when wait was called. ** ** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and ** PR_INTERVAL_NO_WAIT. The former value requires that a condition be ** notified (or the thread interrupted) before it will resume from the ** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect ** is to release the lock, possibly causing a rescheduling within the ** runtime, then immediately attempting to reacquire the lock and resume. ** ** Any other value for timeout will cause the thread to be rescheduled ** either due to explicit notification or an expired interval. The latter ** must be determined by treating time as one part of the monitored data ** being protected by the lock and tested explicitly for an expired ** interval. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable or the thread was interrupted (PR_Interrupt()). ** The particular reason can be extracted with PR_GetError(). */ NSPR_API(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout); /* ** Notify ONE thread that is currently waiting on 'cvar'. Which thread is ** dependent on the implementation of the runtime. Common sense would dictate ** that all threads waiting on a single condition have identical semantics, ** therefore which one gets notified is not significant. ** ** The calling thead must hold the lock that protects the condition, as ** well as the invariants that are tightly bound to the condition, when ** notify is called. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable. */ NSPR_API(PRStatus) PR_NotifyCondVar(PRCondVar *cvar); /* ** Notify all of the threads waiting on the condition variable. The order ** that the threads are notified is indeterminant. The lock that protects ** the condition must be held. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable. */ NSPR_API(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar); PR_END_EXTERN_C #endif /* prcvar_h___ */ nspr-4.11/nspr/pr/include/prdtoa.h0000644000000000000000000000303712623070344015243 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prdtoa_h___ #define prdtoa_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** PR_strtod() returns as a double-precision floating-point number ** the value represented by the character string pointed to by ** s00. The string is scanned up to the first unrecognized ** character. **a ** If the value of se is not (char **)NULL, a pointer to ** the character terminating the scan is returned in the location pointed ** to by se. If no number can be formed, se is set to s00, and ** zero is returned. */ NSPR_API(PRFloat64) PR_strtod(const char *s00, char **se); /* ** PR_cnvtf() ** conversion routines for floating point ** prcsn - number of digits of precision to generate floating ** point value. */ NSPR_API(void) PR_cnvtf(char *buf, PRIntn bufsz, PRIntn prcsn, PRFloat64 fval); /* ** PR_dtoa() converts double to a string. ** ** ARGUMENTS: ** If rve is not null, *rve is set to point to the end of the return value. ** If d is +-Infinity or NaN, then *decpt is set to 9999. ** ** mode: ** 0 ==> shortest string that yields d when read in ** and rounded to nearest. */ NSPR_API(PRStatus) PR_dtoa(PRFloat64 d, PRIntn mode, PRIntn ndigits, PRIntn *decpt, PRIntn *sign, char **rve, char *buf, PRSize bufsize); PR_END_EXTERN_C #endif /* prdtoa_h___ */ nspr-4.11/nspr/pr/include/prenv.h0000644000000000000000000001304112623070344015100 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prenv_h___ #define prenv_h___ #include "prtypes.h" /*******************************************************************************/ /*******************************************************************************/ /****************** THESE FUNCTIONS MAY NOT BE THREAD SAFE *********************/ /*******************************************************************************/ /*******************************************************************************/ PR_BEGIN_EXTERN_C /* ** PR_GetEnv() -- Retrieve value of environment variable ** ** Description: ** PR_GetEnv() is modeled on Unix getenv(). ** ** ** Inputs: ** var -- The name of the environment variable ** ** Returns: ** The value of the environment variable 'var' or NULL if ** the variable is undefined. ** ** Restrictions: ** You'd think that a POSIX getenv(), putenv() would be ** consistently implemented everywhere. Surprise! It is not. On ** some platforms, a putenv() where the argument is of ** the form "name" causes the named environment variable to ** be un-set; that is: a subsequent getenv() returns NULL. On ** other platforms, the putenv() fails, on others, it is a ** no-op. Similarly, a putenv() where the argument is of the ** form "name=" causes the named environment variable to be ** un-set; a subsequent call to getenv() returns NULL. On ** other platforms, a subsequent call to getenv() returns a ** pointer to a null-string (a byte of zero). ** ** PR_GetEnv(), PR_SetEnv() provide a consistent behavior ** across all supported platforms. There are, however, some ** restrictions and some practices you must use to achieve ** consistent results everywhere. ** ** When manipulating the environment there is no way to un-set ** an environment variable across all platforms. We suggest ** you interpret the return of a pointer to null-string to ** mean the same as a return of NULL from PR_GetEnv(). ** ** A call to PR_SetEnv() where the parameter is of the form ** "name" will return PR_FAILURE; the environment remains ** unchanged. A call to PR_SetEnv() where the parameter is ** of the form "name=" may un-set the envrionment variable on ** some platforms; on others it may set the value of the ** environment variable to the null-string. ** ** For example, to test for NULL return or return of the ** null-string from PR_GetEnv(), use the following code ** fragment: ** ** char *val = PR_GetEnv("foo"); ** if ((NULL == val) || ('\0' == *val)) { ** ... interpret this as un-set ... ** } ** ** The caller must ensure that the string passed ** to PR_SetEnv() is persistent. That is: The string should ** not be on the stack, where it can be overwritten ** on return from the function calling PR_SetEnv(). ** Similarly, the string passed to PR_SetEnv() must not be ** overwritten by other actions of the process. ... Some ** platforms use the string by reference rather than copying ** it into the environment space. ... You have been warned! ** ** Use of platform-native functions that manipulate the ** environment (getenv(), putenv(), ** SetEnvironmentVariable(), etc.) must not be used with ** NSPR's similar functions. The platform-native functions ** may not be thread safe and/or may operate on different ** conceptual environment space than that operated upon by ** NSPR's functions or other environment manipulating ** functions on the same platform. (!) ** */ NSPR_API(char*) PR_GetEnv(const char *var); /* ** PR_SetEnv() -- set, unset or change an environment variable ** ** Description: ** PR_SetEnv() is modeled on the Unix putenv() function. ** ** Inputs: ** string -- pointer to a caller supplied ** constant, persistent string of the form name=value. Where ** name is the name of the environment variable to be set or ** changed; value is the value assigned to the variable. ** ** Returns: ** PRStatus. ** ** Restrictions: ** See the Restrictions documented in the description of ** PR_GetEnv() in this header file. ** ** */ NSPR_API(PRStatus) PR_SetEnv(const char *string); /* ** PR_DuplicateEnvironment() -- Obtain a copy of the environment. ** ** Description: ** PR_DuplicateEnvironment() copies the environment so that it can be ** modified without changing the current process's environment, and ** then passed to interfaces such as POSIX execve(). In particular, ** this avoids needing to allocate memory or take locks in the child ** after a fork(); neither of these is allowed by POSIX after a ** multithreaded process calls fork(), and PR_SetEnv does both. ** ** Inputs: ** none ** ** Returns: ** A pointer to a null-terminated array of null-terminated strings, ** like the traditional global variable "environ". The array and ** the strings are allocated with PR_Malloc(), and it is the ** caller's responsibility to free them. ** ** In case of memory allocation failure, or if the operating system ** doesn't support reading the entire environment through the global ** variable "environ" or similar, returns NULL instead. ** ** Restrictions: ** Similarly to PR_GetEnv(), this function may not interoperate as ** expected with the operating system's native environment accessors. */ NSPR_API(char **) PR_DuplicateEnvironment(void); PR_END_EXTERN_C #endif /* prenv_h___ */ nspr-4.11/nspr/pr/include/prerr.h0000644000000000000000000002016412623070344015104 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prerr_h___ #define prerr_h___ /* * * prerr.h * This file is automatically generated; please do not edit it. */ /* Memory allocation attempt failed */ #define PR_OUT_OF_MEMORY_ERROR (-6000L) /* Invalid file descriptor */ #define PR_BAD_DESCRIPTOR_ERROR (-5999L) /* The operation would have blocked */ #define PR_WOULD_BLOCK_ERROR (-5998L) /* Invalid memory address argument */ #define PR_ACCESS_FAULT_ERROR (-5997L) /* Invalid function for file type */ #define PR_INVALID_METHOD_ERROR (-5996L) /* Invalid memory address argument */ #define PR_ILLEGAL_ACCESS_ERROR (-5995L) /* Some unknown error has occurred */ #define PR_UNKNOWN_ERROR (-5994L) /* Operation interrupted by another thread */ #define PR_PENDING_INTERRUPT_ERROR (-5993L) /* function not implemented */ #define PR_NOT_IMPLEMENTED_ERROR (-5992L) /* I/O function error */ #define PR_IO_ERROR (-5991L) /* I/O operation timed out */ #define PR_IO_TIMEOUT_ERROR (-5990L) /* I/O operation on busy file descriptor */ #define PR_IO_PENDING_ERROR (-5989L) /* The directory could not be opened */ #define PR_DIRECTORY_OPEN_ERROR (-5988L) /* Invalid function argument */ #define PR_INVALID_ARGUMENT_ERROR (-5987L) /* Network address not available (in use?) */ #define PR_ADDRESS_NOT_AVAILABLE_ERROR (-5986L) /* Network address type not supported */ #define PR_ADDRESS_NOT_SUPPORTED_ERROR (-5985L) /* Already connected */ #define PR_IS_CONNECTED_ERROR (-5984L) /* Network address is invalid */ #define PR_BAD_ADDRESS_ERROR (-5983L) /* Local Network address is in use */ #define PR_ADDRESS_IN_USE_ERROR (-5982L) /* Connection refused by peer */ #define PR_CONNECT_REFUSED_ERROR (-5981L) /* Network address is presently unreachable */ #define PR_NETWORK_UNREACHABLE_ERROR (-5980L) /* Connection attempt timed out */ #define PR_CONNECT_TIMEOUT_ERROR (-5979L) /* Network file descriptor is not connected */ #define PR_NOT_CONNECTED_ERROR (-5978L) /* Failure to load dynamic library */ #define PR_LOAD_LIBRARY_ERROR (-5977L) /* Failure to unload dynamic library */ #define PR_UNLOAD_LIBRARY_ERROR (-5976L) /* Symbol not found in any of the loaded dynamic libraries */ #define PR_FIND_SYMBOL_ERROR (-5975L) /* Insufficient system resources */ #define PR_INSUFFICIENT_RESOURCES_ERROR (-5974L) /* A directory lookup on a network address has failed */ #define PR_DIRECTORY_LOOKUP_ERROR (-5973L) /* Attempt to access a TPD key that is out of range */ #define PR_TPD_RANGE_ERROR (-5972L) /* Process open FD table is full */ #define PR_PROC_DESC_TABLE_FULL_ERROR (-5971L) /* System open FD table is full */ #define PR_SYS_DESC_TABLE_FULL_ERROR (-5970L) /* Network operation attempted on non-network file descriptor */ #define PR_NOT_SOCKET_ERROR (-5969L) /* TCP-specific function attempted on a non-TCP file descriptor */ #define PR_NOT_TCP_SOCKET_ERROR (-5968L) /* TCP file descriptor is already bound */ #define PR_SOCKET_ADDRESS_IS_BOUND_ERROR (-5967L) /* Access Denied */ #define PR_NO_ACCESS_RIGHTS_ERROR (-5966L) /* The requested operation is not supported by the platform */ #define PR_OPERATION_NOT_SUPPORTED_ERROR (-5965L) /* The host operating system does not support the protocol requested */ #define PR_PROTOCOL_NOT_SUPPORTED_ERROR (-5964L) /* Access to the remote file has been severed */ #define PR_REMOTE_FILE_ERROR (-5963L) /* The value requested is too large to be stored in the data buffer provided */ #define PR_BUFFER_OVERFLOW_ERROR (-5962L) /* TCP connection reset by peer */ #define PR_CONNECT_RESET_ERROR (-5961L) /* Unused */ #define PR_RANGE_ERROR (-5960L) /* The operation would have deadlocked */ #define PR_DEADLOCK_ERROR (-5959L) /* The file is already locked */ #define PR_FILE_IS_LOCKED_ERROR (-5958L) /* Write would result in file larger than the system allows */ #define PR_FILE_TOO_BIG_ERROR (-5957L) /* The device for storing the file is full */ #define PR_NO_DEVICE_SPACE_ERROR (-5956L) /* Unused */ #define PR_PIPE_ERROR (-5955L) /* Unused */ #define PR_NO_SEEK_DEVICE_ERROR (-5954L) /* Cannot perform a normal file operation on a directory */ #define PR_IS_DIRECTORY_ERROR (-5953L) /* Symbolic link loop */ #define PR_LOOP_ERROR (-5952L) /* File name is too long */ #define PR_NAME_TOO_LONG_ERROR (-5951L) /* File not found */ #define PR_FILE_NOT_FOUND_ERROR (-5950L) /* Cannot perform directory operation on a normal file */ #define PR_NOT_DIRECTORY_ERROR (-5949L) /* Cannot write to a read-only file system */ #define PR_READ_ONLY_FILESYSTEM_ERROR (-5948L) /* Cannot delete a directory that is not empty */ #define PR_DIRECTORY_NOT_EMPTY_ERROR (-5947L) /* Cannot delete or rename a file object while the file system is busy */ #define PR_FILESYSTEM_MOUNTED_ERROR (-5946L) /* Cannot rename a file to a file system on another device */ #define PR_NOT_SAME_DEVICE_ERROR (-5945L) /* The directory object in the file system is corrupted */ #define PR_DIRECTORY_CORRUPTED_ERROR (-5944L) /* Cannot create or rename a filename that already exists */ #define PR_FILE_EXISTS_ERROR (-5943L) /* Directory is full. No additional filenames may be added */ #define PR_MAX_DIRECTORY_ENTRIES_ERROR (-5942L) /* The required device was in an invalid state */ #define PR_INVALID_DEVICE_STATE_ERROR (-5941L) /* The device is locked */ #define PR_DEVICE_IS_LOCKED_ERROR (-5940L) /* No more entries in the directory */ #define PR_NO_MORE_FILES_ERROR (-5939L) /* Encountered end of file */ #define PR_END_OF_FILE_ERROR (-5938L) /* Seek error */ #define PR_FILE_SEEK_ERROR (-5937L) /* The file is busy */ #define PR_FILE_IS_BUSY_ERROR (-5936L) /* The I/O operation was aborted */ #define PR_OPERATION_ABORTED_ERROR (-5935L) /* Operation is still in progress (probably a non-blocking connect) */ #define PR_IN_PROGRESS_ERROR (-5934L) /* Operation has already been initiated (probably a non-blocking connect) */ #define PR_ALREADY_INITIATED_ERROR (-5933L) /* The wait group is empty */ #define PR_GROUP_EMPTY_ERROR (-5932L) /* Object state improper for request */ #define PR_INVALID_STATE_ERROR (-5931L) /* Network is down */ #define PR_NETWORK_DOWN_ERROR (-5930L) /* Socket shutdown */ #define PR_SOCKET_SHUTDOWN_ERROR (-5929L) /* Connection aborted */ #define PR_CONNECT_ABORTED_ERROR (-5928L) /* Host is unreachable */ #define PR_HOST_UNREACHABLE_ERROR (-5927L) /* The library is not loaded */ #define PR_LIBRARY_NOT_LOADED_ERROR (-5926L) /* The one-time function was previously called and failed. Its error code is no longer available */ #define PR_CALL_ONCE_ERROR (-5925L) /* Placeholder for the end of the list */ #define PR_MAX_ERROR (-5924L) extern void nspr_InitializePRErrorTable(void); #define ERROR_TABLE_BASE_nspr (-6000L) #endif /* prerr_h___ */ nspr-4.11/nspr/pr/include/prerror.h0000644000000000000000000002603512623070344015450 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prerror_h___ #define prerror_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C typedef PRInt32 PRErrorCode; #define PR_NSPR_ERROR_BASE -6000 #include "prerr.h" /* ** Set error will preserve an error condition within a thread context. ** The values stored are the NSPR (platform independent) translation of ** the error. Also, if available, the platform specific oserror is stored. ** If there is no appropriate OS error number, a zero my be supplied. */ NSPR_API(void) PR_SetError(PRErrorCode errorCode, PRInt32 oserr); /* ** The text value specified may be NULL. If it is not NULL and the text length ** is zero, the string is assumed to be a null terminated C string. Otherwise ** the text is assumed to be the length specified and possibly include NULL ** characters (e.g., a multi-national string). ** ** The text will be copied into to thread structure and remain there ** until the next call to PR_SetError. */ NSPR_API(void) PR_SetErrorText( PRIntn textLength, const char *text); /* ** Return the current threads last set error code. */ NSPR_API(PRErrorCode) PR_GetError(void); /* ** Return the current threads last set os error code. This is used for ** machine specific code that desires the underlying os error. */ NSPR_API(PRInt32) PR_GetOSError(void); /* ** Get the length of the error text. If a zero is returned, then there ** is no text. Otherwise, the value returned is sufficient to contain ** the error text currently available. */ NSPR_API(PRInt32) PR_GetErrorTextLength(void); /* ** Copy the current threads current error text. Then actual number of bytes ** copied is returned as the result. If the result is zero, the 'text' area ** is unaffected. */ NSPR_API(PRInt32) PR_GetErrorText(char *text); /* Copyright (C) 1987, 1988 Student Information Processing Board of the Massachusetts Institute of Technology. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ /* * NOTE: * The interfaces for error-code-translation described in the rest of * this file are preliminary in the 3.1 release of nspr and are subject * to change in future releases. */ /* ** Description: Localizable error code to string function. ** ** ** NSPR provides a mechanism for converting an error code to a ** descriptive string, in a caller-specified language. ** ** Error codes themselves are 32 bit (signed) integers. Typically, ** the high order 24 bits are an identifier of which error table the ** error code is from, and the low order 8 bits are a sequential error ** number within the table. NSPR supports error tables whose first ** error code is not a multiple of 256, such error code assignments ** should be avoided when possible. ** ** Error table 0 is defined to match the UNIX system call error table ** (sys_errlist); this allows errno values to be used directly in the ** library. Other error table numbers are typically formed by ** compacting together the first four characters of the error table ** name. The mapping between characters in the name and numeric ** values in the error code are defined in a system-independent ** fashion, so that two systems that can pass integral values between ** them can reliably pass error codes without loss of meaning; this ** should work even if the character sets used are not the ** same. (However, if this is to be done, error table 0 should be ** avoided, since the local system call error tables may differ.) ** ** Libraries defining error codes need only provide a table mapping ** error code numbers to names and default English descriptions, ** calling a routine to install the table, making it ``known'' to NSPR ** library. Once installed, a table may not be removed. Any error ** code the library generates can be converted to the corresponding ** error message. There is also a default format for error codes ** accidentally returned before making the table known, which is of ** the form "unknown code foo 32", where "foo" would be the name of ** the table. ** ** Normally, the error code conversion routine only supports the ** languages "i-default" and "en", returning the error-table-provided ** English description for both languages. The application may ** provide a localization plugin, allowing support for additional ** languages. ** **/ /**********************************************************************/ /************************* TYPES AND CONSTANTS ************************/ /**********************************************************************/ /* * PRLanguageCode -- * * NSPR represents a language code as a non-negative integer. * Languages 0 is always "i-default" the language you get without * explicit negotiation. Language 1 is always "en", English * which has been explicitly negotiated. Additional language * codes are defined by an application-provided localization plugin. */ typedef PRUint32 PRLanguageCode; #define PR_LANGUAGE_I_DEFAULT 0 /* i-default, the default language */ #define PR_LANGUAGE_EN 1 /* English, explicitly negotiated */ /* * struct PRErrorMessage -- * * An error message in an error table. */ struct PRErrorMessage { const char * name; /* Macro name for error */ const char * en_text; /* Default English text */ }; /* * struct PRErrorTable -- * * An error table, provided by a library. */ struct PRErrorTable { const struct PRErrorMessage * msgs; /* Array of error information */ const char *name; /* Name of error table source */ PRErrorCode base; /* Error code for first error in table */ int n_msgs; /* Number of codes in table */ }; /* * struct PRErrorCallbackPrivate -- * * A private structure for the localization plugin */ struct PRErrorCallbackPrivate; /* * struct PRErrorCallbackTablePrivate -- * * A data structure under which the localization plugin may store information, * associated with an error table, that is private to itself. */ struct PRErrorCallbackTablePrivate; /* * PRErrorCallbackLookupFn -- * * A function of PRErrorCallbackLookupFn type is a localization * plugin callback which converts an error code into a description * in the requested language. The callback is provided the * appropriate error table, private data for the plugin and the table. * The callback returns the appropriate UTF-8 encoded description, or NULL * if no description can be found. */ typedef const char * PRErrorCallbackLookupFn(PRErrorCode code, PRLanguageCode language, const struct PRErrorTable *table, struct PRErrorCallbackPrivate *cb_private, struct PRErrorCallbackTablePrivate *table_private); /* * PRErrorCallbackNewTableFn -- * * A function PRErrorCallbackNewTableFn type is a localization plugin * callback which is called once with each error table registered * with NSPR. The callback is provided with the error table and * the plugin's private structure. The callback returns any table private * data it wishes to associate with the error table. Does not need to be thread * safe. */ typedef struct PRErrorCallbackTablePrivate * PRErrorCallbackNewTableFn(const struct PRErrorTable *table, struct PRErrorCallbackPrivate *cb_private); /**********************************************************************/ /****************************** FUNCTIONS *****************************/ /**********************************************************************/ /*********************************************************************** ** FUNCTION: PR_ErrorToString ** DESCRIPTION: ** Returns the UTF-8 message for an error code in ** the requested language. May return the message ** in the default language if a translation in the requested ** language is not available. The returned string is ** valid for the duration of the process. Never returns NULL. ** ***********************************************************************/ NSPR_API(const char *) PR_ErrorToString(PRErrorCode code, PRLanguageCode language); /*********************************************************************** ** FUNCTION: PR_ErrorToName ** DESCRIPTION: ** Returns the macro name for an error code, or NULL ** if the error code is not known. The returned string is ** valid for the duration of the process. ** ** Does not work for error table 0, the system error codes. ** ***********************************************************************/ NSPR_API(const char *) PR_ErrorToName(PRErrorCode code); /*********************************************************************** ** FUNCTION: PR_ErrorLanguages ** DESCRIPTION: ** Returns the RFC 1766 language tags for the language ** codes PR_ErrorToString() supports. The returned array is valid ** for the duration of the process. Never returns NULL. The first ** item in the returned array is the language tag for PRLanguageCode 0, ** the second is for PRLanguageCode 1, and so on. The array is terminated ** with a null pointer. ** ***********************************************************************/ NSPR_API(const char * const *) PR_ErrorLanguages(void); /*********************************************************************** ** FUNCTION: PR_ErrorInstallTable ** DESCRIPTION: ** Registers an error table with NSPR. Must be done exactly once per ** table. Memory pointed to by `table' must remain valid for the life ** of the process. ** ** NOT THREAD SAFE! ** ***********************************************************************/ NSPR_API(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table); /*********************************************************************** ** FUNCTION: PR_ErrorInstallCallback ** DESCRIPTION: ** Registers an error localization plugin with NSPR. May be called ** at most one time. `languages' contains the language codes supported ** by this plugin. Languages 0 and 1 must be "i-default" and "en" ** respectively. `lookup' and `newtable' contain pointers to ** the plugin callback functions. `cb_private' contains any information ** private to the plugin functions. ** ** NOT THREAD SAFE! ** ***********************************************************************/ NSPR_API(void) PR_ErrorInstallCallback(const char * const * languages, PRErrorCallbackLookupFn *lookup, PRErrorCallbackNewTableFn *newtable, struct PRErrorCallbackPrivate *cb_private); PR_END_EXTERN_C #endif /* prerror_h___ */ nspr-4.11/nspr/pr/include/prinet.h0000644000000000000000000000611012623070344015246 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: prinet.h * Description: * Header file used to find the system header files for socket support[1]. * This file serves the following purposes: * - A cross-platform, "get-everything" socket header file. On * Unix, socket support is scattered in several header files, * while Windows has a "get-everything" socket header file[2]. * - NSPR needs the following macro definitions and function * prototype declarations from these header files: * AF_INET * INADDR_ANY, INADDR_LOOPBACK, INADDR_BROADCAST * ntohl(), ntohs(), htonl(), ntons(). * NSPR does not define its own versions of these macros and * functions. It simply uses the native versions, which have * the same names on all supported platforms. * This file is intended to be included by NSPR public header * files, such as prio.h. One should not include this file directly. * * Notes: * 1. This file should have been an internal header. Please do not * depend on it to pull in the system header files you need. * 2. WARNING: This file is no longer cross-platform as it is a no-op * for WIN32! See the comment in the WIN32 section for details. */ #ifndef prinet_h__ #define prinet_h__ #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) #include #include /* AF_INET */ #include /* INADDR_ANY, ..., ntohl(), ... */ #ifdef XP_OS2 #include #endif #ifdef XP_UNIX #ifdef AIX /* * On AIX 4.3, the header refers to struct * ether_addr and struct sockaddr_dl that are not declared. * The following struct declarations eliminate the compiler * warnings. */ struct ether_addr; struct sockaddr_dl; #endif /* AIX */ #include #endif /* XP_UNIX */ #include #if defined(FREEBSD) || defined(BSDI) || defined(QNX) #include /* the only place that defines INADDR_LOOPBACK */ #endif /* * OS/2 hack. For some reason INADDR_LOOPBACK is not defined in the * socket headers. */ #if defined(OS2) && !defined(INADDR_LOOPBACK) #define INADDR_LOOPBACK 0x7f000001 #endif /* * Prototypes of ntohl() etc. are declared in * on these platforms. */ #if defined(BSDI) || defined(OSF1) #include #endif /* On Android, ntohl() etc. are declared in . */ #ifdef __ANDROID__ #include #endif #elif defined(WIN32) /* * Do not include any system header files. * * Originally we were including . It slowed down the * compilation of files that included NSPR headers, so we removed * the inclusion at customer's request, which created * an unfortunate inconsistency with other platforms. */ #else #error Unknown platform #endif #endif /* prinet_h__ */ nspr-4.11/nspr/pr/include/prinit.h0000644000000000000000000001466612623070344015271 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prinit_h___ #define prinit_h___ #include "prthread.h" #include "prtypes.h" #include "prwin16.h" #include PR_BEGIN_EXTERN_C /************************************************************************/ /**************************IDENTITY AND VERSIONING***********************/ /************************************************************************/ /* ** NSPR's name, this should persist until at least the turn of the ** century. */ #define PR_NAME "NSPR" /* ** NSPR's version is used to determine the likelihood that the version you ** used to build your component is anywhere close to being compatible with ** what is in the underlying library. ** ** The format of the version string is ** ".[.] []" */ #define PR_VERSION "4.11" #define PR_VMAJOR 4 #define PR_VMINOR 11 #define PR_VPATCH 0 #define PR_BETA PR_FALSE /* ** PRVersionCheck ** ** The basic signature of the function that is called to provide version ** checking. The result will be a boolean that indicates the likelihood ** that the underling library will perform as the caller expects. ** ** The only argument is a string, which should be the verson identifier ** of the library in question. That string will be compared against an ** equivalent string that represents the actual build version of the ** exporting library. ** ** The result will be the logical union of the directly called library ** and all dependent libraries. */ typedef PRBool (*PRVersionCheck)(const char*); /* ** PR_VersionCheck ** ** NSPR's existance proof of the version check function. ** ** Note that NSPR has no cooperating dependencies. */ NSPR_API(PRBool) PR_VersionCheck(const char *importedVersion); /* * Returns a const string of the NSPR library version. */ NSPR_API(const char*) PR_GetVersion(void); /************************************************************************/ /*******************************INITIALIZATION***************************/ /************************************************************************/ /* ** Initialize the runtime. Attach a thread object to the currently ** executing native thread of type "type". ** ** The specificaiton of 'maxPTDs' is ignored. */ NSPR_API(void) PR_Init( PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs); /* ** And alternate form of initialization, one that may become the default if ** not the only mechanism, provides a method to get the NSPR runtime init- ** ialized and place NSPR between the caller and the runtime library. This ** allows main() to be treated as any other thread root function, signalling ** its compeletion by returning and allowing the runtime to coordinate the ** completion of the other threads of the runtime. ** ** The priority of the main (or primordial) thread will be PR_PRIORITY_NORMAL. ** The thread may adjust its own priority by using PR_SetPriority(), though ** at this time the support for priorities is somewhat weak. ** ** The specificaiton of 'maxPTDs' is ignored. ** ** The value returned by PR_Initialize is the value returned from the root ** function, 'prmain'. */ typedef PRIntn (PR_CALLBACK *PRPrimordialFn)(PRIntn argc, char **argv); NSPR_API(PRIntn) PR_Initialize( PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs); /* ** Return PR_TRUE if PR_Init has already been called. */ NSPR_API(PRBool) PR_Initialized(void); /* * Perform a graceful shutdown of NSPR. PR_Cleanup() may be called by * the primordial thread near the end of the main() function. * * PR_Cleanup() attempts to synchronize the natural termination of * process. It does that by blocking the caller, if and only if it is * the primordial thread, until the number of user threads has dropped * to zero. When the primordial thread returns from main(), the process * will immediately and silently exit. That is, it will (if necessary) * forcibly terminate any existing threads and exit without significant * blocking and there will be no error messages or core files. * * PR_Cleanup() returns PR_SUCCESS if NSPR is successfully shutdown, * or PR_FAILURE if the calling thread of this function is not the * primordial thread. */ NSPR_API(PRStatus) PR_Cleanup(void); /* ** Disable Interrupts ** Disables timer signals used for pre-emptive scheduling. */ NSPR_API(void) PR_DisableClockInterrupts(void); /* ** Enables Interrupts ** Enables timer signals used for pre-emptive scheduling. */ NSPR_API(void) PR_EnableClockInterrupts(void); /* ** Block Interrupts ** Blocks the timer signal used for pre-emptive scheduling */ NSPR_API(void) PR_BlockClockInterrupts(void); /* ** Unblock Interrupts ** Unblocks the timer signal used for pre-emptive scheduling */ NSPR_API(void) PR_UnblockClockInterrupts(void); /* ** Create extra virtual processor threads. Generally used with MP systems. */ NSPR_API(void) PR_SetConcurrency(PRUintn numCPUs); /* ** Control the method and size of the file descriptor (PRFileDesc*) ** cache used by the runtime. Setting 'high' to zero is for performance, ** any other value probably for debugging (see memo on FD caching). */ NSPR_API(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high); /* * Cause an immediate, nongraceful, forced termination of the process. * It takes a PRIntn argument, which is the exit status code of the * process. */ NSPR_API(void) PR_ProcessExit(PRIntn status); /* ** Abort the process in a non-graceful manner. This will cause a core file, ** call to the debugger or other moral equivalent as well as causing the ** entire process to stop. */ NSPR_API(void) PR_Abort(void); /* **************************************************************** * * Module initialization: * **************************************************************** */ typedef struct PRCallOnceType { PRIntn initialized; PRInt32 inProgress; PRStatus status; } PRCallOnceType; typedef PRStatus (PR_CALLBACK *PRCallOnceFN)(void); typedef PRStatus (PR_CALLBACK *PRCallOnceWithArgFN)(void *arg); NSPR_API(PRStatus) PR_CallOnce( PRCallOnceType *once, PRCallOnceFN func ); NSPR_API(PRStatus) PR_CallOnceWithArg( PRCallOnceType *once, PRCallOnceWithArgFN func, void *arg ); PR_END_EXTERN_C #endif /* prinit_h___ */ nspr-4.11/nspr/pr/include/prinrval.h0000644000000000000000000001234212623070344015606 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prinrval.h ** Description: API to interval timing functions of NSPR. ** ** ** NSPR provides interval times that are independent of network time ** of day values. Interval times are (in theory) accurate regardless ** of host processing requirements and also very cheap to acquire. It ** is expected that getting an interval time while in a synchronized ** function (holding one's lock). **/ #if !defined(prinrval_h) #define prinrval_h #include "prtypes.h" PR_BEGIN_EXTERN_C /**********************************************************************/ /************************* TYPES AND CONSTANTS ************************/ /**********************************************************************/ typedef PRUint32 PRIntervalTime; /*********************************************************************** ** DEFINES: PR_INTERVAL_MIN ** PR_INTERVAL_MAX ** DESCRIPTION: ** These two constants define the range (in ticks / second) of the ** platform dependent type, PRIntervalTime. These constants bound both ** the period and the resolution of a PRIntervalTime. ***********************************************************************/ #define PR_INTERVAL_MIN 1000UL #define PR_INTERVAL_MAX 100000UL /*********************************************************************** ** DEFINES: PR_INTERVAL_NO_WAIT ** PR_INTERVAL_NO_TIMEOUT ** DESCRIPTION: ** Two reserved constants are defined in the PRIntervalTime namespace. ** They are used to indicate that the process should wait no time (return ** immediately) or wait forever (never time out), respectively. ** Note: PR_INTERVAL_NO_TIMEOUT passed as input to PR_Connect is ** interpreted as use the OS's connect timeout. ** ***********************************************************************/ #define PR_INTERVAL_NO_WAIT 0UL #define PR_INTERVAL_NO_TIMEOUT 0xffffffffUL /**********************************************************************/ /****************************** FUNCTIONS *****************************/ /**********************************************************************/ /*********************************************************************** ** FUNCTION: PR_IntervalNow ** DESCRIPTION: ** Return the value of NSPR's free running interval timer. That timer ** can be used to establish epochs and determine intervals (be computing ** the difference between two times). ** INPUTS: void ** OUTPUTS: void ** RETURN: PRIntervalTime ** ** SIDE EFFECTS: ** None ** RESTRICTIONS: ** The units of PRIntervalTime are platform dependent. They are chosen ** such that they are appropriate for the host OS, yet provide sufficient ** resolution and period to be useful to clients. ** MEMORY: N/A ** ALGORITHM: Platform dependent ***********************************************************************/ NSPR_API(PRIntervalTime) PR_IntervalNow(void); /*********************************************************************** ** FUNCTION: PR_TicksPerSecond ** DESCRIPTION: ** Return the number of ticks per second for PR_IntervalNow's clock. ** The value will be in the range [PR_INTERVAL_MIN..PR_INTERVAL_MAX]. ** INPUTS: void ** OUTPUTS: void ** RETURN: PRUint32 ** ** SIDE EFFECTS: ** None ** RESTRICTIONS: ** None ** MEMORY: N/A ** ALGORITHM: N/A ***********************************************************************/ NSPR_API(PRUint32) PR_TicksPerSecond(void); /*********************************************************************** ** FUNCTION: PR_SecondsToInterval ** PR_MillisecondsToInterval ** PR_MicrosecondsToInterval ** DESCRIPTION: ** Convert standard clock units to platform dependent intervals. ** INPUTS: PRUint32 ** OUTPUTS: void ** RETURN: PRIntervalTime ** ** SIDE EFFECTS: ** None ** RESTRICTIONS: ** Conversion may cause overflow, which is not reported. ** MEMORY: N/A ** ALGORITHM: N/A ***********************************************************************/ NSPR_API(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds); NSPR_API(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli); NSPR_API(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro); /*********************************************************************** ** FUNCTION: PR_IntervalToSeconds ** PR_IntervalToMilliseconds ** PR_IntervalToMicroseconds ** DESCRIPTION: ** Convert platform dependent intervals to standard clock units. ** INPUTS: PRIntervalTime ** OUTPUTS: void ** RETURN: PRUint32 ** ** SIDE EFFECTS: ** None ** RESTRICTIONS: ** Conversion may cause overflow, which is not reported. ** MEMORY: N/A ** ALGORITHM: N/A ***********************************************************************/ NSPR_API(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks); NSPR_API(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks); NSPR_API(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks); PR_END_EXTERN_C #endif /* !defined(prinrval_h) */ /* prinrval.h */ nspr-4.11/nspr/pr/include/prio.h0000644000000000000000000022705612623070344014734 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: prio.h * * Description: PR i/o related stuff, such as file system access, file * i/o, socket i/o, etc. */ #ifndef prio_h___ #define prio_h___ #include "prlong.h" #include "prtime.h" #include "prinrval.h" #include "prinet.h" PR_BEGIN_EXTERN_C /* Typedefs */ typedef struct PRDir PRDir; typedef struct PRDirEntry PRDirEntry; #ifdef MOZ_UNICODE typedef struct PRDirUTF16 PRDirUTF16; typedef struct PRDirEntryUTF16 PRDirEntryUTF16; #endif /* MOZ_UNICODE */ typedef struct PRFileDesc PRFileDesc; typedef struct PRFileInfo PRFileInfo; typedef struct PRFileInfo64 PRFileInfo64; typedef union PRNetAddr PRNetAddr; typedef struct PRIOMethods PRIOMethods; typedef struct PRPollDesc PRPollDesc; typedef struct PRFilePrivate PRFilePrivate; typedef struct PRSendFileData PRSendFileData; /* *************************************************************************** ** The file descriptor. ** This is the primary structure to represent any active open socket, ** whether it be a normal file or a network connection. Such objects ** are stackable (or layerable). Each layer may have its own set of ** method pointers and context private to that layer. All each layer ** knows about its neighbors is how to get to their method table. *************************************************************************** */ typedef PRIntn PRDescIdentity; /* see: Layering file descriptors */ struct PRFileDesc { const PRIOMethods *methods; /* the I/O methods table */ PRFilePrivate *secret; /* layer dependent data */ PRFileDesc *lower, *higher; /* pointers to adjacent layers */ void (PR_CALLBACK *dtor)(PRFileDesc *fd); /* A destructor function for layer */ PRDescIdentity identity; /* Identity of this particular layer */ }; /* *************************************************************************** ** PRTransmitFileFlags ** ** Flags for PR_TransmitFile. Pass PR_TRANSMITFILE_CLOSE_SOCKET to ** PR_TransmitFile if the connection should be closed after the file ** is transmitted. *************************************************************************** */ typedef enum PRTransmitFileFlags { PR_TRANSMITFILE_KEEP_OPEN = 0, /* socket is left open after file * is transmitted. */ PR_TRANSMITFILE_CLOSE_SOCKET = 1 /* socket is closed after file * is transmitted. */ } PRTransmitFileFlags; /* ************************************************************************** ** Macros for PRNetAddr ** ** Address families: PR_AF_INET, PR_AF_INET6, PR_AF_LOCAL ** IP addresses: PR_INADDR_ANY, PR_INADDR_LOOPBACK, PR_INADDR_BROADCAST ************************************************************************** */ #ifdef WIN32 #define PR_AF_INET 2 #define PR_AF_LOCAL 1 #define PR_INADDR_ANY (unsigned long)0x00000000 #define PR_INADDR_LOOPBACK 0x7f000001 #define PR_INADDR_BROADCAST (unsigned long)0xffffffff #else /* WIN32 */ #define PR_AF_INET AF_INET #define PR_AF_LOCAL AF_UNIX #define PR_INADDR_ANY INADDR_ANY #define PR_INADDR_LOOPBACK INADDR_LOOPBACK #define PR_INADDR_BROADCAST INADDR_BROADCAST #endif /* WIN32 */ /* ** Define PR_AF_INET6 in prcpucfg.h with the same ** value as AF_INET6 on platforms with IPv6 support. ** Otherwise define it here. */ #ifndef PR_AF_INET6 #define PR_AF_INET6 100 #endif #define PR_AF_INET_SDP 101 #define PR_AF_INET6_SDP 102 #ifndef PR_AF_UNSPEC #define PR_AF_UNSPEC 0 #endif /* ************************************************************************** ** A network address ** ** Only Internet Protocol (IPv4 and IPv6) addresses are supported. ** The address family must always represent IPv4 (AF_INET, probably == 2) ** or IPv6 (AF_INET6). ************************************************************************** *************************************************************************/ struct PRIPv6Addr { union { PRUint8 _S6_u8[16]; PRUint16 _S6_u16[8]; PRUint32 _S6_u32[4]; PRUint64 _S6_u64[2]; } _S6_un; }; #define pr_s6_addr _S6_un._S6_u8 #define pr_s6_addr16 _S6_un._S6_u16 #define pr_s6_addr32 _S6_un._S6_u32 #define pr_s6_addr64 _S6_un._S6_u64 typedef struct PRIPv6Addr PRIPv6Addr; union PRNetAddr { struct { PRUint16 family; /* address family (0x00ff maskable) */ #ifdef XP_BEOS char data[10]; /* Be has a smaller structure */ #else char data[14]; /* raw address data */ #endif } raw; struct { PRUint16 family; /* address family (AF_INET) */ PRUint16 port; /* port number */ PRUint32 ip; /* The actual 32 bits of address */ #ifdef XP_BEOS char pad[4]; /* Be has a smaller structure */ #else char pad[8]; #endif } inet; struct { PRUint16 family; /* address family (AF_INET6) */ PRUint16 port; /* port number */ PRUint32 flowinfo; /* routing information */ PRIPv6Addr ip; /* the actual 128 bits of address */ PRUint32 scope_id; /* set of interfaces for a scope */ } ipv6; #if defined(XP_UNIX) || defined(XP_OS2) struct { /* Unix domain socket address */ PRUint16 family; /* address family (AF_UNIX) */ #ifdef XP_OS2 char path[108]; /* null-terminated pathname */ /* bind fails if size is not 108. */ #else char path[104]; /* null-terminated pathname */ #endif } local; #endif }; /* *************************************************************************** ** PRSockOption ** ** The file descriptors can have predefined options set after they file ** descriptor is created to change their behavior. Only the options in ** the following enumeration are supported. *************************************************************************** */ typedef enum PRSockOption { PR_SockOpt_Nonblocking, /* nonblocking io */ PR_SockOpt_Linger, /* linger on close if data present */ PR_SockOpt_Reuseaddr, /* allow local address reuse */ PR_SockOpt_Keepalive, /* keep connections alive */ PR_SockOpt_RecvBufferSize, /* send buffer size */ PR_SockOpt_SendBufferSize, /* receive buffer size */ PR_SockOpt_IpTimeToLive, /* time to live */ PR_SockOpt_IpTypeOfService, /* type of service and precedence */ PR_SockOpt_AddMember, /* add an IP group membership */ PR_SockOpt_DropMember, /* drop an IP group membership */ PR_SockOpt_McastInterface, /* multicast interface address */ PR_SockOpt_McastTimeToLive, /* multicast timetolive */ PR_SockOpt_McastLoopback, /* multicast loopback */ PR_SockOpt_NoDelay, /* don't delay send to coalesce packets */ PR_SockOpt_MaxSegment, /* maximum segment size */ PR_SockOpt_Broadcast, /* enable broadcast */ PR_SockOpt_Reuseport, /* allow local address & port reuse on * platforms that support it */ PR_SockOpt_Last } PRSockOption; typedef struct PRLinger { PRBool polarity; /* Polarity of the option's setting */ PRIntervalTime linger; /* Time to linger before closing */ } PRLinger; typedef struct PRMcastRequest { PRNetAddr mcaddr; /* IP multicast address of group */ PRNetAddr ifaddr; /* local IP address of interface */ } PRMcastRequest; typedef struct PRSocketOptionData { PRSockOption option; union { PRUintn ip_ttl; /* IP time to live */ PRUintn mcast_ttl; /* IP multicast time to live */ PRUintn tos; /* IP type of service and precedence */ PRBool non_blocking; /* Non-blocking (network) I/O */ PRBool reuse_addr; /* Allow local address reuse */ PRBool reuse_port; /* Allow local address & port reuse on * platforms that support it */ PRBool keep_alive; /* Keep connections alive */ PRBool mcast_loopback; /* IP multicast loopback */ PRBool no_delay; /* Don't delay send to coalesce packets */ PRBool broadcast; /* Enable broadcast */ PRSize max_segment; /* Maximum segment size */ PRSize recv_buffer_size; /* Receive buffer size */ PRSize send_buffer_size; /* Send buffer size */ PRLinger linger; /* Time to linger on close if data present */ PRMcastRequest add_member; /* add an IP group membership */ PRMcastRequest drop_member; /* Drop an IP group membership */ PRNetAddr mcast_if; /* multicast interface address */ } value; } PRSocketOptionData; /* *************************************************************************** ** PRIOVec ** ** The I/O vector is used by the write vector method to describe the areas ** that are affected by the ouput operation. *************************************************************************** */ typedef struct PRIOVec { char *iov_base; int iov_len; } PRIOVec; /* *************************************************************************** ** Discover what type of socket is being described by the file descriptor. *************************************************************************** */ typedef enum PRDescType { PR_DESC_FILE = 1, PR_DESC_SOCKET_TCP = 2, PR_DESC_SOCKET_UDP = 3, PR_DESC_LAYERED = 4, PR_DESC_PIPE = 5 } PRDescType; typedef enum PRSeekWhence { PR_SEEK_SET = 0, PR_SEEK_CUR = 1, PR_SEEK_END = 2 } PRSeekWhence; NSPR_API(PRDescType) PR_GetDescType(PRFileDesc *file); /* *************************************************************************** ** PRIOMethods ** ** The I/O methods table provides procedural access to the functions of ** the file descriptor. It is the responsibility of a layer implementor ** to provide suitable functions at every entry point. If a layer provides ** no functionality, it should call the next lower(higher) function of the ** same name (e.g., return fd->lower->method->close(fd->lower)); ** ** Not all functions are implemented for all types of files. In cases where ** that is true, the function will return a error indication with an error ** code of PR_INVALID_METHOD_ERROR. *************************************************************************** */ typedef PRStatus (PR_CALLBACK *PRCloseFN)(PRFileDesc *fd); typedef PRInt32 (PR_CALLBACK *PRReadFN)(PRFileDesc *fd, void *buf, PRInt32 amount); typedef PRInt32 (PR_CALLBACK *PRWriteFN)(PRFileDesc *fd, const void *buf, PRInt32 amount); typedef PRInt32 (PR_CALLBACK *PRAvailableFN)(PRFileDesc *fd); typedef PRInt64 (PR_CALLBACK *PRAvailable64FN)(PRFileDesc *fd); typedef PRStatus (PR_CALLBACK *PRFsyncFN)(PRFileDesc *fd); typedef PROffset32 (PR_CALLBACK *PRSeekFN)(PRFileDesc *fd, PROffset32 offset, PRSeekWhence how); typedef PROffset64 (PR_CALLBACK *PRSeek64FN)(PRFileDesc *fd, PROffset64 offset, PRSeekWhence how); typedef PRStatus (PR_CALLBACK *PRFileInfoFN)(PRFileDesc *fd, PRFileInfo *info); typedef PRStatus (PR_CALLBACK *PRFileInfo64FN)(PRFileDesc *fd, PRFileInfo64 *info); typedef PRInt32 (PR_CALLBACK *PRWritevFN)( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); typedef PRStatus (PR_CALLBACK *PRConnectFN)( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout); typedef PRFileDesc* (PR_CALLBACK *PRAcceptFN) ( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout); typedef PRStatus (PR_CALLBACK *PRBindFN)(PRFileDesc *fd, const PRNetAddr *addr); typedef PRStatus (PR_CALLBACK *PRListenFN)(PRFileDesc *fd, PRIntn backlog); typedef PRStatus (PR_CALLBACK *PRShutdownFN)(PRFileDesc *fd, PRIntn how); typedef PRInt32 (PR_CALLBACK *PRRecvFN)( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); typedef PRInt32 (PR_CALLBACK *PRSendFN) ( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); typedef PRInt32 (PR_CALLBACK *PRRecvfromFN)( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout); typedef PRInt32 (PR_CALLBACK *PRSendtoFN)( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout); typedef PRInt16 (PR_CALLBACK *PRPollFN)( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags); typedef PRInt32 (PR_CALLBACK *PRAcceptreadFN)( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime t); typedef PRInt32 (PR_CALLBACK *PRTransmitfileFN)( PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime t); typedef PRStatus (PR_CALLBACK *PRGetsocknameFN)(PRFileDesc *fd, PRNetAddr *addr); typedef PRStatus (PR_CALLBACK *PRGetpeernameFN)(PRFileDesc *fd, PRNetAddr *addr); typedef PRStatus (PR_CALLBACK *PRGetsocketoptionFN)( PRFileDesc *fd, PRSocketOptionData *data); typedef PRStatus (PR_CALLBACK *PRSetsocketoptionFN)( PRFileDesc *fd, const PRSocketOptionData *data); typedef PRInt32 (PR_CALLBACK *PRSendfileFN)( PRFileDesc *networkSocket, PRSendFileData *sendData, PRTransmitFileFlags flags, PRIntervalTime timeout); typedef PRStatus (PR_CALLBACK *PRConnectcontinueFN)( PRFileDesc *fd, PRInt16 out_flags); typedef PRIntn (PR_CALLBACK *PRReservedFN)(PRFileDesc *fd); struct PRIOMethods { PRDescType file_type; /* Type of file represented (tos) */ PRCloseFN close; /* close file and destroy descriptor */ PRReadFN read; /* read up to specified bytes into buffer */ PRWriteFN write; /* write specified bytes from buffer */ PRAvailableFN available; /* determine number of bytes available */ PRAvailable64FN available64; /* ditto, 64 bit */ PRFsyncFN fsync; /* flush all buffers to permanent store */ PRSeekFN seek; /* position the file to the desired place */ PRSeek64FN seek64; /* ditto, 64 bit */ PRFileInfoFN fileInfo; /* Get information about an open file */ PRFileInfo64FN fileInfo64; /* ditto, 64 bit */ PRWritevFN writev; /* Write segments as described by iovector */ PRConnectFN connect; /* Connect to the specified (net) address */ PRAcceptFN accept; /* Accept a connection for a (net) peer */ PRBindFN bind; /* Associate a (net) address with the fd */ PRListenFN listen; /* Prepare to listen for (net) connections */ PRShutdownFN shutdown; /* Shutdown a (net) connection */ PRRecvFN recv; /* Solicit up the the specified bytes */ PRSendFN send; /* Send all the bytes specified */ PRRecvfromFN recvfrom; /* Solicit (net) bytes and report source */ PRSendtoFN sendto; /* Send bytes to (net) address specified */ PRPollFN poll; /* Test the fd to see if it is ready */ PRAcceptreadFN acceptread; /* Accept and read on a new (net) fd */ PRTransmitfileFN transmitfile; /* Transmit at entire file */ PRGetsocknameFN getsockname; /* Get (net) address associated with fd */ PRGetpeernameFN getpeername; /* Get peer's (net) address */ PRReservedFN reserved_fn_6; /* reserved for future use */ PRReservedFN reserved_fn_5; /* reserved for future use */ PRGetsocketoptionFN getsocketoption; /* Get current setting of specified option */ PRSetsocketoptionFN setsocketoption; /* Set value of specified option */ PRSendfileFN sendfile; /* Send a (partial) file with header/trailer*/ PRConnectcontinueFN connectcontinue; /* Continue a nonblocking connect */ PRReservedFN reserved_fn_3; /* reserved for future use */ PRReservedFN reserved_fn_2; /* reserved for future use */ PRReservedFN reserved_fn_1; /* reserved for future use */ PRReservedFN reserved_fn_0; /* reserved for future use */ }; /* ************************************************************************** * FUNCTION: PR_GetSpecialFD * DESCRIPTION: Get the file descriptor that represents the standard input, * output, or error stream. * INPUTS: * PRSpecialFD id * A value indicating the type of stream desired: * PR_StandardInput: standard input * PR_StandardOuput: standard output * PR_StandardError: standard error * OUTPUTS: none * RETURNS: PRFileDesc * * If the argument is valid, PR_GetSpecialFD returns a file descriptor * that represents the corresponding standard I/O stream. Otherwise, * PR_GetSpecialFD returns NULL and sets error PR_INVALID_ARGUMENT_ERROR. ************************************************************************** */ typedef enum PRSpecialFD { PR_StandardInput, /* standard input */ PR_StandardOutput, /* standard output */ PR_StandardError /* standard error */ } PRSpecialFD; NSPR_API(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD id); #define PR_STDIN PR_GetSpecialFD(PR_StandardInput) #define PR_STDOUT PR_GetSpecialFD(PR_StandardOutput) #define PR_STDERR PR_GetSpecialFD(PR_StandardError) /* ************************************************************************** * Layering file descriptors * * File descriptors may be layered. Each layer has it's own identity. * Identities are allocated by the runtime and are to be associated * (by the layer implementor) with all layers that are of that type. * It is then possible to scan the chain of layers and find a layer * that one recongizes and therefore predict that it will implement * a desired protocol. * * There are three well-known identities: * PR_INVALID_IO_LAYER => an invalid layer identity, for error return * PR_TOP_IO_LAYER => the identity of the top of the stack * PR_NSPR_IO_LAYER => the identity used by NSPR proper * PR_TOP_IO_LAYER may be used as a shorthand for identifying the topmost * layer of an existing stack. Ie., the following two constructs are * equivalent. * * rv = PR_PushIOLayer(stack, PR_TOP_IO_LAYER, my_layer); * rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), my_layer) * * A string may be associated with the creation of the identity. It * will be copied by the runtime. If queried the runtime will return * a reference to that copied string (not yet another copy). There * is no facility for deleting an identity. ************************************************************************** */ #define PR_IO_LAYER_HEAD (PRDescIdentity)-3 #define PR_INVALID_IO_LAYER (PRDescIdentity)-1 #define PR_TOP_IO_LAYER (PRDescIdentity)-2 #define PR_NSPR_IO_LAYER (PRDescIdentity)0 NSPR_API(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name); NSPR_API(const char*) PR_GetNameForIdentity(PRDescIdentity ident); NSPR_API(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd); NSPR_API(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd_stack, PRDescIdentity id); /* ************************************************************************** * PR_GetDefaultIOMethods: Accessing the default methods table. * You may get a pointer to the default methods table by calling this function. * You may then select any elements from that table with which to build your * layer's methods table. You may NOT modify the table directly. ************************************************************************** */ NSPR_API(const PRIOMethods *) PR_GetDefaultIOMethods(void); /* ************************************************************************** * Creating a layer * * A new layer may be allocated by calling PR_CreateIOLayerStub(). The * file descriptor returned will contain the pointer to the methods table * provided. The runtime will not modify the table nor test its correctness. ************************************************************************** */ NSPR_API(PRFileDesc*) PR_CreateIOLayerStub( PRDescIdentity ident, const PRIOMethods *methods); /* ************************************************************************** * Creating a layer * * A new stack may be created by calling PR_CreateIOLayer(). The * file descriptor returned will point to the top of the stack, which has * the layer 'fd' as the topmost layer. * * NOTE: This function creates a new style stack, which has a fixed, dummy * header. The old style stack, created by a call to PR_PushIOLayer, * results in modifying contents of the top layer of the stack, when * pushing and popping layers of the stack. ************************************************************************** */ NSPR_API(PRFileDesc*) PR_CreateIOLayer(PRFileDesc* fd); /* ************************************************************************** * Pushing a layer * * A file descriptor (perhaps allocated using PR_CreateIOLayerStub()) may * be pushed into an existing stack of file descriptors at any point the * caller deems appropriate. The new layer will be inserted into the stack * just above the layer with the indicated identity. * * Note: Even if the identity parameter indicates the top-most layer of * the stack, the value of the file descriptor describing the original * stack will not change. ************************************************************************** */ NSPR_API(PRStatus) PR_PushIOLayer( PRFileDesc *fd_stack, PRDescIdentity id, PRFileDesc *layer); /* ************************************************************************** * Popping a layer * * A layer may be popped from a stack by indicating the identity of the * layer to be removed. If found, a pointer to the removed object will * be returned to the caller. The object then becomes the responsibility * of the caller. * * Note: Even if the identity indicates the top layer of the stack, the * reference returned will not be the file descriptor for the stack and * that file descriptor will remain valid. ************************************************************************** */ NSPR_API(PRFileDesc*) PR_PopIOLayer(PRFileDesc *fd_stack, PRDescIdentity id); /* ************************************************************************** * FUNCTION: PR_Open * DESCRIPTION: Open a file for reading, writing, or both. * INPUTS: * const char *name * The path name of the file to be opened * PRIntn flags * The file status flags. * It is a bitwise OR of the following bit flags (only one of * the first three flags below may be used): * PR_RDONLY Open for reading only. * PR_WRONLY Open for writing only. * PR_RDWR Open for reading and writing. * PR_CREATE_FILE If the file does not exist, the file is created * If the file exists, this flag has no effect. * PR_SYNC If set, each write will wait for both the file data * and file status to be physically updated. * PR_APPEND The file pointer is set to the end of * the file prior to each write. * PR_TRUNCATE If the file exists, its length is truncated to 0. * PR_EXCL With PR_CREATE_FILE, if the file does not exist, * the file is created. If the file already * exists, no action and NULL is returned * * PRIntn mode * The access permission bits of the file mode, if the file is * created when PR_CREATE_FILE is on. * OUTPUTS: None * RETURNS: PRFileDesc * * If the file is successfully opened, * returns a pointer to the PRFileDesc * created for the newly opened file. * Returns a NULL pointer if the open * failed. * SIDE EFFECTS: * RESTRICTIONS: * MEMORY: * The return value, if not NULL, points to a dynamically allocated * PRFileDesc object. * ALGORITHM: ************************************************************************** */ /* Open flags */ #define PR_RDONLY 0x01 #define PR_WRONLY 0x02 #define PR_RDWR 0x04 #define PR_CREATE_FILE 0x08 #define PR_APPEND 0x10 #define PR_TRUNCATE 0x20 #define PR_SYNC 0x40 #define PR_EXCL 0x80 /* ** File modes .... ** ** CAVEAT: 'mode' is currently only applicable on UNIX platforms. ** The 'mode' argument may be ignored by PR_Open on other platforms. ** ** 00400 Read by owner. ** 00200 Write by owner. ** 00100 Execute (search if a directory) by owner. ** 00040 Read by group. ** 00020 Write by group. ** 00010 Execute by group. ** 00004 Read by others. ** 00002 Write by others ** 00001 Execute by others. ** */ NSPR_API(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode); /* ************************************************************************** * FUNCTION: PR_OpenFile * DESCRIPTION: * Open a file for reading, writing, or both. * PR_OpenFile has the same prototype as PR_Open but implements * the specified file mode where possible. ************************************************************************** */ /* File mode bits */ #define PR_IRWXU 00700 /* read, write, execute/search by owner */ #define PR_IRUSR 00400 /* read permission, owner */ #define PR_IWUSR 00200 /* write permission, owner */ #define PR_IXUSR 00100 /* execute/search permission, owner */ #define PR_IRWXG 00070 /* read, write, execute/search by group */ #define PR_IRGRP 00040 /* read permission, group */ #define PR_IWGRP 00020 /* write permission, group */ #define PR_IXGRP 00010 /* execute/search permission, group */ #define PR_IRWXO 00007 /* read, write, execute/search by others */ #define PR_IROTH 00004 /* read permission, others */ #define PR_IWOTH 00002 /* write permission, others */ #define PR_IXOTH 00001 /* execute/search permission, others */ NSPR_API(PRFileDesc*) PR_OpenFile( const char *name, PRIntn flags, PRIntn mode); #ifdef MOZ_UNICODE /* * EXPERIMENTAL: This function may be removed in a future release. */ NSPR_API(PRFileDesc*) PR_OpenFileUTF16( const PRUnichar *name, PRIntn flags, PRIntn mode); #endif /* MOZ_UNICODE */ /* ************************************************************************** * FUNCTION: PR_Close * DESCRIPTION: * Close a file or socket. * INPUTS: * PRFileDesc *fd * a pointer to a PRFileDesc. * OUTPUTS: * None. * RETURN: * PRStatus * SIDE EFFECTS: * RESTRICTIONS: * None. * MEMORY: * The dynamic memory pointed to by the argument fd is freed. ************************************************************************** */ NSPR_API(PRStatus) PR_Close(PRFileDesc *fd); /* ************************************************************************** * FUNCTION: PR_Read * DESCRIPTION: * Read bytes from a file or socket. * The operation will block until either an end of stream indication is * encountered, some positive number of bytes are transferred, or there * is an error. No more than 'amount' bytes will be transferred. * INPUTS: * PRFileDesc *fd * pointer to the PRFileDesc object for the file or socket * void *buf * pointer to a buffer to hold the data read in. * PRInt32 amount * the size of 'buf' (in bytes) * OUTPUTS: * RETURN: * PRInt32 * a positive number indicates the number of bytes actually read in. * 0 means end of file is reached or the network connection is closed. * -1 indicates a failure. The reason for the failure is obtained * by calling PR_GetError(). * SIDE EFFECTS: * data is written into the buffer pointed to by 'buf'. * RESTRICTIONS: * None. * MEMORY: * N/A * ALGORITHM: * N/A ************************************************************************** */ NSPR_API(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount); /* *************************************************************************** * FUNCTION: PR_Write * DESCRIPTION: * Write a specified number of bytes to a file or socket. The thread * invoking this function blocks until all the data is written. * INPUTS: * PRFileDesc *fd * pointer to a PRFileDesc object that refers to a file or socket * const void *buf * pointer to the buffer holding the data * PRInt32 amount * amount of data in bytes to be written from the buffer * OUTPUTS: * None. * RETURN: PRInt32 * A positive number indicates the number of bytes successfully written. * A -1 is an indication that the operation failed. The reason * for the failure is obtained by calling PR_GetError(). *************************************************************************** */ NSPR_API(PRInt32) PR_Write(PRFileDesc *fd,const void *buf,PRInt32 amount); /* *************************************************************************** * FUNCTION: PR_Writev * DESCRIPTION: * Write data to a socket. The data is organized in a PRIOVec array. The * operation will block until all the data is written or the operation * fails. * INPUTS: * PRFileDesc *fd * Pointer that points to a PRFileDesc object for a socket. * const PRIOVec *iov * An array of PRIOVec. PRIOVec is a struct with the following * two fields: * char *iov_base; * int iov_len; * PRInt32 iov_size * Number of elements in the iov array. The value of this * argument must not be greater than PR_MAX_IOVECTOR_SIZE. * If it is, the method will fail (PR_BUFFER_OVERFLOW_ERROR). * PRIntervalTime timeout * Time limit for completion of the entire write operation. * OUTPUTS: * None * RETURN: * A positive number indicates the number of bytes successfully written. * A -1 is an indication that the operation failed. The reason * for the failure is obtained by calling PR_GetError(). *************************************************************************** */ #define PR_MAX_IOVECTOR_SIZE 16 /* 'iov_size' must be <= */ NSPR_API(PRInt32) PR_Writev( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); /* *************************************************************************** * FUNCTION: PR_Delete * DESCRIPTION: * Delete a file from the filesystem. The operation may fail if the * file is open. * INPUTS: * const char *name * Path name of the file to be deleted. * OUTPUTS: * None. * RETURN: PRStatus * The function returns PR_SUCCESS if the file is successfully * deleted, otherwise it returns PR_FAILURE. *************************************************************************** */ NSPR_API(PRStatus) PR_Delete(const char *name); /**************************************************************************/ typedef enum PRFileType { PR_FILE_FILE = 1, PR_FILE_DIRECTORY = 2, PR_FILE_OTHER = 3 } PRFileType; struct PRFileInfo { PRFileType type; /* Type of file */ PROffset32 size; /* Size, in bytes, of file's contents */ PRTime creationTime; /* Creation time per definition of PRTime */ PRTime modifyTime; /* Last modification time per definition of PRTime */ }; struct PRFileInfo64 { PRFileType type; /* Type of file */ PROffset64 size; /* Size, in bytes, of file's contents */ PRTime creationTime; /* Creation time per definition of PRTime */ PRTime modifyTime; /* Last modification time per definition of PRTime */ }; /**************************************************************************** * FUNCTION: PR_GetFileInfo, PR_GetFileInfo64 * DESCRIPTION: * Get the information about the file with the given path name. This is * applicable only to NSFileDesc describing 'file' types (see * INPUTS: * const char *fn * path name of the file * OUTPUTS: * PRFileInfo *info * Information about the given file is written into the file * information object pointer to by 'info'. * RETURN: PRStatus * PR_GetFileInfo returns PR_SUCCESS if file information is successfully * obtained, otherwise it returns PR_FAILURE. *************************************************************************** */ NSPR_API(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info); NSPR_API(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info); #ifdef MOZ_UNICODE /* * EXPERIMENTAL: This function may be removed in a future release. */ NSPR_API(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info); #endif /* MOZ_UNICODE */ /* ************************************************************************** * FUNCTION: PR_GetOpenFileInfo, PR_GetOpenFileInfo64 * DESCRIPTION: * Get information about an open file referred to by the * given PRFileDesc object. * INPUTS: * const PRFileDesc *fd * A reference to a valid, open file. * OUTPUTS: * Same as PR_GetFileInfo, PR_GetFileInfo64 * RETURN: PRStatus * PR_GetFileInfo returns PR_SUCCESS if file information is successfully * obtained, otherwise it returns PR_FAILURE. *************************************************************************** */ NSPR_API(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info); NSPR_API(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info); /* ************************************************************************** * FUNCTION: PR_Rename * DESCRIPTION: * Rename a file from the old name 'from' to the new name 'to'. * INPUTS: * const char *from * The old name of the file to be renamed. * const char *to * The new name of the file. * OUTPUTS: * None. * RETURN: PRStatus ************************************************************************** */ NSPR_API(PRStatus) PR_Rename(const char *from, const char *to); /* ************************************************************************* * FUNCTION: PR_Access * DESCRIPTION: * Determine accessibility of a file. * INPUTS: * const char *name * path name of the file * PRAccessHow how * specifies which access permission to check for. * It can be one of the following values: * PR_ACCESS_READ_OK Test for read permission * PR_ACCESS_WRITE_OK Test for write permission * PR_ACCESS_EXISTS Check existence of file * OUTPUTS: * None. * RETURN: PRStatus * PR_SUCCESS is returned if the requested access is permitted. * Otherwise, PR_FAILURE is returned. Additional information * regarding the reason for the failure may be retrieved from * PR_GetError(). ************************************************************************* */ typedef enum PRAccessHow { PR_ACCESS_EXISTS = 1, PR_ACCESS_WRITE_OK = 2, PR_ACCESS_READ_OK = 3 } PRAccessHow; NSPR_API(PRStatus) PR_Access(const char *name, PRAccessHow how); /* ************************************************************************* * FUNCTION: PR_Seek, PR_Seek64 * DESCRIPTION: * Moves read-write file offset * INPUTS: * PRFileDesc *fd * Pointer to a PRFileDesc object. * PROffset32, PROffset64 offset * Specifies a value, in bytes, that is used in conjunction * with the 'whence' parameter to set the file pointer. A * negative value causes seeking in the reverse direction. * PRSeekWhence whence * Specifies how to interpret the 'offset' parameter in setting * the file pointer associated with the 'fd' parameter. * Values for the 'whence' parameter are: * PR_SEEK_SET Sets the file pointer to the value of the * 'offset' parameter * PR_SEEK_CUR Sets the file pointer to its current location * plus the value of the offset parameter. * PR_SEEK_END Sets the file pointer to the size of the * file plus the value of the offset parameter. * OUTPUTS: * None. * RETURN: PROffset32, PROffset64 * Upon successful completion, the resulting pointer location, * measured in bytes from the beginning of the file, is returned. * If the PR_Seek() function fails, the file offset remains * unchanged, and the returned value is -1. The error code can * then be retrieved via PR_GetError(). ************************************************************************* */ NSPR_API(PROffset32) PR_Seek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence); NSPR_API(PROffset64) PR_Seek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence); /* ************************************************************************ * FUNCTION: PR_Available * DESCRIPTION: * Determine the amount of data in bytes available for reading * in the given file or socket. * INPUTS: * PRFileDesc *fd * Pointer to a PRFileDesc object that refers to a file or * socket. * OUTPUTS: * None * RETURN: PRInt32, PRInt64 * Upon successful completion, PR_Available returns the number of * bytes beyond the current read pointer that is available for * reading. Otherwise, it returns a -1 and the reason for the * failure can be retrieved via PR_GetError(). ************************************************************************ */ NSPR_API(PRInt32) PR_Available(PRFileDesc *fd); NSPR_API(PRInt64) PR_Available64(PRFileDesc *fd); /* ************************************************************************ * FUNCTION: PR_Sync * DESCRIPTION: * Sync any buffered data for a fd to its backing device (disk). * INPUTS: * PRFileDesc *fd * Pointer to a PRFileDesc object that refers to a file or * socket * OUTPUTS: * None * RETURN: PRStatus * PR_SUCCESS is returned if the requested access is permitted. * Otherwise, PR_FAILURE is returned. ************************************************************************ */ NSPR_API(PRStatus) PR_Sync(PRFileDesc *fd); /************************************************************************/ struct PRDirEntry { const char *name; /* name of entry, relative to directory name */ }; #ifdef MOZ_UNICODE struct PRDirEntryUTF16 { const PRUnichar *name; /* name of entry in UTF16, relative to * directory name */ }; #endif /* MOZ_UNICODE */ #if !defined(NO_NSPR_10_SUPPORT) #define PR_DirName(dirEntry) (dirEntry->name) #endif /* ************************************************************************* * FUNCTION: PR_OpenDir * DESCRIPTION: * Open the directory by the given name * INPUTS: * const char *name * path name of the directory to be opened * OUTPUTS: * None * RETURN: PRDir * * If the directory is sucessfully opened, a PRDir object is * dynamically allocated and a pointer to it is returned. * If the directory cannot be opened, a NULL pointer is returned. * MEMORY: * Upon successful completion, the return value points to * dynamically allocated memory. ************************************************************************* */ NSPR_API(PRDir*) PR_OpenDir(const char *name); #ifdef MOZ_UNICODE /* * EXPERIMENTAL: This function may be removed in a future release. */ NSPR_API(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name); #endif /* MOZ_UNICODE */ /* ************************************************************************* * FUNCTION: PR_ReadDir * DESCRIPTION: * INPUTS: * PRDir *dir * pointer to a PRDir object that designates an open directory * PRDirFlags flags * PR_SKIP_NONE Do not skip any files * PR_SKIP_DOT Skip the directory entry "." that * represents the current directory * PR_SKIP_DOT_DOT Skip the directory entry ".." that * represents the parent directory. * PR_SKIP_BOTH Skip both '.' and '..' * PR_SKIP_HIDDEN Skip hidden files * OUTPUTS: * RETURN: PRDirEntry* * Returns a pointer to the next entry in the directory. Returns * a NULL pointer upon reaching the end of the directory or when an * error occurs. The actual reason can be retrieved via PR_GetError(). ************************************************************************* */ typedef enum PRDirFlags { PR_SKIP_NONE = 0x0, PR_SKIP_DOT = 0x1, PR_SKIP_DOT_DOT = 0x2, PR_SKIP_BOTH = 0x3, PR_SKIP_HIDDEN = 0x4 } PRDirFlags; NSPR_API(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags); #ifdef MOZ_UNICODE /* * EXPERIMENTAL: This function may be removed in a future release. */ NSPR_API(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags); #endif /* MOZ_UNICODE */ /* ************************************************************************* * FUNCTION: PR_CloseDir * DESCRIPTION: * Close the specified directory. * INPUTS: * PRDir *dir * The directory to be closed. * OUTPUTS: * None * RETURN: PRStatus * If successful, will return a status of PR_SUCCESS. Otherwise * a value of PR_FAILURE. The reason for the failure may be re- * trieved using PR_GetError(). ************************************************************************* */ NSPR_API(PRStatus) PR_CloseDir(PRDir *dir); #ifdef MOZ_UNICODE /* * EXPERIMENTAL: This function may be removed in a future release. */ NSPR_API(PRStatus) PR_CloseDirUTF16(PRDirUTF16 *dir); #endif /* MOZ_UNICODE */ /* ************************************************************************* * FUNCTION: PR_MkDir * DESCRIPTION: * Create a new directory with the given name and access mode. * INPUTS: * const char *name * The name of the directory to be created. All the path components * up to but not including the leaf component must already exist. * PRIntn mode * See 'mode' definiton in PR_Open(). * OUTPUTS: * None * RETURN: PRStatus * If successful, will return a status of PR_SUCCESS. Otherwise * a value of PR_FAILURE. The reason for the failure may be re- * trieved using PR_GetError(). ************************************************************************* */ NSPR_API(PRStatus) PR_MkDir(const char *name, PRIntn mode); /* ************************************************************************* * FUNCTION: PR_MakeDir * DESCRIPTION: * Create a new directory with the given name and access mode. * PR_MakeDir has the same prototype as PR_MkDir but implements * the specified access mode where possible. ************************************************************************* */ NSPR_API(PRStatus) PR_MakeDir(const char *name, PRIntn mode); /* ************************************************************************* * FUNCTION: PR_RmDir * DESCRIPTION: * Remove a directory by the given name. * INPUTS: * const char *name * The name of the directory to be removed. All the path components * must already exist. Only the leaf component will be removed. * OUTPUTS: * None * RETURN: PRStatus * If successful, will return a status of PR_SUCCESS. Otherwise * a value of PR_FAILURE. The reason for the failure may be re- * trieved using PR_GetError(). ************************************************************************** */ NSPR_API(PRStatus) PR_RmDir(const char *name); /* ************************************************************************* * FUNCTION: PR_NewUDPSocket * DESCRIPTION: * Create a new UDP socket. * INPUTS: * None * OUTPUTS: * None * RETURN: PRFileDesc* * Upon successful completion, PR_NewUDPSocket returns a pointer * to the PRFileDesc created for the newly opened UDP socket. * Returns a NULL pointer if the creation of a new UDP socket failed. * ************************************************************************** */ NSPR_API(PRFileDesc*) PR_NewUDPSocket(void); /* ************************************************************************* * FUNCTION: PR_NewTCPSocket * DESCRIPTION: * Create a new TCP socket. * INPUTS: * None * OUTPUTS: * None * RETURN: PRFileDesc* * Upon successful completion, PR_NewTCPSocket returns a pointer * to the PRFileDesc created for the newly opened TCP socket. * Returns a NULL pointer if the creation of a new TCP socket failed. * ************************************************************************** */ NSPR_API(PRFileDesc*) PR_NewTCPSocket(void); /* ************************************************************************* * FUNCTION: PR_OpenUDPSocket * DESCRIPTION: * Create a new UDP socket of the specified address family. * INPUTS: * PRIntn af * Address family * OUTPUTS: * None * RETURN: PRFileDesc* * Upon successful completion, PR_OpenUDPSocket returns a pointer * to the PRFileDesc created for the newly opened UDP socket. * Returns a NULL pointer if the creation of a new UDP socket failed. * ************************************************************************** */ NSPR_API(PRFileDesc*) PR_OpenUDPSocket(PRIntn af); /* ************************************************************************* * FUNCTION: PR_OpenTCPSocket * DESCRIPTION: * Create a new TCP socket of the specified address family. * INPUTS: * PRIntn af * Address family * OUTPUTS: * None * RETURN: PRFileDesc* * Upon successful completion, PR_NewTCPSocket returns a pointer * to the PRFileDesc created for the newly opened TCP socket. * Returns a NULL pointer if the creation of a new TCP socket failed. * ************************************************************************** */ NSPR_API(PRFileDesc*) PR_OpenTCPSocket(PRIntn af); /* ************************************************************************* * FUNCTION: PR_Connect * DESCRIPTION: * Initiate a connection on a socket. * INPUTS: * PRFileDesc *fd * Points to a PRFileDesc object representing a socket * PRNetAddr *addr * Specifies the address of the socket in its own communication * space. * PRIntervalTime timeout * The function uses the lesser of the provided timeout and * the OS's connect timeout. In particular, if you specify * PR_INTERVAL_NO_TIMEOUT as the timeout, the OS's connection * time limit will be used. * * OUTPUTS: * None * RETURN: PRStatus * Upon successful completion of connection initiation, PR_Connect * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further * failure information can be obtained by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRStatus) PR_Connect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout); /* ************************************************************************* * FUNCTION: PR_ConnectContinue * DESCRIPTION: * Continue a nonblocking connect. After a nonblocking connect * is initiated with PR_Connect() (which fails with * PR_IN_PROGRESS_ERROR), one should call PR_Poll() on the socket, * with the in_flags PR_POLL_WRITE | PR_POLL_EXCEPT. When * PR_Poll() returns, one calls PR_ConnectContinue() on the * socket to determine whether the nonblocking connect has * completed or is still in progress. Repeat the PR_Poll(), * PR_ConnectContinue() sequence until the nonblocking connect * has completed. * INPUTS: * PRFileDesc *fd * the file descriptor representing a socket * PRInt16 out_flags * the out_flags field of the poll descriptor returned by * PR_Poll() * RETURN: PRStatus * If the nonblocking connect has successfully completed, * PR_ConnectContinue returns PR_SUCCESS. If PR_ConnectContinue() * returns PR_FAILURE, call PR_GetError(): * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in * progress and has not completed yet. The caller should poll * on the file descriptor for the in_flags * PR_POLL_WRITE|PR_POLL_EXCEPT and retry PR_ConnectContinue * later when PR_Poll() returns. * - Other errors: the nonblocking connect has failed with this * error code. */ NSPR_API(PRStatus) PR_ConnectContinue(PRFileDesc *fd, PRInt16 out_flags); /* ************************************************************************* * THIS FUNCTION IS DEPRECATED. USE PR_ConnectContinue INSTEAD. * * FUNCTION: PR_GetConnectStatus * DESCRIPTION: * Get the completion status of a nonblocking connect. After * a nonblocking connect is initiated with PR_Connect() (which * fails with PR_IN_PROGRESS_ERROR), one should call PR_Poll() * on the socket, with the in_flags PR_POLL_WRITE | PR_POLL_EXCEPT. * When PR_Poll() returns, one calls PR_GetConnectStatus on the * PRPollDesc structure to determine whether the nonblocking * connect has succeeded or failed. * INPUTS: * const PRPollDesc *pd * Pointer to a PRPollDesc whose fd member is the socket, * and in_flags must contain PR_POLL_WRITE and PR_POLL_EXCEPT. * PR_Poll() should have been called and set the out_flags. * RETURN: PRStatus * If the nonblocking connect has successfully completed, * PR_GetConnectStatus returns PR_SUCCESS. If PR_GetConnectStatus() * returns PR_FAILURE, call PR_GetError(): * - PR_IN_PROGRESS_ERROR: the nonblocking connect is still in * progress and has not completed yet. * - Other errors: the nonblocking connect has failed with this * error code. */ NSPR_API(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd); /* ************************************************************************* * FUNCTION: PR_Accept * DESCRIPTION: * Accept a connection on a socket. * INPUTS: * PRFileDesc *fd * Points to a PRFileDesc object representing the rendezvous socket * on which the caller is willing to accept new connections. * PRIntervalTime timeout * Time limit for completion of the accept operation. * OUTPUTS: * PRNetAddr *addr * Returns the address of the connecting entity in its own * communication space. It may be NULL. * RETURN: PRFileDesc* * Upon successful acceptance of a connection, PR_Accept * returns a valid file descriptor. Otherwise, it returns NULL. * Further failure information can be obtained by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRFileDesc*) PR_Accept( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout); /* ************************************************************************* * FUNCTION: PR_Bind * DESCRIPTION: * Bind an address to a socket. * INPUTS: * PRFileDesc *fd * Points to a PRFileDesc object representing a socket. * PRNetAddr *addr * Specifies the address to which the socket will be bound. * OUTPUTS: * None * RETURN: PRStatus * Upon successful binding of an address to a socket, PR_Bind * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further * failure information can be obtained by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr); /* ************************************************************************* * FUNCTION: PR_Listen * DESCRIPTION: * Listen for connections on a socket. * INPUTS: * PRFileDesc *fd * Points to a PRFileDesc object representing a socket that will be * used to listen for new connections. * PRIntn backlog * Specifies the maximum length of the queue of pending connections. * OUTPUTS: * None * RETURN: PRStatus * Upon successful completion of listen request, PR_Listen * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further * failure information can be obtained by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog); /* ************************************************************************* * FUNCTION: PR_Shutdown * DESCRIPTION: * Shut down part of a full-duplex connection on a socket. * INPUTS: * PRFileDesc *fd * Points to a PRFileDesc object representing a connected socket. * PRIntn how * Specifies the kind of disallowed operations on the socket. * PR_SHUTDOWN_RCV - Further receives will be disallowed * PR_SHUTDOWN_SEND - Further sends will be disallowed * PR_SHUTDOWN_BOTH - Further sends and receives will be disallowed * OUTPUTS: * None * RETURN: PRStatus * Upon successful completion of shutdown request, PR_Shutdown * returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further * failure information can be obtained by calling PR_GetError(). ************************************************************************** */ typedef enum PRShutdownHow { PR_SHUTDOWN_RCV = 0, /* disallow further receives */ PR_SHUTDOWN_SEND = 1, /* disallow further sends */ PR_SHUTDOWN_BOTH = 2 /* disallow further receives and sends */ } PRShutdownHow; NSPR_API(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how); /* ************************************************************************* * FUNCTION: PR_Recv * DESCRIPTION: * Receive a specified number of bytes from a connected socket. * The operation will block until some positive number of bytes are * transferred, a time out has occurred, or there is an error. * No more than 'amount' bytes will be transferred. * INPUTS: * PRFileDesc *fd * points to a PRFileDesc object representing a socket. * void *buf * pointer to a buffer to hold the data received. * PRInt32 amount * the size of 'buf' (in bytes) * PRIntn flags * must be zero or PR_MSG_PEEK. * PRIntervalTime timeout * Time limit for completion of the receive operation. * OUTPUTS: * None * RETURN: PRInt32 * a positive number indicates the number of bytes actually received. * 0 means the network connection is closed. * -1 indicates a failure. The reason for the failure is obtained * by calling PR_GetError(). ************************************************************************** */ #define PR_MSG_PEEK 0x2 NSPR_API(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); /* ************************************************************************* * FUNCTION: PR_Send * DESCRIPTION: * Send a specified number of bytes from a connected socket. * The operation will block until all bytes are * processed, a time out has occurred, or there is an error. * INPUTS: * PRFileDesc *fd * points to a PRFileDesc object representing a socket. * void *buf * pointer to a buffer from where the data is sent. * PRInt32 amount * the size of 'buf' (in bytes) * PRIntn flags * (OBSOLETE - must always be zero) * PRIntervalTime timeout * Time limit for completion of the send operation. * OUTPUTS: * None * RETURN: PRInt32 * A positive number indicates the number of bytes successfully processed. * This number must always equal 'amount'. A -1 is an indication that the * operation failed. The reason for the failure is obtained by calling * PR_GetError(). ************************************************************************** */ NSPR_API(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); /* ************************************************************************* * FUNCTION: PR_RecvFrom * DESCRIPTION: * Receive up to a specified number of bytes from socket which may * or may not be connected. * The operation will block until one or more bytes are * transferred, a time out has occurred, or there is an error. * No more than 'amount' bytes will be transferred. * INPUTS: * PRFileDesc *fd * points to a PRFileDesc object representing a socket. * void *buf * pointer to a buffer to hold the data received. * PRInt32 amount * the size of 'buf' (in bytes) * PRIntn flags * (OBSOLETE - must always be zero) * PRNetAddr *addr * Specifies the address of the sending peer. It may be NULL. * PRIntervalTime timeout * Time limit for completion of the receive operation. * OUTPUTS: * None * RETURN: PRInt32 * a positive number indicates the number of bytes actually received. * 0 means the network connection is closed. * -1 indicates a failure. The reason for the failure is obtained * by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRInt32) PR_RecvFrom( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout); /* ************************************************************************* * FUNCTION: PR_SendTo * DESCRIPTION: * Send a specified number of bytes from an unconnected socket. * The operation will block until all bytes are * sent, a time out has occurred, or there is an error. * INPUTS: * PRFileDesc *fd * points to a PRFileDesc object representing an unconnected socket. * void *buf * pointer to a buffer from where the data is sent. * PRInt32 amount * the size of 'buf' (in bytes) * PRIntn flags * (OBSOLETE - must always be zero) * PRNetAddr *addr * Specifies the address of the peer. .* PRIntervalTime timeout * Time limit for completion of the send operation. * OUTPUTS: * None * RETURN: PRInt32 * A positive number indicates the number of bytes successfully sent. * -1 indicates a failure. The reason for the failure is obtained * by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRInt32) PR_SendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout); /* ************************************************************************* ** FUNCTION: PR_TransmitFile ** DESCRIPTION: ** Transmitfile sends a complete file (sourceFile) across a socket ** (networkSocket). If headers is non-NULL, the headers will be sent across ** the socket prior to sending the file. ** ** Optionally, the PR_TRANSMITFILE_CLOSE_SOCKET flag may be passed to ** transmitfile. This flag specifies that transmitfile should close the ** socket after sending the data. ** ** INPUTS: ** PRFileDesc *networkSocket ** The socket to send data over ** PRFileDesc *sourceFile ** The file to send ** const void *headers ** A pointer to headers to be sent before sending data ** PRInt32 hlen ** length of header buffers in bytes. ** PRTransmitFileFlags flags ** If the flags indicate that the connection should be closed, ** it will be done immediately after transferring the file, unless ** the operation is unsuccessful. .* PRIntervalTime timeout * Time limit for completion of the transmit operation. ** ** RETURNS: ** Returns the number of bytes written or -1 if the operation failed. ** If an error occurs while sending the file, the PR_TRANSMITFILE_CLOSE_ ** SOCKET flag is ignored. The reason for the failure is obtained ** by calling PR_GetError(). ************************************************************************** */ NSPR_API(PRInt32) PR_TransmitFile( PRFileDesc *networkSocket, PRFileDesc *sourceFile, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout); /* ************************************************************************* ** FUNCTION: PR_SendFile ** DESCRIPTION: ** PR_SendFile sends data from a file (sendData->fd) across a socket ** (networkSocket). If specified, a header and/or trailer buffer are sent ** before and after the file, respectively. The file offset, number of bytes ** of file data to send, the header and trailer buffers are specified in the ** sendData argument. ** ** Optionally, if the PR_TRANSMITFILE_CLOSE_SOCKET flag is passed, the ** socket is closed after successfully sending the data. ** ** INPUTS: ** PRFileDesc *networkSocket ** The socket to send data over ** PRSendFileData *sendData ** Contains the FD, file offset and length, header and trailer ** buffer specifications. ** PRTransmitFileFlags flags ** If the flags indicate that the connection should be closed, ** it will be done immediately after transferring the file, unless ** the operation is unsuccessful. .* PRIntervalTime timeout * Time limit for completion of the send operation. ** ** RETURNS: ** Returns the number of bytes written or -1 if the operation failed. ** If an error occurs while sending the file, the PR_TRANSMITFILE_CLOSE_ ** SOCKET flag is ignored. The reason for the failure is obtained ** by calling PR_GetError(). ************************************************************************** */ struct PRSendFileData { PRFileDesc *fd; /* file to send */ PRUint32 file_offset; /* file offset */ PRSize file_nbytes; /* number of bytes of file data to send */ /* if 0, send data from file_offset to */ /* end-of-file. */ const void *header; /* header buffer */ PRInt32 hlen; /* header len */ const void *trailer; /* trailer buffer */ PRInt32 tlen; /* trailer len */ }; NSPR_API(PRInt32) PR_SendFile( PRFileDesc *networkSocket, PRSendFileData *sendData, PRTransmitFileFlags flags, PRIntervalTime timeout); /* ************************************************************************* ** FUNCTION: PR_AcceptRead ** DESCRIPTION: ** AcceptRead accepts a new connection, returns the newly created ** socket's descriptor and also returns the connecting peer's address. ** AcceptRead, as its name suggests, also receives the first block of data ** sent by the peer. ** ** INPUTS: ** PRFileDesc *listenSock ** A socket descriptor that has been called with the PR_Listen() ** function, also known as the rendezvous socket. ** void *buf ** A pointer to a buffer to receive data sent by the client. This ** buffer must be large enough to receive bytes of data ** and two PRNetAddr structures, plus an extra 32 bytes. See: ** PR_ACCEPT_READ_BUF_OVERHEAD. ** PRInt32 amount ** The number of bytes of client data to receive. Does not include ** the size of the PRNetAddr structures. If 0, no data will be read ** from the client. ** PRIntervalTime timeout ** The timeout interval only applies to the read portion of the ** operation. PR_AcceptRead will block indefinitely until the ** connection is accepted; the read will timeout after the timeout ** interval elapses. ** OUTPUTS: ** PRFileDesc **acceptedSock ** The file descriptor for the newly connected socket. This parameter ** will only be valid if the function return does not indicate failure. ** PRNetAddr **peerAddr, ** The address of the remote socket. This parameter will only be ** valid if the function return does not indicate failure. The ** returned address is not guaranteed to be properly aligned. ** ** RETURNS: ** The number of bytes read from the client or -1 on failure. The reason ** for the failure is obtained by calling PR_GetError(). ************************************************************************** **/ /* define buffer overhead constant. Add this value to the user's ** data length when allocating a buffer to accept data. ** Example: ** #define USER_DATA_SIZE 10 ** char buf[USER_DATA_SIZE + PR_ACCEPT_READ_BUF_OVERHEAD]; ** bytesRead = PR_AcceptRead( s, fd, &a, &p, USER_DATA_SIZE, ...); */ #define PR_ACCEPT_READ_BUF_OVERHEAD (32+(2*sizeof(PRNetAddr))) NSPR_API(PRInt32) PR_AcceptRead( PRFileDesc *listenSock, PRFileDesc **acceptedSock, PRNetAddr **peerAddr, void *buf, PRInt32 amount, PRIntervalTime timeout); /* ************************************************************************* ** FUNCTION: PR_NewTCPSocketPair ** DESCRIPTION: ** Create a new TCP socket pair. The returned descriptors can be used ** interchangeably; they are interconnected full-duplex descriptors: data ** written to one can be read from the other and vice-versa. ** ** INPUTS: ** None ** OUTPUTS: ** PRFileDesc *fds[2] ** The file descriptor pair for the newly created TCP sockets. ** RETURN: PRStatus ** Upon successful completion of TCP socket pair, PR_NewTCPSocketPair ** returns PR_SUCCESS. Otherwise, it returns PR_FAILURE. Further ** failure information can be obtained by calling PR_GetError(). ** XXX can we implement this on windoze and mac? ************************************************************************** **/ NSPR_API(PRStatus) PR_NewTCPSocketPair(PRFileDesc *fds[2]); /* ************************************************************************* ** FUNCTION: PR_GetSockName ** DESCRIPTION: ** Get socket name. Return the network address for this socket. ** ** INPUTS: ** PRFileDesc *fd ** Points to a PRFileDesc object representing the socket. ** OUTPUTS: ** PRNetAddr *addr ** Returns the address of the socket in its own communication space. ** RETURN: PRStatus ** Upon successful completion, PR_GetSockName returns PR_SUCCESS. ** Otherwise, it returns PR_FAILURE. Further failure information can ** be obtained by calling PR_GetError(). ************************************************************************** **/ NSPR_API(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr); /* ************************************************************************* ** FUNCTION: PR_GetPeerName ** DESCRIPTION: ** Get name of the connected peer. Return the network address for the ** connected peer socket. ** ** INPUTS: ** PRFileDesc *fd ** Points to a PRFileDesc object representing the connected peer. ** OUTPUTS: ** PRNetAddr *addr ** Returns the address of the connected peer in its own communication ** space. ** RETURN: PRStatus ** Upon successful completion, PR_GetPeerName returns PR_SUCCESS. ** Otherwise, it returns PR_FAILURE. Further failure information can ** be obtained by calling PR_GetError(). ************************************************************************** **/ NSPR_API(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr); NSPR_API(PRStatus) PR_GetSocketOption( PRFileDesc *fd, PRSocketOptionData *data); NSPR_API(PRStatus) PR_SetSocketOption( PRFileDesc *fd, const PRSocketOptionData *data); /* ********************************************************************* * * File descriptor inheritance * ********************************************************************* */ /* ************************************************************************ * FUNCTION: PR_SetFDInheritable * DESCRIPTION: * Set the inheritance attribute of a file descriptor. * * INPUTS: * PRFileDesc *fd * Points to a PRFileDesc object. * PRBool inheritable * If PR_TRUE, the file descriptor fd is set to be inheritable * by a child process. If PR_FALSE, the file descriptor is set * to be not inheritable by a child process. * RETURN: PRStatus * Upon successful completion, PR_SetFDInheritable returns PR_SUCCESS. * Otherwise, it returns PR_FAILURE. Further failure information can * be obtained by calling PR_GetError(). ************************************************************************* */ NSPR_API(PRStatus) PR_SetFDInheritable( PRFileDesc *fd, PRBool inheritable); /* ************************************************************************ * FUNCTION: PR_GetInheritedFD * DESCRIPTION: * Get an inherited file descriptor with the specified name. * * INPUTS: * const char *name * The name of the inherited file descriptor. * RETURN: PRFileDesc * * Upon successful completion, PR_GetInheritedFD returns the * inherited file descriptor with the specified name. Otherwise, * it returns NULL. Further failure information can be obtained * by calling PR_GetError(). ************************************************************************* */ NSPR_API(PRFileDesc *) PR_GetInheritedFD(const char *name); /* ********************************************************************* * * Memory-mapped files * ********************************************************************* */ typedef struct PRFileMap PRFileMap; /* * protection options for read and write accesses of a file mapping */ typedef enum PRFileMapProtect { PR_PROT_READONLY, /* read only */ PR_PROT_READWRITE, /* readable, and write is shared */ PR_PROT_WRITECOPY /* readable, and write is private (copy-on-write) */ } PRFileMapProtect; NSPR_API(PRFileMap *) PR_CreateFileMap( PRFileDesc *fd, PRInt64 size, PRFileMapProtect prot); /* * return the alignment (in bytes) of the offset argument to PR_MemMap */ NSPR_API(PRInt32) PR_GetMemMapAlignment(void); NSPR_API(void *) PR_MemMap( PRFileMap *fmap, PROffset64 offset, /* must be aligned and sized according to the * return value of PR_GetMemMapAlignment() */ PRUint32 len); NSPR_API(PRStatus) PR_MemUnmap(void *addr, PRUint32 len); NSPR_API(PRStatus) PR_CloseFileMap(PRFileMap *fmap); /* * Synchronously flush the given memory-mapped address range of the given open * file to disk. The function does not return until all modified data have * been written to disk. * * On some platforms, the function will call PR_Sync(fd) internally if it is * necessary for flushing modified data to disk synchronously. */ NSPR_API(PRStatus) PR_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len); /* ****************************************************************** * * Interprocess communication * ****************************************************************** */ /* * Creates an anonymous pipe and returns file descriptors for the * read and write ends of the pipe. */ NSPR_API(PRStatus) PR_CreatePipe( PRFileDesc **readPipe, PRFileDesc **writePipe ); /************************************************************************/ /************** The following definitions are for poll ******************/ /************************************************************************/ struct PRPollDesc { PRFileDesc* fd; PRInt16 in_flags; PRInt16 out_flags; }; /* ** Bit values for PRPollDesc.in_flags or PRPollDesc.out_flags. Binary-or ** these together to produce the desired poll request. */ #if defined(_PR_POLL_BACKCOMPAT) #include #define PR_POLL_READ POLLIN #define PR_POLL_WRITE POLLOUT #define PR_POLL_EXCEPT POLLPRI #define PR_POLL_ERR POLLERR /* only in out_flags */ #define PR_POLL_NVAL POLLNVAL /* only in out_flags when fd is bad */ #define PR_POLL_HUP POLLHUP /* only in out_flags */ #else /* _PR_POLL_BACKCOMPAT */ #define PR_POLL_READ 0x1 #define PR_POLL_WRITE 0x2 #define PR_POLL_EXCEPT 0x4 #define PR_POLL_ERR 0x8 /* only in out_flags */ #define PR_POLL_NVAL 0x10 /* only in out_flags when fd is bad */ #define PR_POLL_HUP 0x20 /* only in out_flags */ #endif /* _PR_POLL_BACKCOMPAT */ /* ************************************************************************* ** FUNCTION: PR_Poll ** DESCRIPTION: ** ** The call returns as soon as I/O is ready on one or more of the underlying ** socket objects. A count of the number of ready descriptors is ** returned unless a timeout occurs in which case zero is returned. ** ** PRPollDesc.fd should be set to a pointer to a PRFileDesc object ** representing a socket. This field can be set to NULL to indicate to ** PR_Poll that this PRFileDesc object should be ignored. ** PRPollDesc.in_flags should be set to the desired request ** (read/write/except or some combination). Upon successful return from ** this call PRPollDesc.out_flags will be set to indicate what kind of ** i/o can be performed on the respective descriptor. PR_Poll() uses the ** out_flags fields as scratch variables during the call. If PR_Poll() ** returns 0 or -1, the out_flags fields do not contain meaningful values ** and must not be used. ** ** INPUTS: ** PRPollDesc *pds A pointer to an array of PRPollDesc ** ** PRIntn npds The number of elements in the array ** If this argument is zero PR_Poll is ** equivalent to a PR_Sleep(timeout). ** ** PRIntervalTime timeout Amount of time the call will block waiting ** for I/O to become ready. If this time expires ** w/o any I/O becoming ready, the result will ** be zero. ** ** OUTPUTS: None ** RETURN: ** PRInt32 Number of PRPollDesc's with events or zero ** if the function timed out or -1 on failure. ** The reason for the failure is obtained by ** calling PR_GetError(). ************************************************************************** */ NSPR_API(PRInt32) PR_Poll( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout); /* ************************************************************************** ** ** Pollable events ** ** A pollable event is a special kind of file descriptor. ** The only I/O operation you can perform on a pollable event ** is to poll it with the PR_POLL_READ flag. You can't ** read from or write to a pollable event. ** ** The purpose of a pollable event is to combine event waiting ** with I/O waiting in a single PR_Poll call. Pollable events ** are implemented using a pipe or a pair of TCP sockets ** connected via the loopback address, therefore setting and ** waiting for pollable events are expensive operating system ** calls. Do not use pollable events for general thread ** synchronization. Use condition variables instead. ** ** A pollable event has two states: set and unset. Events ** are not queued, so there is no notion of an event count. ** A pollable event is either set or unset. ** ** A new pollable event is created by a PR_NewPollableEvent ** call and is initially in the unset state. ** ** PR_WaitForPollableEvent blocks the calling thread until ** the pollable event is set, and then it atomically unsets ** the pollable event before it returns. ** ** To set a pollable event, call PR_SetPollableEvent. ** ** One can call PR_Poll with the PR_POLL_READ flag on a pollable ** event. When the pollable event is set, PR_Poll returns with ** the PR_POLL_READ flag set in the out_flags. ** ** To close a pollable event, call PR_DestroyPollableEvent ** (not PR_Close). ** ************************************************************************** */ NSPR_API(PRFileDesc *) PR_NewPollableEvent(void); NSPR_API(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event); NSPR_API(PRStatus) PR_SetPollableEvent(PRFileDesc *event); NSPR_API(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event); PR_END_EXTERN_C #endif /* prio_h___ */ nspr-4.11/nspr/pr/include/pripcsem.h0000644000000000000000000000512012623070344015567 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pripcsem.h * * Description: named semaphores for interprocess * synchronization * * Unrelated processes obtain access to a shared semaphore * by specifying its name. * * Our goal is to support named semaphores on at least * Unix and Win32 platforms. The implementation will use * one of the three native semaphore APIs: POSIX, System V, * and Win32. * * Because POSIX named semaphores have kernel persistence, * we are forced to have a delete function in this API. */ #ifndef pripcsem_h___ #define pripcsem_h___ #include "prtypes.h" #include "prio.h" PR_BEGIN_EXTERN_C /* * PRSem is an opaque structure that represents a named * semaphore. */ typedef struct PRSem PRSem; /* * PR_OpenSemaphore -- * * Create or open a named semaphore with the specified name. * A handle to the semaphore is returned. * * If the named semaphore doesn't exist and the PR_SEM_CREATE * flag is specified, the named semaphore is created. The * created semaphore needs to be removed from the system with * a PR_DeleteSemaphore call. * * If PR_SEM_CREATE is specified, the third argument is the * access permission bits of the new semaphore (same * interpretation as the mode argument to PR_Open) and the * fourth argument is the initial value of the new semaphore. * If PR_SEM_CREATE is not specified, the third and fourth * arguments are ignored. */ #define PR_SEM_CREATE 0x1 /* create if not exist */ #define PR_SEM_EXCL 0x2 /* fail if already exists */ NSPR_API(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value); /* * PR_WaitSemaphore -- * * If the value of the semaphore is > 0, decrement the value and return. * If the value is 0, sleep until the value becomes > 0, then decrement * the value and return. * * The "test and decrement" operation is performed atomically. */ NSPR_API(PRStatus) PR_WaitSemaphore(PRSem *sem); /* * PR_PostSemaphore -- * * Increment the value of the named semaphore by 1. */ NSPR_API(PRStatus) PR_PostSemaphore(PRSem *sem); /* * PR_CloseSemaphore -- * * Close a named semaphore handle. */ NSPR_API(PRStatus) PR_CloseSemaphore(PRSem *sem); /* * PR_DeleteSemaphore -- * * Remove a named semaphore from the system. */ NSPR_API(PRStatus) PR_DeleteSemaphore(const char *name); PR_END_EXTERN_C #endif /* pripcsem_h___ */ nspr-4.11/nspr/pr/include/private/.cvsignore0000644000000000000000000000001112623070344017240 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/include/private/Makefile.in0000644000000000000000000000140112623070344017311 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk RELEASE_HEADERS = pprio.h pprthred.h prpriv.h RELEASE_HEADERS := $(addprefix $(srcdir)/, $(RELEASE_HEADERS)) RELEASE_HEADERS_DEST = $(RELEASE_INCLUDE_DIR)/private HEADERS = $(RELEASE_HEADERS) $(srcdir)/pprmwait.h $(srcdir)/primpl.h include_subdir = private include $(topsrcdir)/config/rules.mk export:: $(RELEASE_HEADERS) $(INSTALL) -m 444 $(RELEASE_HEADERS) $(dist_includedir)/private nspr-4.11/nspr/pr/include/private/pprio.h0000644000000000000000000002007312623070344016554 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: pprio.h ** ** Description: Private definitions for I/O related structures */ #ifndef pprio_h___ #define pprio_h___ #include "prtypes.h" #include "prio.h" PR_BEGIN_EXTERN_C /************************************************************************/ /************************************************************************/ #ifdef _WIN64 typedef __int64 PROsfd; #else typedef PRInt32 PROsfd; #endif /* Return the method tables for files, tcp sockets and udp sockets */ NSPR_API(const PRIOMethods*) PR_GetFileMethods(void); NSPR_API(const PRIOMethods*) PR_GetTCPMethods(void); NSPR_API(const PRIOMethods*) PR_GetUDPMethods(void); NSPR_API(const PRIOMethods*) PR_GetPipeMethods(void); /* ** Convert a NSPR socket handle to a native socket handle. ** ** Using this function makes your code depend on the properties of the ** current NSPR implementation, which may change (although extremely ** unlikely because of NSPR's backward compatibility requirement). Avoid ** using it if you can. ** ** If you use this function, you need to understand what NSPR does to ** the native handle. For example, NSPR puts native socket handles in ** non-blocking mode or associates them with an I/O completion port (the ** WINNT build configuration only). Your use of the native handle should ** not interfere with NSPR's use of the native handle. If your code ** changes the configuration of the native handle, (e.g., changes it to ** blocking or closes it), NSPR will not work correctly. */ NSPR_API(PROsfd) PR_FileDesc2NativeHandle(PRFileDesc *); NSPR_API(void) PR_ChangeFileDescNativeHandle(PRFileDesc *, PROsfd); NSPR_API(PRFileDesc*) PR_AllocFileDesc(PROsfd osfd, const PRIOMethods *methods); NSPR_API(void) PR_FreeFileDesc(PRFileDesc *fd); /* ** Import an existing OS file to NSPR. */ NSPR_API(PRFileDesc*) PR_ImportFile(PROsfd osfd); NSPR_API(PRFileDesc*) PR_ImportPipe(PROsfd osfd); NSPR_API(PRFileDesc*) PR_ImportTCPSocket(PROsfd osfd); NSPR_API(PRFileDesc*) PR_ImportUDPSocket(PROsfd osfd); /* ************************************************************************* * FUNCTION: PR_CreateSocketPollFd * DESCRIPTION: * Create a PRFileDesc wrapper for a native socket handle, for use with * PR_Poll only * INPUTS: * None * OUTPUTS: * None * RETURN: PRFileDesc* * Upon successful completion, PR_CreateSocketPollFd returns a pointer * to the PRFileDesc created for the native socket handle * Returns a NULL pointer if the create of a new PRFileDesc failed * ************************************************************************** */ NSPR_API(PRFileDesc*) PR_CreateSocketPollFd(PROsfd osfd); /* ************************************************************************* * FUNCTION: PR_DestroySocketPollFd * DESCRIPTION: * Destroy the PRFileDesc wrapper created by PR_CreateSocketPollFd * INPUTS: * None * OUTPUTS: * None * RETURN: PRFileDesc* * Upon successful completion, PR_DestroySocketPollFd returns * PR_SUCCESS, else PR_FAILURE * ************************************************************************** */ NSPR_API(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd); /* ** Macros for PR_Socket ** ** Socket types: PR_SOCK_STREAM, PR_SOCK_DGRAM */ #ifdef WIN32 #define PR_SOCK_STREAM 1 #define PR_SOCK_DGRAM 2 #else /* WIN32 */ #define PR_SOCK_STREAM SOCK_STREAM #define PR_SOCK_DGRAM SOCK_DGRAM #endif /* WIN32 */ /* ** Create a new Socket; this function is obsolete. */ NSPR_API(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto); /* FUNCTION: PR_LockFile ** DESCRIPTION: ** Lock a file for exclusive access. ** RETURNS: ** PR_SUCCESS when the lock is held ** PR_FAILURE otherwise */ NSPR_API(PRStatus) PR_LockFile(PRFileDesc *fd); /* FUNCTION: PR_TLockFile ** DESCRIPTION: ** Test and Lock a file for exclusive access. Do not block if the ** file cannot be locked immediately. ** RETURNS: ** PR_SUCCESS when the lock is held ** PR_FAILURE otherwise */ NSPR_API(PRStatus) PR_TLockFile(PRFileDesc *fd); /* FUNCTION: PR_UnlockFile ** DESCRIPTION: ** Unlock a file which has been previously locked successfully by this ** process. ** RETURNS: ** PR_SUCCESS when the lock is released ** PR_FAILURE otherwise */ NSPR_API(PRStatus) PR_UnlockFile(PRFileDesc *fd); /* ** Emulate acceptread by accept and recv. */ NSPR_API(PRInt32) PR_EmulateAcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout); /* ** Emulate sendfile by reading from the file and writing to the socket. ** The file is memory-mapped if memory-mapped files are supported. */ NSPR_API(PRInt32) PR_EmulateSendFile( PRFileDesc *networkSocket, PRSendFileData *sendData, PRTransmitFileFlags flags, PRIntervalTime timeout); #ifdef WIN32 /* FUNCTION: PR_NTFast_AcceptRead ** DESCRIPTION: ** NT has the notion of an "accept context", which is only needed in ** order to make certain calls. By default, a socket connected via ** AcceptEx can only do a limited number of things without updating ** the acceptcontext. The generic version of PR_AcceptRead always ** updates the accept context. This version does not. **/ NSPR_API(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime t); typedef void (*_PR_AcceptTimeoutCallback)(void *); /* FUNCTION: PR_NTFast_AcceptRead_WithTimeoutCallback ** DESCRIPTION: ** The AcceptEx call combines the accept with the read function. However, ** our daemon threads need to be able to wakeup and reliably flush their ** log buffers if the Accept times out. However, with the current blocking ** interface to AcceptRead, there is no way for us to timeout the Accept; ** this is because when we timeout the Read, we can close the newly ** socket and continue; but when we timeout the accept itself, there is no ** new socket to timeout. So instead, this version of the function is ** provided. After the initial timeout period elapses on the accept() ** portion of the function, it will call the callback routine and then ** continue the accept. If the timeout occurs on the read, it will ** close the connection and return error. */ NSPR_API(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime t, _PR_AcceptTimeoutCallback callback, void *callback_arg); /* FUNCTION: PR_NTFast_Accept ** DESCRIPTION: ** NT has the notion of an "accept context", which is only needed in ** order to make certain calls. By default, a socket connected via ** AcceptEx can only do a limited number of things without updating ** the acceptcontext. The generic version of PR_Accept always ** updates the accept context. This version does not. **/ NSPR_API(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout); /* FUNCTION: PR_NTFast_Update ** DESCRIPTION: ** For sockets accepted with PR_NTFast_Accept or PR_NTFastAcceptRead, ** this function will update the accept context for those sockets, ** so that the socket can make general purpose socket calls. ** Without calling this, the only operations supported on the socket ** Are PR_Read, PR_Write, PR_Transmitfile, and PR_Close. */ NSPR_API(void) PR_NTFast_UpdateAcceptContext(PRFileDesc *acceptSock, PRFileDesc *listenSock); /* FUNCTION: PR_NT_CancelIo ** DESCRIPTION: ** Cancel IO operations on fd. */ NSPR_API(PRStatus) PR_NT_CancelIo(PRFileDesc *fd); #endif /* WIN32 */ PR_END_EXTERN_C #endif /* pprio_h___ */ nspr-4.11/nspr/pr/include/private/pprmwait.h0000644000000000000000000001036112623070344017265 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if defined(_PPRMWAIT_H) #else #define _PPRMWAIT_H #include "prlock.h" #include "prcvar.h" #include "prclist.h" #include "prthread.h" #define MAX_POLLING_INTERVAL 100 #define _PR_POLL_COUNT_FUDGE 64 #define _PR_DEFAULT_HASH_LENGTH 59 /* * Our hash table resolves collisions by open addressing with * double hashing. See Cormen, Leiserson, and Rivest, * Introduction to Algorithms, p. 232, The MIT Press, 1990. */ #define _MW_HASH(a, m) ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m)) #define _MW_HASH2(a, m) (1 + ((((PRUptrdiff)(a) >> 4) ^ ((PRUptrdiff)(a) >> 10)) % (m - 2))) #define _MW_ABORTED(_rv) \ ((PR_FAILURE == (_rv)) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) typedef enum {_prmw_success, _prmw_rehash, _prmw_error} _PR_HashStory; typedef struct _PRWaiterHash { PRUint16 count; /* current number in hash table */ PRUint16 length; /* current size of the hash table */ PRRecvWait *recv_wait; /* hash table of receive wait objects */ } _PRWaiterHash; typedef enum {_prmw_running, _prmw_stopping, _prmw_stopped} PRMWGroupState; struct PRWaitGroup { PRCList group_link; /* all groups are linked to each other */ PRCList io_ready; /* list of I/O requests that are ready */ PRMWGroupState state; /* state of this group (so we can shut down) */ PRLock *ml; /* lock for synchronizing this wait group */ PRCondVar *io_taken; /* calling threads notify when they take I/O */ PRCondVar *io_complete; /* calling threads wait here for completions */ PRCondVar *new_business; /* polling thread waits here more work */ PRCondVar *mw_manage; /* used to manage group lists */ PRThread* poller; /* thread that's actually doing the poll() */ PRUint16 waiting_threads; /* number of threads waiting for recv */ PRUint16 polling_count; /* number of elements in the polling list */ PRUint32 p_timestamp; /* pseudo-time group had element removed */ PRPollDesc *polling_list; /* list poller builds for polling */ PRIntervalTime last_poll; /* last time we polled */ _PRWaiterHash *waiter; /* pointer to hash table of wait receive objects */ #ifdef WINNT /* * On NT, idle threads are responsible for getting completed i/o. * They need to add completed i/o to the io_ready list. Since * idle threads cannot use nspr locks, we have to use an md lock * to protect the io_ready list. */ _MDLock mdlock; /* protect io_ready, waiter, and wait_list */ PRCList wait_list; /* used in place of io_complete. reuse * waitQLinks in the PRThread structure. */ #endif /* WINNT */ }; /********************************************************************** *********************************************************************** ******************** Wait group enumerations ************************** *********************************************************************** **********************************************************************/ typedef struct _PRGlobalState { PRCList group_list; /* master of the group list */ PRWaitGroup *group; /* the default (NULL) group */ } _PRGlobalState; #ifdef WINNT extern PRStatus NT_HashRemoveInternal(PRWaitGroup *group, PRFileDesc *fd); #endif typedef enum {_PR_ENUM_UNSEALED=0, _PR_ENUM_SEALED=0x0eadface} _PREnumSeal; struct PRMWaitEnumerator { PRWaitGroup *group; /* group this enumerator is bound to */ PRThread *thread; /* thread in midst of an enumeration */ _PREnumSeal seal; /* trying to detect deleted objects */ PRUint32 p_timestamp; /* when enumeration was (re)started */ PRRecvWait **waiter; /* pointer into hash table */ PRUintn index; /* position in hash table */ void *pad[4]; /* some room to grow */ }; #endif /* defined(_PPRMWAIT_H) */ /* pprmwait.h */ nspr-4.11/nspr/pr/include/private/pprthred.h0000644000000000000000000002570112623070344017256 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef pprthred_h___ #define pprthred_h___ /* ** API for PR private functions. These calls are to be used by internal ** developers only. */ #include "nspr.h" #if defined(XP_OS2) #define INCL_DOS #define INCL_DOSERRORS #define INCL_WIN #include #endif PR_BEGIN_EXTERN_C /*--------------------------------------------------------------------------- ** THREAD PRIVATE FUNCTIONS ---------------------------------------------------------------------------*/ /* ** Associate a thread object with an existing native thread. ** "type" is the type of thread object to attach ** "priority" is the priority to assign to the thread ** "stack" defines the shape of the threads stack ** ** This can return NULL if some kind of error occurs, or if memory is ** tight. This call invokes "start(obj,arg)" and returns when the ** function returns. The thread object is automatically destroyed. ** ** This call is not normally needed unless you create your own native ** thread. PR_Init does this automatically for the primordial thread. */ NSPR_API(PRThread*) PR_AttachThread(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack); /* ** Detach the nspr thread from the currently executing native thread. ** The thread object will be destroyed and all related data attached ** to it. The exit procs will be invoked. ** ** This call is not normally needed unless you create your own native ** thread. PR_Exit will automatially detach the nspr thread object ** created by PR_Init for the primordial thread. ** ** This call returns after the nspr thread object is destroyed. */ NSPR_API(void) PR_DetachThread(void); /* ** Get the id of the named thread. Each thread is assigned a unique id ** when it is created or attached. */ NSPR_API(PRUint32) PR_GetThreadID(PRThread *thread); /* ** Set the procedure that is called when a thread is dumped. The procedure ** will be applied to the argument, arg, when called. Setting the procedure ** to NULL effectively removes it. */ typedef void (*PRThreadDumpProc)(PRFileDesc *fd, PRThread *t, void *arg); NSPR_API(void) PR_SetThreadDumpProc( PRThread* thread, PRThreadDumpProc dump, void *arg); /* ** Get this thread's affinity mask. The affinity mask is a 32 bit quantity ** marking a bit for each processor this process is allowed to run on. ** The processor mask is returned in the mask argument. ** The least-significant-bit represents processor 0. ** ** Returns 0 on success, -1 on failure. */ NSPR_API(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask); /* ** Set this thread's affinity mask. ** ** Returns 0 on success, -1 on failure. */ NSPR_API(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask ); /* ** Set the default CPU Affinity mask. ** */ NSPR_API(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask); /* ** Show status of all threads to standard error output. */ NSPR_API(void) PR_ShowStatus(void); /* ** Set thread recycle mode to on (1) or off (0) */ NSPR_API(void) PR_SetThreadRecycleMode(PRUint32 flag); /*--------------------------------------------------------------------------- ** THREAD PRIVATE FUNCTIONS FOR GARBAGE COLLECTIBLE THREADS ---------------------------------------------------------------------------*/ /* ** Only Garbage collectible threads participate in resume all, suspend all and ** enumeration operations. They are also different during creation when ** platform specific action may be needed (For example, all Solaris GC able ** threads are bound threads). */ /* ** Same as PR_CreateThread except that the thread is marked as garbage ** collectible. */ NSPR_API(PRThread*) PR_CreateThreadGCAble(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); /* ** Same as PR_AttachThread except that the thread being attached is marked as ** garbage collectible. */ NSPR_API(PRThread*) PR_AttachThreadGCAble(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack); /* ** Mark the thread as garbage collectible. */ NSPR_API(void) PR_SetThreadGCAble(void); /* ** Unmark the thread as garbage collectible. */ NSPR_API(void) PR_ClearThreadGCAble(void); /* ** This routine prevents all other GC able threads from running. This call is needed by ** the garbage collector. */ NSPR_API(void) PR_SuspendAll(void); /* ** This routine unblocks all other GC able threads that were suspended from running by ** PR_SuspendAll(). This call is needed by the garbage collector. */ NSPR_API(void) PR_ResumeAll(void); /* ** Return the thread stack pointer of the given thread. ** Needed by the garbage collector. */ NSPR_API(void *) PR_GetSP(PRThread *thread); /* ** Save the registers that the GC would find interesting into the thread ** "t". isCurrent will be non-zero if the thread state that is being ** saved is the currently executing thread. Return the address of the ** first register to be scanned as well as the number of registers to ** scan in "np". ** ** If "isCurrent" is non-zero then it is allowed for the thread context ** area to be used as scratch storage to hold just the registers ** necessary for scanning. ** ** This function simply calls the internal function _MD_HomeGCRegisters(). */ NSPR_API(PRWord *) PR_GetGCRegisters(PRThread *t, int isCurrent, int *np); /* ** (Get|Set)ExecutionEnvironent ** ** Used by Java to associate it's execution environment so garbage collector ** can find it. If return is NULL, then it's probably not a collectable thread. ** ** There's no locking required around these calls. */ NSPR_API(void*) GetExecutionEnvironment(PRThread *thread); NSPR_API(void) SetExecutionEnvironment(PRThread* thread, void *environment); /* ** Enumeration function that applies "func(thread,i,arg)" to each active ** thread in the process. The enumerator returns PR_SUCCESS if the enumeration ** should continue, any other value is considered failure, and enumeration ** stops, returning the failure value from PR_EnumerateThreads. ** Needed by the garbage collector. */ typedef PRStatus (PR_CALLBACK *PREnumerator)(PRThread *t, int i, void *arg); NSPR_API(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg); /* ** Signature of a thread stack scanning function. It is applied to every ** contiguous group of potential pointers within a thread. Count denotes the ** number of pointers. */ typedef PRStatus (PR_CALLBACK *PRScanStackFun)(PRThread* t, void** baseAddr, PRUword count, void* closure); /* ** Applies scanFun to all contiguous groups of potential pointers ** within a thread. This includes the stack, registers, and thread-local ** data. If scanFun returns a status value other than PR_SUCCESS the scan ** is aborted, and the status value is returned. */ NSPR_API(PRStatus) PR_ThreadScanStackPointers(PRThread* t, PRScanStackFun scanFun, void* scanClosure); /* ** Calls PR_ThreadScanStackPointers for every thread. */ NSPR_API(PRStatus) PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure); /* ** Returns a conservative estimate on the amount of stack space left ** on a thread in bytes, sufficient for making decisions about whether ** to continue recursing or not. */ NSPR_API(PRUword) PR_GetStackSpaceLeft(PRThread* t); /*--------------------------------------------------------------------------- ** THREAD CPU PRIVATE FUNCTIONS ---------------------------------------------------------------------------*/ /* ** Get a pointer to the primordial CPU. */ NSPR_API(struct _PRCPU *) _PR_GetPrimordialCPU(void); /*--------------------------------------------------------------------------- ** THREAD SYNCHRONIZATION PRIVATE FUNCTIONS ---------------------------------------------------------------------------*/ /* ** Create a new named monitor (named for debugging purposes). ** Monitors are re-entrant locks with a built-in condition variable. ** ** This may fail if memory is tight or if some operating system resource ** is low. */ NSPR_API(PRMonitor*) PR_NewNamedMonitor(const char* name); /* ** Test and then lock the lock if it's not already locked by some other ** thread. Return PR_FALSE if some other thread owned the lock at the ** time of the call. */ NSPR_API(PRBool) PR_TestAndLock(PRLock *lock); /* ** Test and then enter the mutex associated with the monitor if it's not ** already entered by some other thread. Return PR_FALSE if some other ** thread owned the mutex at the time of the call. */ NSPR_API(PRBool) PR_TestAndEnterMonitor(PRMonitor *mon); /* ** Return the number of times that the current thread has entered the ** mutex. Returns zero if the current thread has not entered the mutex. */ NSPR_API(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon); /* ** Just like PR_CEnterMonitor except that if the monitor is owned by ** another thread NULL is returned. */ NSPR_API(PRMonitor*) PR_CTestAndEnterMonitor(void *address); /*--------------------------------------------------------------------------- ** PLATFORM-SPECIFIC INITIALIZATION FUNCTIONS ---------------------------------------------------------------------------*/ #if defined(IRIX) /* ** Irix specific initialization funtion to be called before PR_Init ** is called by the application. Sets the CONF_INITUSERS and CONF_INITSIZE ** attributes of the shared arena set up by nspr. ** ** The environment variables _NSPR_IRIX_INITUSERS and _NSPR_IRIX_INITSIZE ** can also be used to set these arena attributes. If _NSPR_IRIX_INITUSERS ** is set, but not _NSPR_IRIX_INITSIZE, the value of the CONF_INITSIZE ** attribute of the nspr arena is scaled as a function of the ** _NSPR_IRIX_INITUSERS value. ** ** If the _PR_Irix_Set_Arena_Params() is called in addition to setting the ** environment variables, the values of the environment variables are used. ** */ NSPR_API(void) _PR_Irix_Set_Arena_Params(PRInt32 initusers, PRInt32 initsize); #endif /* IRIX */ #if defined(XP_OS2) /* ** These functions need to be called at the start and end of a thread. ** An EXCEPTIONREGISTRATIONRECORD must be declared on the stack and its ** address passed to the two functions. */ NSPR_API(void) PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* e); NSPR_API(void) PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* e); #endif /* XP_OS2 */ /* I think PR_GetMonitorEntryCount is useless. All you really want is this... */ #define PR_InMonitor(m) (PR_GetMonitorEntryCount(m) > 0) /*--------------------------------------------------------------------------- ** Special X-Lock hack for client ---------------------------------------------------------------------------*/ #ifdef XP_UNIX extern void PR_XLock(void); extern void PR_XUnlock(void); extern PRBool PR_XIsLocked(void); #endif /* XP_UNIX */ PR_END_EXTERN_C #endif /* pprthred_h___ */ nspr-4.11/nspr/pr/include/private/primpl.h0000644000000000000000000022121312623070344016725 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef primpl_h___ #define primpl_h___ /* * HP-UX 10.10's pthread.h (DCE threads) includes dce/cma.h, which * has: * #define sigaction _sigaction_sys * This macro causes chaos if signal.h gets included before pthread.h. * To be safe, we include pthread.h first. */ #if defined(_PR_PTHREADS) #include #endif #if defined(_PR_BTHREADS) #include #endif #ifdef WIN32 /* * Allow use of functions and symbols first defined in Win2k. */ #if !defined(WINVER) || (WINVER < 0x0500) #undef WINVER #define WINVER 0x0500 #endif #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) #undef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif #endif /* WIN32 */ #include "nspr.h" #include "prpriv.h" typedef struct PRSegment PRSegment; #include "md/prosdep.h" #include "obsolete/probslet.h" #ifdef _PR_HAVE_POSIX_SEMAPHORES #include #elif defined(_PR_HAVE_SYSV_SEMAPHORES) #include #endif #ifdef HAVE_SYSCALL #include #endif /************************************************************************* ***** A Word about Model Dependent Function Naming Convention *********** *************************************************************************/ /* NSPR 2.0 must implement its function across a range of platforms including: MAC, Windows/16, Windows/95, Windows/NT, and several variants of Unix. Each implementation shares common code as well as having platform dependent portions. This standard describes how the model dependent portions are to be implemented. In header file pr/include/primpl.h, each publicly declared platform dependent function is declared as: NSPR_API void _PR_MD_FUNCTION( long arg1, long arg2 ); #define _PR_MD_FUNCTION _MD_FUNCTION In header file pr/include/md//_.h, each #define'd macro is redefined as one of: #define _MD_FUNCTION #define _MD_FUNCTION #define _MD_FUNCTION #define _MD_FUNCTION <_MD_Function> Where: is no definition at all. In this case, the function is not implemented and is never called for this platform. For example: #define _MD_INIT_CPUS() is a C language macro expansion. For example: #define _MD_CLEAN_THREAD(_thread) \ PR_BEGIN_MACRO \ PR_DestroyCondVar(_thread->md.asyncIOCVar); \ PR_DestroyLock(_thread->md.asyncIOLock); \ PR_END_MACRO is some function implemented by the host operating system. For example: #define _MD_EXIT exit <_MD_function> is the name of a function implemented for this platform in pr/src/md//.c file. For example: #define _MD_GETFILEINFO _MD_GetFileInfo In .c, the implementation is: PR_IMPLEMENT(PRInt32) _MD_GetFileInfo(const char *fn, PRFileInfo *info); */ PR_BEGIN_EXTERN_C typedef struct _MDLock _MDLock; typedef struct _MDCVar _MDCVar; typedef struct _MDSegment _MDSegment; typedef struct _MDThread _MDThread; typedef struct _MDThreadStack _MDThreadStack; typedef struct _MDSemaphore _MDSemaphore; typedef struct _MDDir _MDDir; #ifdef MOZ_UNICODE typedef struct _MDDirUTF16 _MDDirUTF16; #endif /* MOZ_UNICODE */ typedef struct _MDFileDesc _MDFileDesc; typedef struct _MDProcess _MDProcess; typedef struct _MDFileMap _MDFileMap; #if defined(_PR_PTHREADS) /* ** The following definitions are unique to implementing NSPR using pthreads. ** Since pthreads defines most of the thread and thread synchronization ** stuff, this is a pretty small set. */ #define PT_CV_NOTIFIED_LENGTH 6 typedef struct _PT_Notified _PT_Notified; struct _PT_Notified { PRIntn length; /* # of used entries in this structure */ struct { PRCondVar *cv; /* the condition variable notified */ PRIntn times; /* and the number of times notified */ } cv[PT_CV_NOTIFIED_LENGTH]; _PT_Notified *link; /* link to another of these | NULL */ }; /* * bits defined for pthreads 'state' field */ #define PT_THREAD_DETACHED 0x01 /* thread can't be joined */ #define PT_THREAD_GLOBAL 0x02 /* a global thread (unlikely) */ #define PT_THREAD_SYSTEM 0x04 /* system (not user) thread */ #define PT_THREAD_PRIMORD 0x08 /* this is the primordial thread */ #define PT_THREAD_ABORTED 0x10 /* thread has been interrupted */ #define PT_THREAD_GCABLE 0x20 /* thread is garbage collectible */ #define PT_THREAD_SUSPENDED 0x40 /* thread has been suspended */ #define PT_THREAD_FOREIGN 0x80 /* thread is not one of ours */ #define PT_THREAD_BOUND 0x100 /* a bound-global thread */ #define _PT_THREAD_INTERRUPTED(thr) \ (!(thr->interrupt_blocked) && (thr->state & PT_THREAD_ABORTED)) #define _PT_THREAD_BLOCK_INTERRUPT(thr) \ (thr->interrupt_blocked = 1) #define _PT_THREAD_UNBLOCK_INTERRUPT(thr) \ (thr->interrupt_blocked = 0) #define _PT_IS_GCABLE_THREAD(thr) ((thr)->state & PT_THREAD_GCABLE) /* ** Possible values for thread's suspend field ** Note that the first two can be the same as they are really mutually exclusive, ** i.e. both cannot be happening at the same time. We have two symbolic names ** just as a mnemonic. **/ #define PT_THREAD_RESUMED 0x80 /* thread has been resumed */ #define PT_THREAD_SETGCABLE 0x100 /* set the GCAble flag */ #if defined(DEBUG) typedef struct PTDebug { PRTime timeStarted; PRUintn locks_created, locks_destroyed; PRUintn locks_acquired, locks_released; PRUintn cvars_created, cvars_destroyed; PRUintn cvars_notified, delayed_cv_deletes; } PTDebug; #endif /* defined(DEBUG) */ NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); /* * On Linux and its derivatives POSIX priority scheduling works only for * real-time threads. On those platforms we set thread's nice values * instead which requires us to track kernel thread IDs for each POSIX * thread we create. */ #if defined(LINUX) && defined(HAVE_SETPRIORITY) && \ ((defined(HAVE_SYSCALL) && defined(SYS_gettid)) || defined(HAVE_GETTID)) #define _PR_NICE_PRIORITY_SCHEDULING #endif #else /* defined(_PR_PTHREADS) */ NSPR_API(void) PT_FPrintStats(PRFileDesc *fd, const char *msg); /* ** This section is contains those parts needed to implement NSPR on ** platforms in general. One would assume that the pthreads implementation ** included lots of the same types, at least conceptually. */ /* * Local threads only. No multiple CPU support and hence all the * following routines are no-op. */ #ifdef _PR_LOCAL_THREADS_ONLY #define _PR_MD_SUSPEND_THREAD(thread) #define _PR_MD_RESUME_THREAD(thread) #define _PR_MD_SUSPEND_CPU(cpu) #define _PR_MD_RESUME_CPU(cpu) #define _PR_MD_BEGIN_SUSPEND_ALL() #define _PR_MD_END_SUSPEND_ALL() #define _PR_MD_BEGIN_RESUME_ALL() #define _PR_MD_END_RESUME_ALL() #define _PR_MD_INIT_ATTACHED_THREAD(thread) PR_FAILURE #endif typedef struct _PRCPUQueue _PRCPUQueue; typedef struct _PRCPU _PRCPU; typedef struct _MDCPU _MDCPU; struct _PRCPUQueue { _MDLock runQLock; /* lock for the run + wait queues */ _MDLock sleepQLock; /* lock for the run + wait queues */ _MDLock miscQLock; /* lock for the run + wait queues */ PRCList runQ[PR_PRIORITY_LAST + 1]; /* run queue for this CPU */ PRUint32 runQReadyMask; PRCList sleepQ; PRIntervalTime sleepQmax; PRCList pauseQ; PRCList suspendQ; PRCList waitingToJoinQ; PRUintn numCPUs; /* number of CPUs using this Q */ }; struct _PRCPU { PRCList links; /* link list of CPUs */ PRUint32 id; /* id for this CPU */ union { PRInt32 bits; PRUint8 missed[4]; } u; PRIntn where; /* index into u.missed */ PRPackedBool paused; /* cpu is paused */ PRPackedBool exit; /* cpu should exit */ PRThread *thread; /* native thread for this CPUThread */ PRThread *idle_thread; /* user-level idle thread for this CPUThread */ PRIntervalTime last_clock; /* the last time we went into * _PR_ClockInterrupt() on this CPU */ _PRCPUQueue *queue; _MDCPU md; }; typedef struct _PRInterruptTable { const char *name; PRUintn missed_bit; void (*handler)(void); } _PRInterruptTable; #define _PR_CPU_PTR(_qp) \ ((_PRCPU*) ((char*) (_qp) - offsetof(_PRCPU,links))) #if !defined(IRIX) && !defined(WIN32) && !defined(XP_OS2) \ && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)) #define _MD_GET_ATTACHED_THREAD() (_PR_MD_CURRENT_THREAD()) #endif #ifdef _PR_LOCAL_THREADS_ONLY NSPR_API(struct _PRCPU *) _pr_currentCPU; NSPR_API(PRThread *) _pr_currentThread; NSPR_API(PRThread *) _pr_lastThread; NSPR_API(PRInt32) _pr_intsOff; #define _MD_CURRENT_CPU() (_pr_currentCPU) #define _MD_SET_CURRENT_CPU(_cpu) (_pr_currentCPU = (_cpu)) #define _MD_CURRENT_THREAD() (_pr_currentThread) #define _MD_SET_CURRENT_THREAD(_thread) (_pr_currentThread = (_thread)) #define _MD_LAST_THREAD() (_pr_lastThread) #define _MD_SET_LAST_THREAD(t) (_pr_lastThread = t) #define _MD_GET_INTSOFF() (_pr_intsOff) #define _MD_SET_INTSOFF(_val) (_pr_intsOff = _val) /* The unbalanced curly braces in these two macros are intentional */ #define _PR_LOCK_HEAP() { PRIntn _is; if (_pr_currentCPU) _PR_INTSOFF(_is); #define _PR_UNLOCK_HEAP() if (_pr_currentCPU) _PR_INTSON(_is); } #endif /* _PR_LOCAL_THREADS_ONLY */ extern PRInt32 _native_threads_only; #if defined(_PR_GLOBAL_THREADS_ONLY) #define _MD_GET_INTSOFF() 0 #define _MD_SET_INTSOFF(_val) #define _PR_INTSOFF(_is) #define _PR_FAST_INTSON(_is) #define _PR_INTSON(_is) #define _PR_THREAD_LOCK(_thread) #define _PR_THREAD_UNLOCK(_thread) #define _PR_RUNQ_LOCK(cpu) #define _PR_RUNQ_UNLOCK(cpu) #define _PR_SLEEPQ_LOCK(thread) #define _PR_SLEEPQ_UNLOCK(thread) #define _PR_MISCQ_LOCK(thread) #define _PR_MISCQ_UNLOCK(thread) #define _PR_CPU_LIST_LOCK() #define _PR_CPU_LIST_UNLOCK() #define _PR_ADD_RUNQ(_thread, _cpu, _pri) #define _PR_DEL_RUNQ(_thread) #define _PR_ADD_SLEEPQ(_thread, _timeout) #define _PR_DEL_SLEEPQ(_thread, _propogate) #define _PR_ADD_JOINQ(_thread, _cpu) #define _PR_DEL_JOINQ(_thread) #define _PR_ADD_SUSPENDQ(_thread, _cpu) #define _PR_DEL_SUSPENDQ(_thread) #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) #define _PR_IS_NATIVE_THREAD(thread) 1 #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1 #else #define _PR_INTSOFF(_is) \ PR_BEGIN_MACRO \ (_is) = _PR_MD_GET_INTSOFF(); \ _PR_MD_SET_INTSOFF(1); \ PR_END_MACRO #define _PR_FAST_INTSON(_is) \ PR_BEGIN_MACRO \ _PR_MD_SET_INTSOFF(_is); \ PR_END_MACRO #define _PR_INTSON(_is) \ PR_BEGIN_MACRO \ if ((_is == 0) && (_PR_MD_CURRENT_CPU())->u.bits) \ _PR_IntsOn((_PR_MD_CURRENT_CPU())); \ _PR_MD_SET_INTSOFF(_is); \ PR_END_MACRO #ifdef _PR_LOCAL_THREADS_ONLY #define _PR_IS_NATIVE_THREAD(thread) 0 #define _PR_THREAD_LOCK(_thread) #define _PR_THREAD_UNLOCK(_thread) #define _PR_RUNQ_LOCK(cpu) #define _PR_RUNQ_UNLOCK(cpu) #define _PR_SLEEPQ_LOCK(thread) #define _PR_SLEEPQ_UNLOCK(thread) #define _PR_MISCQ_LOCK(thread) #define _PR_MISCQ_UNLOCK(thread) #define _PR_CPU_LIST_LOCK() #define _PR_CPU_LIST_UNLOCK() #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \ PR_BEGIN_MACRO \ PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \ _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \ PR_END_MACRO #define _PR_DEL_RUNQ(_thread) \ PR_BEGIN_MACRO \ _PRCPU *_cpu = _thread->cpu; \ PRInt32 _pri = _thread->priority; \ PR_REMOVE_LINK(&(_thread)->links); \ if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \ _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \ PR_END_MACRO #define _PR_ADD_SLEEPQ(_thread, _timeout) \ _PR_AddSleepQ(_thread, _timeout); #define _PR_DEL_SLEEPQ(_thread, _propogate) \ _PR_DelSleepQ(_thread, _propogate); #define _PR_ADD_JOINQ(_thread, _cpu) \ PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu)); #define _PR_DEL_JOINQ(_thread) \ PR_REMOVE_LINK(&(_thread)->links); #define _PR_ADD_SUSPENDQ(_thread, _cpu) \ PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu)); #define _PR_DEL_SUSPENDQ(_thread) \ PR_REMOVE_LINK(&(_thread)->links); #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) #define _PR_IS_NATIVE_THREAD_SUPPORTED() 0 #else /* _PR_LOCAL_THREADS_ONLY */ /* These are for the "combined" thread model */ #define _PR_THREAD_LOCK(_thread) \ _PR_MD_LOCK(&(_thread)->threadLock); #define _PR_THREAD_UNLOCK(_thread) \ _PR_MD_UNLOCK(&(_thread)->threadLock); #define _PR_RUNQ_LOCK(_cpu) \ PR_BEGIN_MACRO \ _PR_MD_LOCK(&(_cpu)->queue->runQLock );\ PR_END_MACRO #define _PR_RUNQ_UNLOCK(_cpu) \ PR_BEGIN_MACRO \ _PR_MD_UNLOCK(&(_cpu)->queue->runQLock );\ PR_END_MACRO #define _PR_SLEEPQ_LOCK(_cpu) \ _PR_MD_LOCK(&(_cpu)->queue->sleepQLock ); #define _PR_SLEEPQ_UNLOCK(_cpu) \ _PR_MD_UNLOCK(&(_cpu)->queue->sleepQLock ); #define _PR_MISCQ_LOCK(_cpu) \ _PR_MD_LOCK(&(_cpu)->queue->miscQLock ); #define _PR_MISCQ_UNLOCK(_cpu) \ _PR_MD_UNLOCK(&(_cpu)->queue->miscQLock ); #define _PR_CPU_LIST_LOCK() _PR_MD_LOCK(&_pr_cpuLock) #define _PR_CPU_LIST_UNLOCK() _PR_MD_UNLOCK(&_pr_cpuLock) #define QUEUE_RUN 0x1 #define QUEUE_SLEEP 0x2 #define QUEUE_JOIN 0x4 #define QUEUE_SUSPEND 0x8 #define QUEUE_LOCK 0x10 #define _PR_ADD_RUNQ(_thread, _cpu, _pri) \ PR_BEGIN_MACRO \ PR_APPEND_LINK(&(_thread)->links, &_PR_RUNQ(_cpu)[_pri]); \ _PR_RUNQREADYMASK(_cpu) |= (1L << _pri); \ PR_ASSERT((_thread)->queueCount == 0); \ (_thread)->queueCount = QUEUE_RUN; \ PR_END_MACRO #define _PR_DEL_RUNQ(_thread) \ PR_BEGIN_MACRO \ _PRCPU *_cpu = _thread->cpu; \ PRInt32 _pri = _thread->priority; \ PR_REMOVE_LINK(&(_thread)->links); \ if (PR_CLIST_IS_EMPTY(&_PR_RUNQ(_cpu)[_pri])) \ _PR_RUNQREADYMASK(_cpu) &= ~(1L << _pri); \ PR_ASSERT((_thread)->queueCount == QUEUE_RUN);\ (_thread)->queueCount = 0; \ PR_END_MACRO #define _PR_ADD_SLEEPQ(_thread, _timeout) \ PR_ASSERT((_thread)->queueCount == 0); \ (_thread)->queueCount = QUEUE_SLEEP; \ _PR_AddSleepQ(_thread, _timeout); #define _PR_DEL_SLEEPQ(_thread, _propogate) \ PR_ASSERT((_thread)->queueCount == QUEUE_SLEEP);\ (_thread)->queueCount = 0; \ _PR_DelSleepQ(_thread, _propogate); #define _PR_ADD_JOINQ(_thread, _cpu) \ PR_ASSERT((_thread)->queueCount == 0); \ (_thread)->queueCount = QUEUE_JOIN; \ PR_APPEND_LINK(&(_thread)->links, &_PR_WAITINGTOJOINQ(_cpu)); #define _PR_DEL_JOINQ(_thread) \ PR_ASSERT((_thread)->queueCount == QUEUE_JOIN);\ (_thread)->queueCount = 0; \ PR_REMOVE_LINK(&(_thread)->links); #define _PR_ADD_SUSPENDQ(_thread, _cpu) \ PR_ASSERT((_thread)->queueCount == 0); \ (_thread)->queueCount = QUEUE_SUSPEND; \ PR_APPEND_LINK(&(_thread)->links, &_PR_SUSPENDQ(_cpu)); #define _PR_DEL_SUSPENDQ(_thread) \ PR_ASSERT((_thread)->queueCount == QUEUE_SUSPEND);\ (_thread)->queueCount = 0; \ PR_REMOVE_LINK(&(_thread)->links); #define _PR_THREAD_SWITCH_CPU(_thread, _newCPU) \ (_thread)->cpu = (_newCPU); #define _PR_IS_NATIVE_THREAD(thread) (thread->flags & _PR_GLOBAL_SCOPE) #define _PR_IS_NATIVE_THREAD_SUPPORTED() 1 #endif /* _PR_LOCAL_THREADS_ONLY */ #endif /* _PR_GLOBAL_THREADS_ONLY */ #define _PR_SET_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 1 #define _PR_CLEAR_RESCHED_FLAG() _PR_MD_CURRENT_CPU()->u.missed[3] = 0 extern _PRInterruptTable _pr_interruptTable[]; /* Bits for _pr_interruptState.u.missed[0,1] */ #define _PR_MISSED_CLOCK 0x1 #define _PR_MISSED_IO 0x2 #define _PR_MISSED_CHILD 0x4 extern void _PR_IntsOn(_PRCPU *cpu); NSPR_API(void) _PR_WakeupCPU(void); NSPR_API(void) _PR_PauseCPU(void); /************************************************************************/ #define _PR_LOCK_LOCK(_lock) \ _PR_MD_LOCK(&(_lock)->ilock); #define _PR_LOCK_UNLOCK(_lock) \ _PR_MD_UNLOCK(&(_lock)->ilock); extern void _PR_UnblockLockWaiter(PRLock *lock); extern PRStatus _PR_InitLock(PRLock *lock); extern void _PR_FreeLock(PRLock *lock); #define _PR_LOCK_PTR(_qp) \ ((PRLock*) ((char*) (_qp) - offsetof(PRLock,links))) /************************************************************************/ #define _PR_CVAR_LOCK(_cvar) \ _PR_MD_LOCK(&(_cvar)->ilock); #define _PR_CVAR_UNLOCK(_cvar) \ _PR_MD_UNLOCK(&(_cvar)->ilock); extern PRStatus _PR_InitCondVar(PRCondVar *cvar, PRLock *lock); extern void _PR_FreeCondVar(PRCondVar *cvar); extern PRStatus _PR_WaitCondVar( PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout); extern void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me); extern PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen); NSPR_API(void) _PR_Notify(PRMonitor *mon, PRBool all, PRBool sticky); /* PRThread.flags */ #define _PR_SYSTEM 0x01 #define _PR_INTERRUPT 0x02 #define _PR_ATTACHED 0x04 /* created via PR_AttachThread */ #define _PR_PRIMORDIAL 0x08 /* the thread that called PR_Init */ #define _PR_ON_SLEEPQ 0x10 /* thread is on the sleepQ */ #define _PR_ON_PAUSEQ 0x20 /* thread is on the pauseQ */ #define _PR_SUSPENDING 0x40 /* thread wants to suspend */ #define _PR_GLOBAL_SCOPE 0x80 /* thread is global scope */ #define _PR_IDLE_THREAD 0x200 /* this is an idle thread */ #define _PR_GCABLE_THREAD 0x400 /* this is a collectable thread */ #define _PR_BOUND_THREAD 0x800 /* a bound thread */ #define _PR_INTERRUPT_BLOCKED 0x1000 /* interrupts blocked */ /* PRThread.state */ #define _PR_UNBORN 0 #define _PR_RUNNABLE 1 #define _PR_RUNNING 2 #define _PR_LOCK_WAIT 3 #define _PR_COND_WAIT 4 #define _PR_JOIN_WAIT 5 #define _PR_IO_WAIT 6 #define _PR_SUSPENDED 7 #define _PR_DEAD_STATE 8 /* for debugging */ /* PRThreadStack.flags */ #define _PR_STACK_VM 0x1 /* using vm instead of malloc */ #define _PR_STACK_MAPPED 0x2 /* vm is mapped */ #define _PR_STACK_PRIMORDIAL 0x4 /* stack for primordial thread */ /* ** If the default stcksize from the client is zero, we need to pick a machine ** dependent value. This is only for standard user threads. For custom threads, ** 0 has a special meaning. ** Adjust stackSize. Round up to a page boundary. */ #ifndef _MD_MINIMUM_STACK_SIZE #define _MD_MINIMUM_STACK_SIZE 0 #endif #if (!defined(HAVE_CUSTOM_USER_THREADS)) #define _PR_ADJUST_STACKSIZE(stackSize) \ PR_BEGIN_MACRO \ if (stackSize == 0) \ stackSize = _MD_DEFAULT_STACK_SIZE; \ if (stackSize < _MD_MINIMUM_STACK_SIZE) \ stackSize = _MD_MINIMUM_STACK_SIZE; \ stackSize = (stackSize + (1 << _pr_pageShift) - 1) >> _pr_pageShift; \ stackSize <<= _pr_pageShift; \ PR_END_MACRO #else #define _PR_ADJUST_STACKSIZE(stackSize) #endif #define _PR_IS_GCABLE_THREAD(thr) ((thr)->flags & _PR_GCABLE_THREAD) #define _PR_PENDING_INTERRUPT(thr) \ (!((thr)->flags & _PR_INTERRUPT_BLOCKED) && ((thr)->flags & _PR_INTERRUPT)) #define _PR_THREAD_BLOCK_INTERRUPT(thr) \ (thr->flags |= _PR_INTERRUPT_BLOCKED) #define _PR_THREAD_UNBLOCK_INTERRUPT(thr) \ (thr->flags &= ~_PR_INTERRUPT_BLOCKED) #define _PR_THREAD_PTR(_qp) \ ((PRThread*) ((char*) (_qp) - offsetof(PRThread,links))) #define _PR_ACTIVE_THREAD_PTR(_qp) \ ((PRThread*) ((char*) (_qp) - offsetof(PRThread,active))) #define _PR_THREAD_CONDQ_PTR(_qp) \ ((PRThread*) ((char*) (_qp) - offsetof(PRThread,waitQLinks))) #define _PR_THREAD_MD_TO_PTR(_md) \ ((PRThread*) ((char*) (_md) - offsetof(PRThread,md))) #define _PR_THREAD_STACK_TO_PTR(_stack) \ ((PRThread*) (_stack->thr)) extern PRCList _pr_active_local_threadQ; extern PRCList _pr_active_global_threadQ; extern PRCList _pr_cpuQ; extern _MDLock _pr_cpuLock; extern PRInt32 _pr_md_idle_cpus; #define _PR_ACTIVE_LOCAL_THREADQ() _pr_active_local_threadQ #define _PR_ACTIVE_GLOBAL_THREADQ() _pr_active_global_threadQ #define _PR_CPUQ() _pr_cpuQ #define _PR_RUNQ(_cpu) ((_cpu)->queue->runQ) #define _PR_RUNQREADYMASK(_cpu) ((_cpu)->queue->runQReadyMask) #define _PR_SLEEPQ(_cpu) ((_cpu)->queue->sleepQ) #define _PR_SLEEPQMAX(_cpu) ((_cpu)->queue->sleepQmax) #define _PR_PAUSEQ(_cpu) ((_cpu)->queue->pauseQ) #define _PR_SUSPENDQ(_cpu) ((_cpu)->queue->suspendQ) #define _PR_WAITINGTOJOINQ(_cpu) ((_cpu)->queue->waitingToJoinQ) extern PRUint32 _pr_recycleThreads; /* Flag for behavior on thread cleanup */ extern PRLock *_pr_deadQLock; extern PRUint32 _pr_numNativeDead; extern PRUint32 _pr_numUserDead; extern PRCList _pr_deadNativeQ; extern PRCList _pr_deadUserQ; #define _PR_DEADNATIVEQ _pr_deadNativeQ #define _PR_DEADUSERQ _pr_deadUserQ #define _PR_DEADQ_LOCK PR_Lock(_pr_deadQLock); #define _PR_DEADQ_UNLOCK PR_Unlock(_pr_deadQLock); #define _PR_INC_DEADNATIVE (_pr_numNativeDead++) #define _PR_DEC_DEADNATIVE (_pr_numNativeDead--) #define _PR_NUM_DEADNATIVE (_pr_numNativeDead) #define _PR_INC_DEADUSER (_pr_numUserDead++) #define _PR_DEC_DEADUSER (_pr_numUserDead--) #define _PR_NUM_DEADUSER (_pr_numUserDead) extern PRUint32 _pr_utid; extern struct _PRCPU *_pr_primordialCPU; extern PRLock *_pr_activeLock; /* lock for userActive and systemActive */ extern PRInt32 _pr_userActive; /* number of active user threads */ extern PRInt32 _pr_systemActive; /* number of active system threads */ extern PRInt32 _pr_primordialExitCount; /* number of user threads left * before the primordial thread * can exit. */ extern PRCondVar *_pr_primordialExitCVar; /* the condition variable for * notifying the primordial thread * when all other user threads * have terminated. */ extern PRUintn _pr_maxPTDs; extern PRLock *_pr_terminationCVLock; /************************************************************************* * Internal routines either called by PR itself or from machine-dependent * * code. * *************************************************************************/ extern void _PR_ClockInterrupt(void); extern void _PR_Schedule(void); extern void _PR_SetThreadPriority( PRThread* thread, PRThreadPriority priority); /*********************************************************************** ** FUNCTION: _PR_NewSegment() ** DESCRIPTION: ** Allocate a memory segment. The "size" value is rounded up to the ** native system page size and a page aligned portion of memory is ** returned. This memory is not part of the malloc heap. If "vaddr" is ** not NULL then PR tries to allocate the segment at the desired virtual ** address. ** INPUTS: size: size of the desired memory segment ** vaddr: address at which the newly aquired segment is to be ** mapped into memory. ** OUTPUTS: a memory segment is allocated, a PRSegment is allocated ** RETURN: pointer to PRSegment ***********************************************************************/ extern PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr); /*********************************************************************** ** FUNCTION: _PR_DestroySegment() ** DESCRIPTION: ** The memory segment and the PRSegment are freed ** INPUTS: seg: pointer to PRSegment to be freed ** OUTPUTS: the the PRSegment and its associated memory segment are freed ** RETURN: void ***********************************************************************/ extern void _PR_DestroySegment(PRSegment *seg); extern PRThreadStack * _PR_NewStack(PRUint32 stackSize); extern void _PR_FreeStack(PRThreadStack *stack); extern PRBool _PR_NotifyThread (PRThread *thread, PRThread *me); extern void _PR_NotifyLockedThread (PRThread *thread); NSPR_API(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout); NSPR_API(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time); extern void _PR_AddThreadToRunQ(PRThread *me, PRThread *thread); NSPR_API(PRThread*) _PR_CreateThread(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize, PRUint32 flags); extern void _PR_NativeDestroyThread(PRThread *thread); extern void _PR_UserDestroyThread(PRThread *thread); extern PRThread* _PRI_AttachThread( PRThreadType type, PRThreadPriority priority, PRThreadStack *stack, PRUint32 flags); extern void _PRI_DetachThread(void); #define _PR_IO_PENDING(_thread) ((_thread)->io_pending) NSPR_API(void) _PR_MD_INIT_CPUS(); #define _PR_MD_INIT_CPUS _MD_INIT_CPUS NSPR_API(void) _PR_MD_WAKEUP_CPUS(); #define _PR_MD_WAKEUP_CPUS _MD_WAKEUP_CPUS /* Interrupts related */ NSPR_API(void) _PR_MD_START_INTERRUPTS(void); #define _PR_MD_START_INTERRUPTS _MD_START_INTERRUPTS NSPR_API(void) _PR_MD_STOP_INTERRUPTS(void); #define _PR_MD_STOP_INTERRUPTS _MD_STOP_INTERRUPTS NSPR_API(void) _PR_MD_ENABLE_CLOCK_INTERRUPTS(void); #define _PR_MD_ENABLE_CLOCK_INTERRUPTS _MD_ENABLE_CLOCK_INTERRUPTS NSPR_API(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void); #define _PR_MD_DISABLE_CLOCK_INTERRUPTS _MD_DISABLE_CLOCK_INTERRUPTS NSPR_API(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void); #define _PR_MD_BLOCK_CLOCK_INTERRUPTS _MD_BLOCK_CLOCK_INTERRUPTS NSPR_API(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void); #define _PR_MD_UNBLOCK_CLOCK_INTERRUPTS _MD_UNBLOCK_CLOCK_INTERRUPTS /* The _PR_MD_WAIT_LOCK and _PR_MD_WAKEUP_WAITER functions put to sleep and * awaken a thread which is waiting on a lock or cvar. */ extern PRStatus _PR_MD_WAIT(PRThread *, PRIntervalTime timeout); #define _PR_MD_WAIT _MD_WAIT extern PRStatus _PR_MD_WAKEUP_WAITER(PRThread *); #define _PR_MD_WAKEUP_WAITER _MD_WAKEUP_WAITER #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ NSPR_API(void) _PR_MD_CLOCK_INTERRUPT(void); #define _PR_MD_CLOCK_INTERRUPT _MD_CLOCK_INTERRUPT #endif /* Stack debugging */ NSPR_API(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone); #define _PR_MD_INIT_STACK _MD_INIT_STACK NSPR_API(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts); #define _PR_MD_CLEAR_STACK _MD_CLEAR_STACK /* CPU related */ NSPR_API(PRInt32) _PR_MD_GET_INTSOFF(void); #define _PR_MD_GET_INTSOFF _MD_GET_INTSOFF NSPR_API(void) _PR_MD_SET_INTSOFF(PRInt32 _val); #define _PR_MD_SET_INTSOFF _MD_SET_INTSOFF NSPR_API(_PRCPU*) _PR_MD_CURRENT_CPU(void); #define _PR_MD_CURRENT_CPU _MD_CURRENT_CPU NSPR_API(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu); #define _PR_MD_SET_CURRENT_CPU _MD_SET_CURRENT_CPU NSPR_API(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu); #define _PR_MD_INIT_RUNNING_CPU _MD_INIT_RUNNING_CPU /* * Returns the number of threads awoken or 0 if a timeout occurred; */ extern PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime timeout); #define _PR_MD_PAUSE_CPU _MD_PAUSE_CPU extern void _PR_MD_CLEANUP_BEFORE_EXIT(void); #define _PR_MD_CLEANUP_BEFORE_EXIT _MD_CLEANUP_BEFORE_EXIT extern void _PR_MD_EXIT(PRIntn status); #define _PR_MD_EXIT _MD_EXIT /* Locks related */ NSPR_API(void) _PR_MD_INIT_LOCKS(void); #define _PR_MD_INIT_LOCKS _MD_INIT_LOCKS NSPR_API(PRStatus) _PR_MD_NEW_LOCK(_MDLock *md); #define _PR_MD_NEW_LOCK _MD_NEW_LOCK NSPR_API(void) _PR_MD_FREE_LOCK(_MDLock *md); #define _PR_MD_FREE_LOCK _MD_FREE_LOCK NSPR_API(void) _PR_MD_LOCK(_MDLock *md); #define _PR_MD_LOCK _MD_LOCK /* Return 0 on success, a nonzero value on failure. */ NSPR_API(PRIntn) _PR_MD_TEST_AND_LOCK(_MDLock *md); #define _PR_MD_TEST_AND_LOCK _MD_TEST_AND_LOCK NSPR_API(void) _PR_MD_UNLOCK(_MDLock *md); #define _PR_MD_UNLOCK _MD_UNLOCK NSPR_API(void) _PR_MD_IOQ_LOCK(void); #define _PR_MD_IOQ_LOCK _MD_IOQ_LOCK NSPR_API(void) _PR_MD_IOQ_UNLOCK(void); #define _PR_MD_IOQ_UNLOCK _MD_IOQ_UNLOCK #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ /* Semaphore related -- only for native threads */ #ifdef HAVE_CVAR_BUILT_ON_SEM NSPR_API(void) _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value); #define _PR_MD_NEW_SEM _MD_NEW_SEM NSPR_API(void) _PR_MD_DESTROY_SEM(_MDSemaphore *md); #define _PR_MD_DESTROY_SEM _MD_DESTROY_SEM NSPR_API(PRStatus) _PR_MD_TIMED_WAIT_SEM( _MDSemaphore *md, PRIntervalTime timeout); #define _PR_MD_TIMED_WAIT_SEM _MD_TIMED_WAIT_SEM NSPR_API(PRStatus) _PR_MD_WAIT_SEM(_MDSemaphore *md); #define _PR_MD_WAIT_SEM _MD_WAIT_SEM NSPR_API(void) _PR_MD_POST_SEM(_MDSemaphore *md); #define _PR_MD_POST_SEM _MD_POST_SEM #endif /* HAVE_CVAR_BUILT_ON_SEM */ #endif /* Condition Variables related -- only for native threads */ #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ NSPR_API(PRInt32) _PR_MD_NEW_CV(_MDCVar *md); #define _PR_MD_NEW_CV _MD_NEW_CV NSPR_API(void) _PR_MD_FREE_CV(_MDCVar *md); #define _PR_MD_FREE_CV _MD_FREE_CV NSPR_API(void) _PR_MD_WAIT_CV( _MDCVar *mdCVar,_MDLock *mdLock,PRIntervalTime timeout); #define _PR_MD_WAIT_CV _MD_WAIT_CV NSPR_API(void) _PR_MD_NOTIFY_CV(_MDCVar *md, _MDLock *lock); #define _PR_MD_NOTIFY_CV _MD_NOTIFY_CV NSPR_API(void) _PR_MD_NOTIFYALL_CV(_MDCVar *md, _MDLock *lock); #define _PR_MD_NOTIFYALL_CV _MD_NOTIFYALL_CV #endif /* _PR_LOCAL_THREADS_ONLY */ /* Threads related */ NSPR_API(PRThread*) _PR_MD_CURRENT_THREAD(void); #define _PR_MD_CURRENT_THREAD _MD_CURRENT_THREAD NSPR_API(PRThread*) _PR_MD_GET_ATTACHED_THREAD(void); #define _PR_MD_GET_ATTACHED_THREAD _MD_GET_ATTACHED_THREAD NSPR_API(PRThread*) _PR_MD_LAST_THREAD(void); #define _PR_MD_LAST_THREAD _MD_LAST_THREAD NSPR_API(void) _PR_MD_SET_CURRENT_THREAD(PRThread *thread); #define _PR_MD_SET_CURRENT_THREAD _MD_SET_CURRENT_THREAD NSPR_API(void) _PR_MD_SET_LAST_THREAD(PRThread *thread); #define _PR_MD_SET_LAST_THREAD _MD_SET_LAST_THREAD extern PRStatus _PR_MD_INIT_THREAD(PRThread *thread); #define _PR_MD_INIT_THREAD _MD_INIT_THREAD extern void _PR_MD_EXIT_THREAD(PRThread *thread); #define _PR_MD_EXIT_THREAD _MD_EXIT_THREAD #ifndef _PR_LOCAL_THREADS_ONLY /* not if only local threads supported */ NSPR_API(PRStatus) _PR_MD_INIT_ATTACHED_THREAD(PRThread *thread); #define _PR_MD_INIT_ATTACHED_THREAD _MD_INIT_ATTACHED_THREAD extern void _PR_MD_SUSPEND_THREAD(PRThread *thread); #define _PR_MD_SUSPEND_THREAD _MD_SUSPEND_THREAD extern void _PR_MD_RESUME_THREAD(PRThread *thread); #define _PR_MD_RESUME_THREAD _MD_RESUME_THREAD extern void _PR_MD_SUSPEND_CPU(_PRCPU *cpu); #define _PR_MD_SUSPEND_CPU _MD_SUSPEND_CPU extern void _PR_MD_RESUME_CPU(_PRCPU *cpu); #define _PR_MD_RESUME_CPU _MD_RESUME_CPU extern void _PR_MD_BEGIN_SUSPEND_ALL(void); #define _PR_MD_BEGIN_SUSPEND_ALL _MD_BEGIN_SUSPEND_ALL extern void _PR_MD_END_SUSPEND_ALL(void); #define _PR_MD_END_SUSPEND_ALL _MD_END_SUSPEND_ALL extern void _PR_MD_BEGIN_RESUME_ALL(void); #define _PR_MD_BEGIN_RESUME_ALL _MD_BEGIN_RESUME_ALL extern void _PR_MD_END_RESUME_ALL(void); #define _PR_MD_END_RESUME_ALL _MD_END_RESUME_ALL #if defined(IRIX) NSPR_API(void) _PR_IRIX_CHILD_PROCESS(void); #endif /* IRIX */ #endif /* !_PR_LOCAL_THREADS_ONLY */ extern void _PR_MD_CLEAN_THREAD(PRThread *thread); #define _PR_MD_CLEAN_THREAD _MD_CLEAN_THREAD #ifdef HAVE_CUSTOM_USER_THREADS extern void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *); #define _PR_MD_CREATE_PRIMORDIAL_USER_THREAD _MD_CREATE_PRIMORDIAL_USER_THREAD extern PRThread* _PR_MD_CREATE_USER_THREAD( PRUint32 stacksize, void (*start)(void *), void *arg); #define _PR_MD_CREATE_USER_THREAD _MD_CREATE_USER_THREAD #endif extern PRStatus _PR_MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); #define _PR_MD_CREATE_THREAD _MD_CREATE_THREAD extern void _PR_MD_JOIN_THREAD(_MDThread *md); #define _PR_MD_JOIN_THREAD _MD_JOIN_THREAD extern void _PR_MD_END_THREAD(void); #define _PR_MD_END_THREAD _MD_END_THREAD extern void _PR_MD_YIELD(void); #define _PR_MD_YIELD _MD_YIELD extern void _PR_MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri); #define _PR_MD_SET_PRIORITY _MD_SET_PRIORITY extern void _PR_MD_SET_CURRENT_THREAD_NAME(const char *name); #define _PR_MD_SET_CURRENT_THREAD_NAME _MD_SET_CURRENT_THREAD_NAME NSPR_API(void) _PR_MD_SUSPENDALL(void); #define _PR_MD_SUSPENDALL _MD_SUSPENDALL NSPR_API(void) _PR_MD_RESUMEALL(void); #define _PR_MD_RESUMEALL _MD_RESUMEALL extern void _PR_MD_INIT_CONTEXT( PRThread *thread, char *top, void (*start) (void), PRBool *status); #define _PR_MD_INIT_CONTEXT _MD_INIT_CONTEXT extern void _PR_MD_SWITCH_CONTEXT(PRThread *thread); #define _PR_MD_SWITCH_CONTEXT _MD_SWITCH_CONTEXT extern void _PR_MD_RESTORE_CONTEXT(PRThread *thread); #define _PR_MD_RESTORE_CONTEXT _MD_RESTORE_CONTEXT /* Segment related */ extern void _PR_MD_INIT_SEGS(void); #define _PR_MD_INIT_SEGS _MD_INIT_SEGS extern PRStatus _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr); #define _PR_MD_ALLOC_SEGMENT _MD_ALLOC_SEGMENT extern void _PR_MD_FREE_SEGMENT(PRSegment *seg); #define _PR_MD_FREE_SEGMENT _MD_FREE_SEGMENT /* Directory enumeration related */ extern PRStatus _PR_MD_OPEN_DIR(_MDDir *md,const char *name); #define _PR_MD_OPEN_DIR _MD_OPEN_DIR extern char * _PR_MD_READ_DIR(_MDDir *md, PRIntn flags); #define _PR_MD_READ_DIR _MD_READ_DIR extern PRInt32 _PR_MD_CLOSE_DIR(_MDDir *md); #define _PR_MD_CLOSE_DIR _MD_CLOSE_DIR /* Named semaphores related */ extern PRSem * _PR_MD_OPEN_SEMAPHORE( const char *osname, PRIntn flags, PRIntn mode, PRUintn value); #define _PR_MD_OPEN_SEMAPHORE _MD_OPEN_SEMAPHORE extern PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem); #define _PR_MD_WAIT_SEMAPHORE _MD_WAIT_SEMAPHORE extern PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem); #define _PR_MD_POST_SEMAPHORE _MD_POST_SEMAPHORE extern PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem); #define _PR_MD_CLOSE_SEMAPHORE _MD_CLOSE_SEMAPHORE extern PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname); #define _PR_MD_DELETE_SEMAPHORE _MD_DELETE_SEMAPHORE /* I/O related */ extern void _PR_MD_INIT_FILEDESC(PRFileDesc *fd); #define _PR_MD_INIT_FILEDESC _MD_INIT_FILEDESC extern void _PR_MD_MAKE_NONBLOCK(PRFileDesc *fd); #define _PR_MD_MAKE_NONBLOCK _MD_MAKE_NONBLOCK /* File I/O related */ extern PROsfd _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode); #define _PR_MD_OPEN _MD_OPEN extern PROsfd _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode); #define _PR_MD_OPEN_FILE _MD_OPEN_FILE extern PRInt32 _PR_MD_CLOSE_FILE(PROsfd osfd); #define _PR_MD_CLOSE_FILE _MD_CLOSE_FILE extern PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 amount); #define _PR_MD_READ _MD_READ extern PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 amount); #define _PR_MD_WRITE _MD_WRITE extern PRInt32 _PR_MD_WRITEV( PRFileDesc *fd, const struct PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout); #define _PR_MD_WRITEV _MD_WRITEV extern PRInt32 _PR_MD_FSYNC(PRFileDesc *fd); #define _PR_MD_FSYNC _MD_FSYNC extern PRInt32 _PR_MD_DELETE(const char *name); #define _PR_MD_DELETE _MD_DELETE extern PRInt32 _PR_MD_RENAME(const char *from, const char *to); #define _PR_MD_RENAME _MD_RENAME extern PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how); #define _PR_MD_ACCESS _MD_ACCESS extern PRInt32 _PR_MD_STAT(const char *name, struct stat *buf); #define _PR_MD_STAT _MD_STAT extern PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode); #define _PR_MD_MKDIR _MD_MKDIR extern PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode); #define _PR_MD_MAKE_DIR _MD_MAKE_DIR extern PRInt32 _PR_MD_RMDIR(const char *name); #define _PR_MD_RMDIR _MD_RMDIR #ifdef MOZ_UNICODE /* UTF16 File I/O related */ extern PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *md, const PRUnichar *name); #define _PR_MD_OPEN_DIR_UTF16 _MD_OPEN_DIR_UTF16 extern PROsfd _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, PRIntn mode); #define _PR_MD_OPEN_FILE_UTF16 _MD_OPEN_FILE_UTF16 extern PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *md, PRIntn flags); #define _PR_MD_READ_DIR_UTF16 _MD_READ_DIR_UTF16 extern PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *md); #define _PR_MD_CLOSE_DIR_UTF16 _MD_CLOSE_DIR_UTF16 extern PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info); #define _PR_MD_GETFILEINFO64_UTF16 _MD_GETFILEINFO64_UTF16 #endif /* MOZ_UNICODE */ /* Socket I/O related */ extern void _PR_MD_INIT_IO(void); #define _PR_MD_INIT_IO _MD_INIT_IO extern PRInt32 _PR_MD_CLOSE_SOCKET(PROsfd osfd); #define _PR_MD_CLOSE_SOCKET _MD_CLOSE_SOCKET extern PRInt32 _PR_MD_CONNECT( PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); #define _PR_MD_CONNECT _MD_CONNECT extern PROsfd _PR_MD_ACCEPT( PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); #define _PR_MD_ACCEPT _MD_ACCEPT extern PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen); #define _PR_MD_BIND _MD_BIND extern PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog); #define _PR_MD_LISTEN _MD_LISTEN extern PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how); #define _PR_MD_SHUTDOWN _MD_SHUTDOWN extern PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); #define _PR_MD_RECV _MD_RECV extern PRInt32 _PR_MD_SEND( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout); #define _PR_MD_SEND _MD_SEND extern PRInt32 _PR_MD_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout); #define _PR_MD_ACCEPT_READ _MD_ACCEPT_READ #ifdef WIN32 extern PROsfd _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg); extern PRInt32 _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg); extern void _PR_MD_UPDATE_ACCEPT_CONTEXT(PROsfd s, PROsfd ls); #define _PR_MD_UPDATE_ACCEPT_CONTEXT _MD_UPDATE_ACCEPT_CONTEXT /* * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. * We store the value in a PRTime variable for convenience. * This constant is used by _PR_FileTimeToPRTime(). * This is defined in ntmisc.c */ extern const PRTime _pr_filetime_offset; #endif /* WIN32 */ extern PRInt32 _PR_MD_SENDFILE( PRFileDesc *sock, PRSendFileData *sfd, PRInt32 flags, PRIntervalTime timeout); #define _PR_MD_SENDFILE _MD_SENDFILE extern PRStatus _PR_MD_GETSOCKNAME( PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); #define _PR_MD_GETSOCKNAME _MD_GETSOCKNAME extern PRStatus _PR_MD_GETPEERNAME( PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen); #define _PR_MD_GETPEERNAME _MD_GETPEERNAME extern PRStatus _PR_MD_GETSOCKOPT( PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen); #define _PR_MD_GETSOCKOPT _MD_GETSOCKOPT extern PRStatus _PR_MD_SETSOCKOPT( PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen); #define _PR_MD_SETSOCKOPT _MD_SETSOCKOPT extern PRStatus PR_CALLBACK _PR_SocketGetSocketOption( PRFileDesc *fd, PRSocketOptionData *data); extern PRStatus PR_CALLBACK _PR_SocketSetSocketOption( PRFileDesc *fd, const PRSocketOptionData *data); extern PRInt32 _PR_MD_RECVFROM( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout); #define _PR_MD_RECVFROM _MD_RECVFROM extern PRInt32 _PR_MD_SENDTO( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout); #define _PR_MD_SENDTO _MD_SENDTO extern PRInt32 _PR_MD_SOCKETPAIR(int af, int type, int flags, PROsfd *osfd); #define _PR_MD_SOCKETPAIR _MD_SOCKETPAIR extern PROsfd _PR_MD_SOCKET(int af, int type, int flags); #define _PR_MD_SOCKET _MD_SOCKET extern PRInt32 _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd); #define _PR_MD_SOCKETAVAILABLE _MD_SOCKETAVAILABLE extern PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd); #define _PR_MD_PIPEAVAILABLE _MD_PIPEAVAILABLE extern PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout); #define _PR_MD_PR_POLL _MD_PR_POLL /* * Initialize fd->secret->inheritable for a newly created fd. * If 'imported' is false, the osfd (i.e., fd->secret->md.osfd) * was created by NSPR and hence has the OS-dependent default * inheritable attribute. If 'imported' is true, the osfd was * not created by NSPR and hence a system call is required to * query its inheritable attribute. Since we may never need to * know the inheritable attribute of a fd, a platform may choose * to initialize fd->secret->inheritable of an imported fd to * _PR_TRI_UNKNOWN and only pay the cost of the system call * (in _PR_MD_QUERY_FD_INHERITABLE) when necessary. */ extern void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported); #define _PR_MD_INIT_FD_INHERITABLE _MD_INIT_FD_INHERITABLE extern PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable); #define _PR_MD_SET_FD_INHERITABLE _MD_SET_FD_INHERITABLE #define _PR_PROCESS_TIMEOUT_INTERRUPT_ERRORS(me) \ if (_PR_PENDING_INTERRUPT(me)) { \ me->flags &= ~_PR_INTERRUPT; \ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); \ } else { \ PR_SetError(PR_IO_TIMEOUT_ERROR, 0); \ } extern void *_PR_MD_GET_SP(PRThread *thread); #define _PR_MD_GET_SP _MD_GET_SP #endif /* defined(_PR_PTHREADS) */ /************************************************************************/ /************************************************************************* ** The remainder of the definitions are shared by pthreads and the classic ** NSPR code. These too may be conditionalized. *************************************************************************/ /************************************************************************/ extern PROffset32 _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence); #define _PR_MD_LSEEK _MD_LSEEK extern PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence); #define _PR_MD_LSEEK64 _MD_LSEEK64 extern PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info); #define _PR_MD_GETFILEINFO _MD_GETFILEINFO extern PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info); #define _PR_MD_GETFILEINFO64 _MD_GETFILEINFO64 extern PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info); #define _PR_MD_GETOPENFILEINFO _MD_GETOPENFILEINFO extern PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info); #define _PR_MD_GETOPENFILEINFO64 _MD_GETOPENFILEINFO64 /*****************************************************************************/ /************************** File descriptor caching **************************/ /*****************************************************************************/ extern void _PR_InitFdCache(void); extern void _PR_CleanupFdCache(void); extern PRFileDesc *_PR_Getfd(void); extern void _PR_Putfd(PRFileDesc *fd); /* * These flags are used by NSPR temporarily in the poll * descriptor's out_flags field to record the mapping of * NSPR's poll flags to the system poll flags. * * If _PR_POLL_READ_SYS_WRITE bit is set, it means the * PR_POLL_READ flag specified by the topmost layer is * mapped to the WRITE flag at the system layer. Similarly * for the other three _PR_POLL_XXX_SYS_YYY flags. It is * assumed that the PR_POLL_EXCEPT flag doesn't get mapped * to other flags. */ #define _PR_POLL_READ_SYS_READ 0x1 #define _PR_POLL_READ_SYS_WRITE 0x2 #define _PR_POLL_WRITE_SYS_READ 0x4 #define _PR_POLL_WRITE_SYS_WRITE 0x8 /* ** These methods are coerced into file descriptor methods table ** when the intended service is inappropriate for the particular ** type of file descriptor. */ extern PRIntn _PR_InvalidInt(void); extern PRInt16 _PR_InvalidInt16(void); extern PRInt64 _PR_InvalidInt64(void); extern PRStatus _PR_InvalidStatus(void); extern PRFileDesc *_PR_InvalidDesc(void); extern PRIOMethods _pr_faulty_methods; /* ** The PR_NETADDR_SIZE macro can only be called on a PRNetAddr union ** whose 'family' field is set. It returns the size of the union ** member corresponding to the specified address family. */ extern PRUintn _PR_NetAddrSize(const PRNetAddr* addr); #if defined(_PR_INET6) #define PR_NETADDR_SIZE(_addr) _PR_NetAddrSize(_addr) #elif defined(_PR_HAVE_MD_SOCKADDR_IN6) /* ** Under the following conditions: ** 1. _PR_INET6 is not defined; ** 2. _PR_INET6_PROBE is defined; ** 3. struct sockaddr_in6 has nonstandard fields at the end ** (e.g., on Solaris 8), ** (_addr)->ipv6 is smaller than struct sockaddr_in6, and ** hence we can't pass sizeof((_addr)->ipv6) to socket ** functions such as connect because they would fail with ** EINVAL. ** ** To pass the correct socket address length to socket ** functions, define the macro _PR_HAVE_MD_SOCKADDR_IN6 and ** define struct _md_sockaddr_in6 to be isomorphic to ** struct sockaddr_in6. */ #if defined(XP_UNIX) || defined(XP_OS2) #define PR_NETADDR_SIZE(_addr) \ ((_addr)->raw.family == PR_AF_INET \ ? sizeof((_addr)->inet) \ : ((_addr)->raw.family == PR_AF_INET6 \ ? sizeof(struct _md_sockaddr_in6) \ : sizeof((_addr)->local))) #else #define PR_NETADDR_SIZE(_addr) \ ((_addr)->raw.family == PR_AF_INET \ ? sizeof((_addr)->inet) \ : sizeof(struct _md_sockaddr_in6)) #endif /* defined(XP_UNIX) */ #else #if defined(XP_UNIX) || defined(XP_OS2) #define PR_NETADDR_SIZE(_addr) \ ((_addr)->raw.family == PR_AF_INET \ ? sizeof((_addr)->inet) \ : ((_addr)->raw.family == PR_AF_INET6 \ ? sizeof((_addr)->ipv6) \ : sizeof((_addr)->local))) #else #define PR_NETADDR_SIZE(_addr) \ ((_addr)->raw.family == PR_AF_INET \ ? sizeof((_addr)->inet) \ : sizeof((_addr)->ipv6)) #endif /* defined(XP_UNIX) */ #endif /* defined(_PR_INET6) */ extern PRStatus _PR_MapOptionName( PRSockOption optname, PRInt32 *level, PRInt32 *name); extern void _PR_InitThreads( PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs); struct PRLock { #if defined(_PR_PTHREADS) pthread_mutex_t mutex; /* the underlying lock */ _PT_Notified notified; /* array of conditions notified */ PRBool locked; /* whether the mutex is locked */ pthread_t owner; /* if locked, current lock owner */ #elif defined(_PR_BTHREADS) sem_id semaphoreID; /* the underlying lock */ int32 benaphoreCount; /* number of people in lock */ thread_id owner; /* current lock owner */ #else /* not pthreads or Be threads */ PRCList links; /* linkage for PRThread.lockList */ struct PRThread *owner; /* current lock owner */ PRCList waitQ; /* list of threads waiting for lock */ PRThreadPriority priority; /* priority of lock */ PRThreadPriority boostPriority; /* boosted priority of lock owner */ _MDLock ilock; /* Internal Lock to protect user-level fields */ #endif }; struct PRCondVar { PRLock *lock; /* associated lock that protects the condition */ #if defined(_PR_PTHREADS) pthread_cond_t cv; /* underlying pthreads condition */ PRInt32 notify_pending; /* CV has destroy pending notification */ #elif defined(_PR_BTHREADS) sem_id sem; /* the underlying lock */ sem_id handshakeSem; /* the lock for 'notify'-threads waiting for confirmation */ sem_id signalSem; /* the lock for threads waiting for someone to notify */ volatile int32 nw; /* the number waiting */ volatile int32 ns; /* the number signalling */ long signalBenCount; /* the number waiting on the underlying sem */ #else /* not pthreads or Be threads */ PRCList condQ; /* Condition variable wait Q */ _MDLock ilock; /* Internal Lock to protect condQ */ _MDCVar md; #endif }; /************************************************************************/ struct PRMonitor { const char* name; /* monitor name for debugging */ #if defined(_PR_PTHREADS) pthread_mutex_t lock; /* lock is only held when accessing fields * of the PRMonitor, instead of being held * while the monitor is entered. The only * exception is notifyTimes, which is * protected by the monitor. */ pthread_t owner; /* the owner of the monitor or invalid */ pthread_cond_t entryCV; /* for threads waiting to enter the monitor */ pthread_cond_t waitCV; /* for threads waiting on the monitor */ PRInt32 refCount; /* reference count, an atomic variable. * PR_NewMonitor adds a reference to the * newly created PRMonitor, and * PR_DestroyMonitor releases that reference. * PR_ExitMonitor adds a reference before * unlocking the internal lock if it needs to * signal entryCV, and releases the reference * after signaling entryCV. */ #else /* defined(_PR_PTHREADS) */ PRLock lock; /* lock is only held when accessing fields * of the PRMonitor, instead of being held * while the monitor is entered. The only * exception is notifyTimes, which is * protected by the monitor. */ PRThread *owner; /* the owner of the monitor or invalid */ PRCondVar entryCV; /* for threads waiting to enter the monitor */ PRCondVar waitCV; /* for threads waiting on the monitor */ #endif /* defined(_PR_PTHREADS) */ PRUint32 entryCount; /* # of times re-entered */ PRIntn notifyTimes; /* number of pending notifies for waitCV. * The special value -1 means a broadcast * (PR_NotifyAll). */ }; /************************************************************************/ struct PRSemaphore { #if defined(_PR_BTHREADS) sem_id sem; int32 benaphoreCount; #else PRCondVar *cvar; /* associated lock and condition variable queue */ PRUintn count; /* the value of the counting semaphore */ PRUint32 waiters; /* threads waiting on the semaphore */ #if defined(_PR_PTHREADS) #else /* defined(_PR_PTHREADS) */ _MDSemaphore md; #endif /* defined(_PR_PTHREADS) */ #endif /* defined(_PR_BTHREADS) */ }; /*************************************************************************/ struct PRSem { #ifdef _PR_HAVE_POSIX_SEMAPHORES sem_t *sem; #elif defined(_PR_HAVE_SYSV_SEMAPHORES) int semid; #elif defined(WIN32) HANDLE sem; #else PRInt8 notused; #endif }; /*************************************************************************/ struct PRStackStr { /* head MUST be at offset 0; assembly language code relies on this */ #if defined(AIX) volatile PRStackElem prstk_head; #else PRStackElem prstk_head; #endif PRLock *prstk_lock; char *prstk_name; }; /************************************************************************/ /* XXX this needs to be exported (sigh) */ struct PRThreadStack { PRCList links; PRUintn flags; char *allocBase; /* base of stack's allocated memory */ PRUint32 allocSize; /* size of stack's allocated memory */ char *stackBottom; /* bottom of stack from C's point of view */ char *stackTop; /* top of stack from C's point of view */ PRUint32 stackSize; /* size of usable portion of the stack */ PRSegment *seg; PRThread* thr; /* back pointer to thread owning this stack */ #if defined(_PR_PTHREADS) #else /* defined(_PR_PTHREADS) */ _MDThreadStack md; #endif /* defined(_PR_PTHREADS) */ }; extern void _PR_DestroyThreadPrivate(PRThread*); typedef void (PR_CALLBACK *_PRStartFn)(void *); struct PRThread { PRUint32 state; /* thread's creation state */ PRThreadPriority priority; /* apparent priority, loosly defined */ void *arg; /* argument to the client's entry point */ _PRStartFn startFunc; /* the root of the client's thread */ PRThreadStack *stack; /* info about thread's stack (for GC) */ void *environment; /* pointer to execution environment */ PRThreadDumpProc dump; /* dump thread info out */ void *dumpArg; /* argument for the dump function */ /* ** Per thread private data */ PRUint32 tpdLength; /* thread's current vector length */ void **privateData; /* private data vector or NULL */ PRErrorCode errorCode; /* current NSPR error code | zero */ PRInt32 osErrorCode; /* mapping of errorCode | zero */ PRIntn errorStringLength; /* textLength from last call to PR_SetErrorText() */ PRInt32 errorStringSize; /* malloc()'d size of buffer | zero */ char *errorString; /* current error string | NULL */ char *name; /* thread's name */ #if defined(_PR_PTHREADS) pthread_t id; /* pthread identifier for the thread */ PRBool idSet; /* whether 'id' has been set. Protected by * pt_book.ml. */ #ifdef _PR_NICE_PRIORITY_SCHEDULING pid_t tid; /* Linux-specific kernel thread ID */ #endif PRBool okToDelete; /* ok to delete the PRThread struct? */ PRCondVar *waiting; /* where the thread is waiting | NULL */ void *sp; /* recorded sp for garbage collection */ PRThread *next, *prev; /* simple linked list of all threads */ PRUint32 suspend; /* used to store suspend and resume flags */ #ifdef PT_NO_SIGTIMEDWAIT pthread_mutex_t suspendResumeMutex; pthread_cond_t suspendResumeCV; #endif PRUint32 interrupt_blocked; /* interrupt blocked */ struct pollfd *syspoll_list; /* Unix polling list used by PR_Poll */ PRUint32 syspoll_count; /* number of elements in syspoll_list */ #if defined(_PR_POLL_WITH_SELECT) int *selectfd_list; /* Unix fd's that PR_Poll selects on */ PRUint32 selectfd_count; /* number of elements in selectfd_list */ #endif #elif defined(_PR_BTHREADS) PRUint32 flags; _MDThread md; PRBool io_pending; PRInt32 io_fd; PRBool io_suspended; #else /* not pthreads or Be threads */ _MDLock threadLock; /* Lock to protect thread state variables. * Protects the following fields: * state * priority * links * wait * cpu */ PRUint32 queueCount; PRUint32 waitCount; PRCList active; /* on list of all active threads */ PRCList links; PRCList waitQLinks; /* when thread is PR_Wait'ing */ PRCList lockList; /* list of locks currently holding */ PRIntervalTime sleep; /* sleep time when thread is sleeping */ struct _wait { struct PRLock *lock; struct PRCondVar *cvar; } wait; PRUint32 id; PRUint32 flags; PRUint32 no_sched; /* Don't schedule the thread to run. * This flag has relevance only when * multiple NSPR CPUs are created. * When a thread is de-scheduled, there * is a narrow window of time in which * the thread is put on the run queue * but the scheduler is actually using * the stack of this thread. It is safe * to run this thread on a different CPU * only when its stack is not in use on * any other CPU. The no_sched flag is * set during this interval to prevent * the thread from being scheduled on a * different CPU. */ /* thread termination condition variable for join */ PRCondVar *term; _PRCPU *cpu; /* cpu to which this thread is bound */ PRUint32 threadAllocatedOnStack;/* boolean */ /* When an async IO is in progress and a second async IO cannot be * initiated, the io_pending flag is set to true. Some platforms will * not use the io_pending flag. If the io_pending flag is true, then * io_fd is the OS-file descriptor on which IO is pending. */ PRBool io_pending; PRInt32 io_fd; /* If a timeout occurs or if an outstanding IO is interrupted and the * OS doesn't support a real cancellation (NT or MAC), then the * io_suspended flag will be set to true. The thread will be resumed * but may run into trouble issuing additional IOs until the io_pending * flag can be cleared */ PRBool io_suspended; _MDThread md; #endif }; struct PRProcessAttr { PRFileDesc *stdinFd; PRFileDesc *stdoutFd; PRFileDesc *stderrFd; char *currentDirectory; char *fdInheritBuffer; PRSize fdInheritBufferSize; PRSize fdInheritBufferUsed; }; struct PRProcess { _MDProcess md; }; struct PRFileMap { PRFileDesc *fd; PRFileMapProtect prot; _MDFileMap md; }; /************************************************************************/ /* ** File descriptors of the NSPR layer can be in one of the ** following states (stored in the 'state' field of struct ** PRFilePrivate): ** - _PR_FILEDESC_OPEN: The OS fd is open. ** - _PR_FILEDESC_CLOSED: The OS fd is closed. The PRFileDesc ** is still open but is unusable. The only operation allowed ** on the PRFileDesc is PR_Close(). ** - _PR_FILEDESC_FREED: The OS fd is closed and the PRFileDesc ** structure is freed. */ #define _PR_FILEDESC_OPEN 0xaaaaaaaa /* 1010101... */ #define _PR_FILEDESC_CLOSED 0x55555555 /* 0101010... */ #define _PR_FILEDESC_FREED 0x11111111 /* ** A boolean type with an additional "unknown" state */ typedef enum { _PR_TRI_TRUE = 1, _PR_TRI_FALSE = 0, _PR_TRI_UNKNOWN = -1 } _PRTriStateBool; struct PRFilePrivate { PRInt32 state; PRBool nonblocking; _PRTriStateBool inheritable; PRFileDesc *next; PRIntn lockCount; /* 0: not locked * -1: a native lockfile call is in progress * > 0: # times the file is locked */ #ifdef _PR_HAVE_PEEK_BUFFER char *peekBuffer; PRInt32 peekBufSize; PRInt32 peekBytes; #endif #if !defined(_PR_HAVE_O_APPEND) PRBool appendMode; /* Some platforms don't have O_APPEND or its * equivalent, so they have to seek to end of * file on write if the file was opened in * append mode. See Bugzilla 4090, 276330. */ #endif _MDFileDesc md; #ifdef _PR_NEED_SECRET_AF PRUint16 af; /* If the platform's implementation of accept() * requires knowing the address family of the * socket, we save the address family here. */ #endif }; #ifdef _WIN64 #define PR_PRIdOSFD "lld" /* for printing PROsfd */ #define PR_PRIxOSFD "llx" #define PR_SCNdOSFD "lld" /* for scanning PROsfd */ #define PR_SCNxOSFD "llx" #else #define PR_PRIdOSFD "ld" /* for printing PROsfd */ #define PR_PRIxOSFD "lx" #define PR_SCNdOSFD "ld" /* for scanning PROsfd */ #define PR_SCNxOSFD "lx" #endif struct PRDir { PRDirEntry d; _MDDir md; }; #ifdef MOZ_UNICODE struct PRDirUTF16 { PRDirEntry d; _MDDirUTF16 md; }; #endif /* MOZ_UNICODE */ extern void _PR_InitLocks(void); extern void _PR_InitSegs(void); extern void _PR_InitStacks(void); extern void _PR_InitTPD(void); extern void _PR_InitMem(void); extern void _PR_InitEnv(void); extern void _PR_InitCMon(void); extern void _PR_InitIO(void); extern void _PR_InitLog(void); extern void _PR_InitNet(void); extern void _PR_InitClock(void); extern void _PR_InitLinker(void); extern void _PR_InitAtomic(void); extern void _PR_InitCPUs(void); extern void _PR_InitDtoa(void); extern void _PR_InitTime(void); extern void _PR_InitMW(void); extern void _PR_InitRWLocks(void); extern void _PR_CleanupThread(PRThread *thread); extern void _PR_CleanupCallOnce(void); extern void _PR_CleanupMW(void); extern void _PR_CleanupTime(void); extern void _PR_CleanupDtoa(void); extern void _PR_ShutdownLinker(void); extern void _PR_CleanupEnv(void); extern void _PR_CleanupIO(void); extern void _PR_CleanupCMon(void); extern void _PR_CleanupNet(void); extern void _PR_CleanupLayerCache(void); extern void _PR_CleanupStacks(void); #ifdef WINNT extern void _PR_CleanupCPUs(void); #endif extern void _PR_CleanupThreads(void); extern void _PR_CleanupTPD(void); extern void _PR_Cleanup(void); extern void _PR_LogCleanup(void); extern void _PR_InitLayerCache(void); extern PRBool _pr_initialized; extern void _PR_ImplicitInitialization(void); extern PRBool _PR_Obsolete(const char *obsolete, const char *preferred); /************************************************************************/ struct PRSegment { void *vaddr; PRUint32 size; PRUintn flags; #if defined(_PR_PTHREADS) #else /* defined(_PR_PTHREADS) */ _MDSegment md; #endif /* defined(_PR_PTHREADS) */ }; /* PRSegment.flags */ #define _PR_SEG_VM 0x1 /************************************************************************/ extern PRInt32 _pr_pageSize; extern PRInt32 _pr_pageShift; extern PRLogModuleInfo *_pr_clock_lm; extern PRLogModuleInfo *_pr_cmon_lm; extern PRLogModuleInfo *_pr_io_lm; extern PRLogModuleInfo *_pr_cvar_lm; extern PRLogModuleInfo *_pr_mon_lm; extern PRLogModuleInfo *_pr_linker_lm; extern PRLogModuleInfo *_pr_sched_lm; extern PRLogModuleInfo *_pr_thread_lm; extern PRLogModuleInfo *_pr_gc_lm; extern PRFileDesc *_pr_stdin; extern PRFileDesc *_pr_stdout; extern PRFileDesc *_pr_stderr; /* Zone allocator */ /* ** The zone allocator code has hardcoded pthread types and ** functions, so it can only be used in the pthreads version. ** This can be fixed by replacing the hardcoded pthread types ** and functions with macros that expand to the native thread ** types and functions on each platform. */ #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #define _PR_ZONE_ALLOCATOR #endif #ifdef _PR_ZONE_ALLOCATOR extern void _PR_InitZones(void); extern void _PR_DestroyZones(void); #endif /* Overriding malloc, free, etc. */ #if !defined(_PR_NO_PREEMPT) && defined(XP_UNIX) \ && !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) \ && !defined(PURIFY) \ && !defined(DARWIN) \ && !defined(QNX) \ && !(defined (UNIXWARE) && defined (USE_SVR4_THREADS)) #define _PR_OVERRIDE_MALLOC #endif /************************************************************************* * External machine-dependent code provided by each OS. * * *************************************************************************/ /* Initialization related */ extern void _PR_MD_EARLY_INIT(void); #define _PR_MD_EARLY_INIT _MD_EARLY_INIT extern void _PR_MD_INTERVAL_INIT(void); #define _PR_MD_INTERVAL_INIT _MD_INTERVAL_INIT NSPR_API(void) _PR_MD_FINAL_INIT(void); #define _PR_MD_FINAL_INIT _MD_FINAL_INIT extern void _PR_MD_EARLY_CLEANUP(void); #define _PR_MD_EARLY_CLEANUP _MD_EARLY_CLEANUP /* Process control */ extern PRProcess * _PR_MD_CREATE_PROCESS( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr); #define _PR_MD_CREATE_PROCESS _MD_CREATE_PROCESS extern PRStatus _PR_MD_DETACH_PROCESS(PRProcess *process); #define _PR_MD_DETACH_PROCESS _MD_DETACH_PROCESS extern PRStatus _PR_MD_WAIT_PROCESS(PRProcess *process, PRInt32 *exitCode); #define _PR_MD_WAIT_PROCESS _MD_WAIT_PROCESS extern PRStatus _PR_MD_KILL_PROCESS(PRProcess *process); #define _PR_MD_KILL_PROCESS _MD_KILL_PROCESS /* Current Time */ NSPR_API(PRTime) _PR_MD_NOW(void); #define _PR_MD_NOW _MD_NOW /* Environment related */ extern char* _PR_MD_GET_ENV(const char *name); #define _PR_MD_GET_ENV _MD_GET_ENV extern PRIntn _PR_MD_PUT_ENV(const char *name); #define _PR_MD_PUT_ENV _MD_PUT_ENV /* Atomic operations */ extern void _PR_MD_INIT_ATOMIC(void); #define _PR_MD_INIT_ATOMIC _MD_INIT_ATOMIC extern PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *); #define _PR_MD_ATOMIC_INCREMENT _MD_ATOMIC_INCREMENT extern PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *, PRInt32); #define _PR_MD_ATOMIC_ADD _MD_ATOMIC_ADD extern PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *); #define _PR_MD_ATOMIC_DECREMENT _MD_ATOMIC_DECREMENT extern PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *, PRInt32); #define _PR_MD_ATOMIC_SET _MD_ATOMIC_SET /* Garbage collection */ /* ** Save the registers that the GC would find interesting into the thread ** "t". isCurrent will be non-zero if the thread state that is being ** saved is the currently executing thread. Return the address of the ** first register to be scanned as well as the number of registers to ** scan in "np". ** ** If "isCurrent" is non-zero then it is allowed for the thread context ** area to be used as scratch storage to hold just the registers ** necessary for scanning. */ extern PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np); /* Time intervals */ extern PRIntervalTime _PR_MD_GET_INTERVAL(void); #define _PR_MD_GET_INTERVAL _MD_GET_INTERVAL extern PRIntervalTime _PR_MD_INTERVAL_PER_SEC(void); #define _PR_MD_INTERVAL_PER_SEC _MD_INTERVAL_PER_SEC /* Affinity masks */ extern PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ); #define _PR_MD_SETTHREADAFFINITYMASK _MD_SETTHREADAFFINITYMASK extern PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask); #define _PR_MD_GETTHREADAFFINITYMASK _MD_GETTHREADAFFINITYMASK /* File locking */ extern PRStatus _PR_MD_LOCKFILE(PROsfd osfd); #define _PR_MD_LOCKFILE _MD_LOCKFILE extern PRStatus _PR_MD_TLOCKFILE(PROsfd osfd); #define _PR_MD_TLOCKFILE _MD_TLOCKFILE extern PRStatus _PR_MD_UNLOCKFILE(PROsfd osfd); #define _PR_MD_UNLOCKFILE _MD_UNLOCKFILE /* Memory-mapped files */ extern PRStatus _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size); #define _PR_MD_CREATE_FILE_MAP _MD_CREATE_FILE_MAP extern PRInt32 _PR_MD_GET_MEM_MAP_ALIGNMENT(void); #define _PR_MD_GET_MEM_MAP_ALIGNMENT _MD_GET_MEM_MAP_ALIGNMENT extern void * _PR_MD_MEM_MAP( PRFileMap *fmap, PROffset64 offset, PRUint32 len); #define _PR_MD_MEM_MAP _MD_MEM_MAP extern PRStatus _PR_MD_MEM_UNMAP(void *addr, PRUint32 size); #define _PR_MD_MEM_UNMAP _MD_MEM_UNMAP extern PRStatus _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap); #define _PR_MD_CLOSE_FILE_MAP _MD_CLOSE_FILE_MAP extern PRStatus _PR_MD_SYNC_MEM_MAP( PRFileDesc *fd, void *addr, PRUint32 len); #define _PR_MD_SYNC_MEM_MAP _MD_SYNC_MEM_MAP /* Named Shared Memory */ /* ** Declare PRSharedMemory. */ struct PRSharedMemory { char *ipcname; /* after conversion to native */ PRSize size; /* from open */ PRIntn mode; /* from open */ PRIntn flags; /* from open */ #if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY) int id; #elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY) int id; #elif defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY) HANDLE handle; #else PRUint32 nothing; /* placeholder, nothing behind here */ #endif PRUint32 ident; /* guard word at end of struct */ #define _PR_SHM_IDENT 0xdeadbad }; extern PRSharedMemory * _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ); #define _PR_MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ); #define _PR_MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ); #define _PR_MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ); #define _PR_MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory extern PRStatus _MD_DeleteSharedMemory( const char *name ); #define _PR_MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory extern PRFileMap* _md_OpenAnonFileMap( const char *dirName, PRSize size, PRFileMapProtect prot ); #define _PR_MD_OPEN_ANON_FILE_MAP _md_OpenAnonFileMap extern PRStatus _md_ExportFileMapAsString( PRFileMap *fm, PRSize bufSize, char *buf ); #define _PR_MD_EXPORT_FILE_MAP_AS_STRING _md_ExportFileMapAsString extern PRFileMap * _md_ImportFileMapFromString( const char *fmstring ); #define _PR_MD_IMPORT_FILE_MAP_FROM_STRING _md_ImportFileMapFromString /* Interprocess communications (IPC) */ /* * The maximum length of an NSPR IPC name, including the * terminating null byte. */ #define PR_IPC_NAME_SIZE 1024 /* * Types of NSPR IPC objects */ typedef enum { _PRIPCSem, /* semaphores */ _PRIPCShm /* shared memory segments */ } _PRIPCType; /* * Make a native IPC name from an NSPR IPC name. */ extern PRStatus _PR_MakeNativeIPCName( const char *name, /* NSPR IPC name */ char *result, /* result buffer */ PRIntn size, /* size of result buffer */ _PRIPCType type /* type of IPC object */ ); /* Socket call error code */ NSPR_API(PRInt32) _PR_MD_GET_SOCKET_ERROR(void); #define _PR_MD_GET_SOCKET_ERROR _MD_GET_SOCKET_ERROR /* Get name of current host */ extern PRStatus _PR_MD_GETHOSTNAME(char *name, PRUint32 namelen); #define _PR_MD_GETHOSTNAME _MD_GETHOSTNAME extern PRStatus _PR_MD_GETSYSINFO(PRSysInfo cmd, char *name, PRUint32 namelen); #define _PR_MD_GETSYSINFO _MD_GETSYSINFO /* File descriptor inheritance */ /* * If fd->secret->inheritable is _PR_TRI_UNKNOWN and we need to * know the inheritable attribute of the fd, call this function * to find that out. This typically requires a system call. */ extern void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd); #define _PR_MD_QUERY_FD_INHERITABLE _MD_QUERY_FD_INHERITABLE /* --- PR_GetRandomNoise() related things --- */ extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size ); #define _PR_MD_GET_RANDOM_NOISE(buf,size) _PR_MD_GetRandomNoise((buf),(size)) extern PRSize _pr_CopyLowBits( void *dest, PRSize dstlen, void *src, PRSize srclen ); /* end PR_GetRandomNoise() related */ #ifdef XP_BEOS extern PRLock *_connectLock; typedef struct _ConnectListNode { PRInt32 osfd; PRNetAddr addr; PRUint32 addrlen; PRIntervalTime timeout; } ConnectListNode; extern ConnectListNode connectList[64]; extern PRUint32 connectCount; #endif /* XP_BEOS */ PR_END_EXTERN_C #endif /* primpl_h___ */ nspr-4.11/nspr/pr/include/private/prpriv.h0000644000000000000000000000067212623070344016750 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prpriv_h___ #define prpriv_h___ /* * NSPR 2.0 Private API */ #include "private/pprio.h" #include "private/pprthred.h" #endif /* prpriv_h___ */ nspr-4.11/nspr/pr/include/prlink.h0000644000000000000000000002021712623070344015250 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prlink_h___ #define prlink_h___ /* ** API to static and dynamic linking. */ #include "prtypes.h" PR_BEGIN_EXTERN_C typedef struct PRLibrary PRLibrary; typedef struct PRStaticLinkTable { const char *name; void (*fp)(void); } PRStaticLinkTable; /* ** Change the default library path to the given string. The string is ** copied. This call will fail if it runs out of memory. ** ** The string provided as 'path' is copied. The caller can do whatever is ** convenient with the argument when the function is complete. */ NSPR_API(PRStatus) PR_SetLibraryPath(const char *path); /* ** Return a character string which contains the path used to search for ** dynamically loadable libraries. ** ** The returned value is basically a copy of a PR_SetLibraryPath(). ** The storage is allocated by the runtime and becomes the responsibilty ** of the caller. */ NSPR_API(char*) PR_GetLibraryPath(void); /* ** Given a directory name "dir" and a library name "lib" construct a full ** path name that will refer to the actual dynamically loaded ** library. This does not test for existance of said file, it just ** constructs the full filename. The name constructed is system dependent ** and prepared for PR_LoadLibrary. The result must be free'd when the ** caller is done with it. ** ** The storage for the result is allocated by the runtime and becomes the ** responsibility of the caller. */ NSPR_API(char*) PR_GetLibraryName(const char *dir, const char *lib); /* ** ** Free the memory allocated, for the caller, by PR_GetLibraryName */ NSPR_API(void) PR_FreeLibraryName(char *mem); /* ** Given a library "name" try to load the library. The argument "name" ** is a machine-dependent name for the library, such as the full pathname ** returned by PR_GetLibraryName. If the library is already loaded, ** this function will avoid loading the library twice. ** ** If the library is loaded successfully, then a pointer to the PRLibrary ** structure representing the library is returned. Otherwise, NULL is ** returned. ** ** This increments the reference count of the library. */ NSPR_API(PRLibrary*) PR_LoadLibrary(const char *name); /* ** Each operating system has its preferred way of specifying ** a file in the file system. Most operating systems use ** a pathname. Mac OS Classic, on the other hand, uses the FSSpec ** structure to specify a file. PRLibSpec allows NSPR clients ** to use the type of file specification that is most efficient ** for a particular platform. ** ** On some operating systems such as Mac OS Classic, a shared library ** may contain code fragments that can be individually loaded. ** PRLibSpec also allows NSPR clients to identify a code fragment ** in a library, if code fragments are supported by the OS. ** A code fragment can be specified by name or by an integer index. ** ** Right now PRLibSpec supports four types of library specification: ** a pathname in the native character encoding, a Mac code fragment ** by name, a Mac code fragment by index, and a UTF-16 pathname. */ typedef enum PRLibSpecType { PR_LibSpec_Pathname, PR_LibSpec_MacNamedFragment, /* obsolete (for Mac OS Classic) */ PR_LibSpec_MacIndexedFragment, /* obsolete (for Mac OS Classic) */ PR_LibSpec_PathnameU /* supported only on Win32 */ } PRLibSpecType; struct FSSpec; /* Mac OS Classic FSSpec */ typedef struct PRLibSpec { PRLibSpecType type; union { /* if type is PR_LibSpec_Pathname */ const char *pathname; /* if type is PR_LibSpec_MacNamedFragment */ struct { const struct FSSpec *fsspec; const char *name; } mac_named_fragment; /* obsolete (for Mac OS Classic) */ /* if type is PR_LibSpec_MacIndexedFragment */ struct { const struct FSSpec *fsspec; PRUint32 index; } mac_indexed_fragment; /* obsolete (for Mac OS Classic) */ /* if type is PR_LibSpec_PathnameU */ const PRUnichar *pathname_u; /* supported only on Win32 */ } value; } PRLibSpec; /* ** The following bit flags may be or'd together and passed ** as the 'flags' argument to PR_LoadLibraryWithFlags. ** Flags not supported by the underlying OS are ignored. */ #define PR_LD_LAZY 0x1 /* equivalent to RTLD_LAZY on Unix */ #define PR_LD_NOW 0x2 /* equivalent to RTLD_NOW on Unix */ #define PR_LD_GLOBAL 0x4 /* equivalent to RTLD_GLOBAL on Unix */ #define PR_LD_LOCAL 0x8 /* equivalent to RTLD_LOCAL on Unix */ /* The following is equivalent to LOAD_WITH_ALTERED_SEARCH_PATH on Windows */ #define PR_LD_ALT_SEARCH_PATH 0x10 /* 0x8000 reserved for NSPR internal use */ /* ** Load the specified library, in the manner specified by 'flags'. */ NSPR_API(PRLibrary *) PR_LoadLibraryWithFlags( PRLibSpec libSpec, /* the shared library */ PRIntn flags /* flags that affect the loading */ ); /* ** Unload a previously loaded library. If the library was a static ** library then the static link table will no longer be referenced. The ** associated PRLibrary object is freed. ** ** PR_FAILURE is returned if the library cannot be unloaded. ** ** This function decrements the reference count of the library. */ NSPR_API(PRStatus) PR_UnloadLibrary(PRLibrary *lib); /* ** Given the name of a procedure, return the address of the function that ** implements the procedure, or NULL if no such function can be ** found. This does not find symbols in the main program (the ".exe"); ** use PR_LoadStaticLibrary to register symbols in the main program. ** ** This function does not modify the reference count of the library. */ NSPR_API(void*) PR_FindSymbol(PRLibrary *lib, const char *name); /* ** Similar to PR_FindSymbol, except that the return value is a pointer to ** a function, and not a pointer to void. Casting between a data pointer ** and a function pointer is not portable according to the C standard. ** Any function pointer can be cast to any other function pointer. ** ** This function does not modify the reference count of the library. */ typedef void (*PRFuncPtr)(void); NSPR_API(PRFuncPtr) PR_FindFunctionSymbol(PRLibrary *lib, const char *name); /* ** Finds a symbol in one of the currently loaded libraries. Given the ** name of a procedure, return the address of the function that ** implements the procedure, and return the library that contains that ** symbol, or NULL if no such function can be found. This does not find ** symbols in the main program (the ".exe"); use PR_AddStaticLibrary to ** register symbols in the main program. ** ** This increments the reference count of the library. */ NSPR_API(void*) PR_FindSymbolAndLibrary(const char *name, PRLibrary* *lib); /* ** Similar to PR_FindSymbolAndLibrary, except that the return value is ** a pointer to a function, and not a pointer to void. Casting between a ** data pointer and a function pointer is not portable according to the C ** standard. Any function pointer can be cast to any other function pointer. ** ** This increments the reference count of the library. */ NSPR_API(PRFuncPtr) PR_FindFunctionSymbolAndLibrary(const char *name, PRLibrary* *lib); /* ** Register a static link table with the runtime under the name ** "name". The symbols present in the static link table will be made ** available to PR_FindSymbol. If "name" is null then the symbols will be ** made available to the library which represents the executable. The ** tables are not copied. ** ** Returns the library object if successful, null otherwise. ** ** This increments the reference count of the library. */ NSPR_API(PRLibrary*) PR_LoadStaticLibrary( const char *name, const PRStaticLinkTable *table); /* ** Return the pathname of the file that the library "name" was loaded ** from. "addr" is the address of a function defined in the library. ** ** The caller is responsible for freeing the result with PR_Free. */ NSPR_API(char *) PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr); PR_END_EXTERN_C #endif /* prlink_h___ */ nspr-4.11/nspr/pr/include/prlock.h0000644000000000000000000000734512623070344015252 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prlock.h ** Description: API to basic locking functions of NSPR. ** ** ** NSPR provides basic locking mechanisms for thread synchronization. Locks ** are lightweight resource contention controls that prevent multiple threads ** from accessing something (code/data) simultaneously. **/ #ifndef prlock_h___ #define prlock_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /**********************************************************************/ /************************* TYPES AND CONSTANTS ************************/ /**********************************************************************/ /* * PRLock -- * * NSPR represents the lock as an opaque entity to the client of the * API. All routines operate on a pointer to this opaque entity. */ typedef struct PRLock PRLock; /**********************************************************************/ /****************************** FUNCTIONS *****************************/ /**********************************************************************/ /*********************************************************************** ** FUNCTION: PR_NewLock ** DESCRIPTION: ** Returns a pointer to a newly created opaque lock object. ** INPUTS: void ** OUTPUTS: void ** RETURN: PRLock* ** If the lock can not be created because of resource constraints, NULL ** is returned. ** ***********************************************************************/ NSPR_API(PRLock*) PR_NewLock(void); /*********************************************************************** ** FUNCTION: PR_DestroyLock ** DESCRIPTION: ** Destroys a given opaque lock object. ** INPUTS: PRLock *lock ** Lock to be freed. ** OUTPUTS: void ** RETURN: None ***********************************************************************/ NSPR_API(void) PR_DestroyLock(PRLock *lock); /*********************************************************************** ** FUNCTION: PR_Lock ** DESCRIPTION: ** Lock a lock. ** INPUTS: PRLock *lock ** Lock to locked. ** OUTPUTS: void ** RETURN: None ***********************************************************************/ NSPR_API(void) PR_Lock(PRLock *lock); /*********************************************************************** ** FUNCTION: PR_Unlock ** DESCRIPTION: ** Unlock a lock. Unlocking an unlocked lock has undefined results. ** INPUTS: PRLock *lock ** Lock to unlocked. ** OUTPUTS: void ** RETURN: PR_STATUS ** Returns PR_FAILURE if the caller does not own the lock. ***********************************************************************/ NSPR_API(PRStatus) PR_Unlock(PRLock *lock); /*********************************************************************** ** MACRO: PR_ASSERT_CURRENT_THREAD_OWNS_LOCK ** DESCRIPTION: ** If the current thread owns |lock|, this assertion is guaranteed to ** succeed. Otherwise, the behavior of this function is undefined. ** INPUTS: PRLock *lock ** Lock to assert ownership of. ** OUTPUTS: void ** RETURN: None ***********************************************************************/ #if defined(DEBUG) || defined(FORCE_PR_ASSERT) #define PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(/* PrLock* */ lock) \ PR_AssertCurrentThreadOwnsLock(lock) #else #define PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(/* PrLock* */ lock) #endif /* Don't call this function directly. */ NSPR_API(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock); PR_END_EXTERN_C #endif /* prlock_h___ */ nspr-4.11/nspr/pr/include/prlog.h0000644000000000000000000001540212623070344015074 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prlog_h___ #define prlog_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** prlog.h -- Declare interfaces to NSPR's Logging service ** ** NSPR provides a logging service that is used by NSPR itself and is ** available to client programs. ** ** To use the service from a client program, you should create a ** PRLogModuleInfo structure by calling PR_NewLogModule(). After ** creating the LogModule, you can write to the log using the PR_LOG() ** macro. ** ** Initialization of the log service is handled by NSPR initialization. ** ** At execution time, you must enable the log service. To enable the ** log service, set the environment variable: NSPR_LOG_MODULES ** variable. ** ** NSPR_LOG_MODULES variable has the form: ** ** :[, :]* ** ** Where: ** is the name passed to PR_NewLogModule(). ** is a numeric constant, e.g. 5. This value is the maximum ** value of a log event, enumerated by PRLogModuleLevel, that you want ** written to the log. ** ** For example: to record all events of greater value than or equal to ** PR_LOG_ERROR for a LogModule names "gizmo", say: ** ** set NSPR_LOG_MODULES=gizmo:2 ** ** Note that you must specify the numeric value of PR_LOG_ERROR. ** ** Special LogModule names are provided for controlling NSPR's log ** service at execution time. These controls should be set in the ** NSPR_LOG_MODULES environment variable at execution time to affect ** NSPR's log service for your application. ** ** The special LogModule "all" enables all LogModules. To enable all ** LogModule calls to PR_LOG(), say: ** ** set NSPR_LOG_MODULES=all:5 ** ** The special LogModule name "sync" tells the NSPR log service to do ** unbuffered logging. ** ** The special LogModule name "bufsize:" tells NSPR to set the ** log buffer to . ** ** The environment variable NSPR_LOG_FILE specifies the log file to use ** unless the default of "stderr" is acceptable. For MS Windows ** systems, NSPR_LOG_FILE can be set to a special value: "WinDebug" ** (case sensitive). This value causes PR_LOG() output to be written ** using the Windows API OutputDebugString(). OutputDebugString() ** writes to the debugger window; some people find this helpful. ** ** ** To put log messages in your programs, use the PR_LOG macro: ** ** PR_LOG(, , (, *)); ** ** Where is the address of a PRLogModuleInfo structure, and ** is one of the levels defined by the enumeration: ** PRLogModuleLevel. is a printf() style of argument list. That ** is: (fmtstring, ...). ** ** Example: ** ** main() { ** PRIntn one = 1; ** PRLogModuleInfo * myLm = PR_NewLogModule("gizmo"); ** PR_LOG( myLm, PR_LOG_ALWAYS, ("Log this! %d\n", one)); ** return; ** } ** ** Note the use of printf() style arguments as the third agrument(s) to ** PR_LOG(). ** ** After compiling and linking you application, set the environment: ** ** set NSPR_LOG_MODULES=gizmo:5 ** set NSPR_LOG_FILE=logfile.txt ** ** When you execute your application, the string "Log this! 1" will be ** written to the file "logfile.txt". ** ** Note to NSPR engineers: a number of PRLogModuleInfo structures are ** defined and initialized in prinit.c. See this module for ideas on ** what to log where. ** */ typedef enum PRLogModuleLevel { PR_LOG_NONE = 0, /* nothing */ PR_LOG_ALWAYS = 1, /* always printed */ PR_LOG_ERROR = 2, /* error messages */ PR_LOG_WARNING = 3, /* warning messages */ PR_LOG_DEBUG = 4, /* debug messages */ PR_LOG_NOTICE = PR_LOG_DEBUG, /* notice messages */ PR_LOG_WARN = PR_LOG_WARNING, /* warning messages */ PR_LOG_MIN = PR_LOG_DEBUG, /* minimal debugging messages */ PR_LOG_MAX = PR_LOG_DEBUG /* maximal debugging messages */ } PRLogModuleLevel; /* ** One of these structures is created for each module that uses logging. ** "name" is the name of the module ** "level" is the debugging level selected for that module */ typedef struct PRLogModuleInfo { const char *name; PRLogModuleLevel level; struct PRLogModuleInfo *next; } PRLogModuleInfo; /* ** Create a new log module. */ NSPR_API(PRLogModuleInfo*) PR_NewLogModule(const char *name); /* ** Set the file to use for logging. Returns PR_FALSE if the file cannot ** be created */ NSPR_API(PRBool) PR_SetLogFile(const char *name); /* ** Set the size of the logging buffer. If "buffer_size" is zero then the ** logging becomes "synchronous" (or unbuffered). */ NSPR_API(void) PR_SetLogBuffering(PRIntn buffer_size); /* ** Print a string to the log. "fmt" is a PR_snprintf format type. All ** messages printed to the log are preceeded by the name of the thread ** and a time stamp. Also, the routine provides a missing newline if one ** is not provided. */ NSPR_API(void) PR_LogPrint(const char *fmt, ...); /* ** Flush the log to its file. */ NSPR_API(void) PR_LogFlush(void); NSPR_API(void) PR_Assert(const char *s, const char *file, PRIntn ln) PR_PRETEND_NORETURN; #if defined(DEBUG) || defined(FORCE_PR_LOG) #define PR_LOGGING 1 #define PR_LOG_TEST(_module,_level) \ ((_module)->level >= (_level)) /* ** Log something. ** "module" is the address of a PRLogModuleInfo structure ** "level" is the desired logging level ** "args" is a variable length list of arguments to print, in the following ** format: ("printf style format string", ...) */ #define PR_LOG(_module,_level,_args) \ PR_BEGIN_MACRO \ if (PR_LOG_TEST(_module,_level)) { \ PR_LogPrint _args; \ } \ PR_END_MACRO #else /* defined(DEBUG) || defined(FORCE_PR_LOG) */ #undef PR_LOGGING #define PR_LOG_TEST(module,level) 0 #define PR_LOG(module,level,args) #endif /* defined(DEBUG) || defined(FORCE_PR_LOG) */ #ifndef NO_NSPR_10_SUPPORT #ifdef PR_LOGGING #define PR_LOG_BEGIN PR_LOG #define PR_LOG_END PR_LOG #define PR_LOG_DEFINE PR_NewLogModule #else #define PR_LOG_BEGIN(module,level,args) #define PR_LOG_END(module,level,args) #define PR_LOG_DEFINE(_name) NULL #endif /* PR_LOGGING */ #endif /* NO_NSPR_10_SUPPORT */ #if defined(DEBUG) || defined(FORCE_PR_ASSERT) #define PR_ASSERT(_expr) \ ((_expr)?((void)0):PR_Assert(# _expr,__FILE__,__LINE__)) #define PR_NOT_REACHED(_reasonStr) \ PR_Assert(_reasonStr,__FILE__,__LINE__) #else #define PR_ASSERT(expr) ((void) 0) #define PR_NOT_REACHED(reasonStr) #endif /* defined(DEBUG) || defined(FORCE_PR_ASSERT) */ PR_END_EXTERN_C #endif /* prlog_h___ */ nspr-4.11/nspr/pr/include/prlong.h0000644000000000000000000003072612623070344015260 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prlong.h ** Description: Portable access to 64 bit numerics ** ** Long-long (64-bit signed integer type) support. Some C compilers ** don't support 64 bit integers yet, so we use these macros to ** support both machines that do and don't. **/ #ifndef prlong_h___ #define prlong_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /*********************************************************************** ** DEFINES: LL_MaxInt ** LL_MinInt ** LL_Zero ** LL_MaxUint ** DESCRIPTION: ** Various interesting constants and static variable ** initializer ***********************************************************************/ NSPR_API(PRInt64) LL_MaxInt(void); NSPR_API(PRInt64) LL_MinInt(void); NSPR_API(PRInt64) LL_Zero(void); NSPR_API(PRUint64) LL_MaxUint(void); #if defined(HAVE_LONG_LONG) /* Keep this in sync with prtypes.h. */ #if PR_BYTES_PER_LONG == 8 && !defined(PR_ALTERNATE_INT64_TYPEDEF) #define LL_MAXINT 9223372036854775807L #define LL_MININT (-LL_MAXINT - 1L) #define LL_ZERO 0L #define LL_MAXUINT 18446744073709551615UL #define LL_INIT(hi, lo) ((hi ## L << 32) + lo ## L) #elif defined(WIN32) && !defined(__GNUC__) #define LL_MAXINT 9223372036854775807i64 #define LL_MININT (-LL_MAXINT - 1i64) #define LL_ZERO 0i64 #define LL_MAXUINT 18446744073709551615ui64 #define LL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64) #else #define LL_MAXINT 9223372036854775807LL #define LL_MININT (-LL_MAXINT - 1LL) #define LL_ZERO 0LL #define LL_MAXUINT 18446744073709551615ULL #define LL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL) #endif /*********************************************************************** ** MACROS: LL_* ** DESCRIPTION: ** The following macros define portable access to the 64 bit ** math facilities. ** ***********************************************************************/ /*********************************************************************** ** MACROS: LL_ ** ** LL_IS_ZERO Test for zero ** LL_EQ Test for equality ** LL_NE Test for inequality ** LL_GE_ZERO Test for zero or positive ** LL_CMP Compare two values ***********************************************************************/ #define LL_IS_ZERO(a) ((a) == 0) #define LL_EQ(a, b) ((a) == (b)) #define LL_NE(a, b) ((a) != (b)) #define LL_GE_ZERO(a) ((a) >= 0) #define LL_CMP(a, op, b) ((PRInt64)(a) op (PRInt64)(b)) #define LL_UCMP(a, op, b) ((PRUint64)(a) op (PRUint64)(b)) /*********************************************************************** ** MACROS: LL_ ** ** LL_AND Logical and ** LL_OR Logical or ** LL_XOR Logical exclusion ** LL_OR2 A disgusting deviation ** LL_NOT Negation (one's complement) ***********************************************************************/ #define LL_AND(r, a, b) ((r) = (a) & (b)) #define LL_OR(r, a, b) ((r) = (a) | (b)) #define LL_XOR(r, a, b) ((r) = (a) ^ (b)) #define LL_OR2(r, a) ((r) = (r) | (a)) #define LL_NOT(r, a) ((r) = ~(a)) /*********************************************************************** ** MACROS: LL_ ** ** LL_NEG Negation (two's complement) ** LL_ADD Summation (two's complement) ** LL_SUB Difference (two's complement) ***********************************************************************/ #define LL_NEG(r, a) ((r) = -(a)) #define LL_ADD(r, a, b) ((r) = (a) + (b)) #define LL_SUB(r, a, b) ((r) = (a) - (b)) /*********************************************************************** ** MACROS: LL_ ** ** LL_MUL Product (two's complement) ** LL_DIV Quotient (two's complement) ** LL_MOD Modulus (two's complement) ***********************************************************************/ #define LL_MUL(r, a, b) ((r) = (a) * (b)) #define LL_DIV(r, a, b) ((r) = (a) / (b)) #define LL_MOD(r, a, b) ((r) = (a) % (b)) /*********************************************************************** ** MACROS: LL_ ** ** LL_SHL Shift left [0..64] bits ** LL_SHR Shift right [0..64] bits with sign extension ** LL_USHR Unsigned shift right [0..64] bits ** LL_ISHL Signed shift left [0..64] bits ***********************************************************************/ #define LL_SHL(r, a, b) ((r) = (PRInt64)(a) << (b)) #define LL_SHR(r, a, b) ((r) = (PRInt64)(a) >> (b)) #define LL_USHR(r, a, b) ((r) = (PRUint64)(a) >> (b)) #define LL_ISHL(r, a, b) ((r) = (PRInt64)(a) << (b)) /*********************************************************************** ** MACROS: LL_ ** ** LL_L2I Convert to signed 32 bit ** LL_L2UI Convert to unsigned 32 bit ** LL_L2F Convert to floating point ** LL_L2D Convert to floating point ** LL_I2L Convert signed to 64 bit ** LL_UI2L Convert unsigned to 64 bit ** LL_F2L Convert float to 64 bit ** LL_D2L Convert float to 64 bit ***********************************************************************/ #define LL_L2I(i, l) ((i) = (PRInt32)(l)) #define LL_L2UI(ui, l) ((ui) = (PRUint32)(l)) #define LL_L2F(f, l) ((f) = (PRFloat64)(l)) #define LL_L2D(d, l) ((d) = (PRFloat64)(l)) #define LL_I2L(l, i) ((l) = (PRInt64)(i)) #define LL_UI2L(l, ui) ((l) = (PRInt64)(ui)) #define LL_F2L(l, f) ((l) = (PRInt64)(f)) #define LL_D2L(l, d) ((l) = (PRInt64)(d)) /*********************************************************************** ** MACROS: LL_UDIVMOD ** DESCRIPTION: ** Produce both a quotient and a remainder given an unsigned ** INPUTS: PRUint64 a: The dividend of the operation ** PRUint64 b: The quotient of the operation ** OUTPUTS: PRUint64 *qp: pointer to quotient ** PRUint64 *rp: pointer to remainder ***********************************************************************/ #define LL_UDIVMOD(qp, rp, a, b) \ (*(qp) = ((PRUint64)(a) / (b)), \ *(rp) = ((PRUint64)(a) % (b))) #else /* !HAVE_LONG_LONG */ #define LL_MAXINT LL_MaxInt() #define LL_MININT LL_MinInt() #define LL_ZERO LL_Zero() #define LL_MAXUINT LL_MaxUint() #ifdef IS_LITTLE_ENDIAN #define LL_INIT(hi, lo) {PR_UINT32(lo), PR_UINT32(hi)} #else #define LL_INIT(hi, lo) {PR_UINT32(hi), PR_UINT32(lo)} #endif #define LL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0)) #define LL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo)) #define LL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo)) #define LL_GE_ZERO(a) (((a).hi >> 31) == 0) #define LL_CMP(a, op, b) (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \ ((PRInt32)(a).hi op (PRInt32)(b).hi)) #define LL_UCMP(a, op, b) (((a).hi == (b).hi) ? ((a).lo op (b).lo) : \ ((a).hi op (b).hi)) #define LL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \ (r).hi = (a).hi & (b).hi) #define LL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \ (r).hi = (a).hi | (b).hi) #define LL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \ (r).hi = (a).hi ^ (b).hi) #define LL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \ (r).hi = (r).hi | (a).hi) #define LL_NOT(r, a) ((r).lo = ~(a).lo, \ (r).hi = ~(a).hi) #define LL_NEG(r, a) ((r).lo = -(PRInt32)(a).lo, \ (r).hi = -(PRInt32)(a).hi - ((r).lo != 0)) #define LL_ADD(r, a, b) { \ PRInt64 _a, _b; \ _a = a; _b = b; \ (r).lo = _a.lo + _b.lo; \ (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \ } #define LL_SUB(r, a, b) { \ PRInt64 _a, _b; \ _a = a; _b = b; \ (r).lo = _a.lo - _b.lo; \ (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \ } #define LL_MUL(r, a, b) { \ PRInt64 _a, _b; \ _a = a; _b = b; \ LL_MUL32(r, _a.lo, _b.lo); \ (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \ } #define _lo16(a) ((a) & PR_BITMASK(16)) #define _hi16(a) ((a) >> 16) #define LL_MUL32(r, a, b) { \ PRUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \ _a1 = _hi16(a), _a0 = _lo16(a); \ _b1 = _hi16(b), _b0 = _lo16(b); \ _y0 = _a0 * _b0; \ _y1 = _a0 * _b1; \ _y2 = _a1 * _b0; \ _y3 = _a1 * _b1; \ _y1 += _hi16(_y0); /* can't carry */ \ _y1 += _y2; /* might carry */ \ if (_y1 < _y2) \ _y3 += (PRUint32)(PR_BIT(16)); /* propagate */ \ (r).lo = (_lo16(_y1) << 16) + _lo16(_y0); \ (r).hi = _y3 + _hi16(_y1); \ } #define LL_UDIVMOD(qp, rp, a, b) ll_udivmod(qp, rp, a, b) NSPR_API(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b); #define LL_DIV(r, a, b) { \ PRInt64 _a, _b; \ PRUint32 _negative = (PRInt32)(a).hi < 0; \ if (_negative) { \ LL_NEG(_a, a); \ } else { \ _a = a; \ } \ if ((PRInt32)(b).hi < 0) { \ _negative ^= 1; \ LL_NEG(_b, b); \ } else { \ _b = b; \ } \ LL_UDIVMOD(&(r), 0, _a, _b); \ if (_negative) \ LL_NEG(r, r); \ } #define LL_MOD(r, a, b) { \ PRInt64 _a, _b; \ PRUint32 _negative = (PRInt32)(a).hi < 0; \ if (_negative) { \ LL_NEG(_a, a); \ } else { \ _a = a; \ } \ if ((PRInt32)(b).hi < 0) { \ LL_NEG(_b, b); \ } else { \ _b = b; \ } \ LL_UDIVMOD(0, &(r), _a, _b); \ if (_negative) \ LL_NEG(r, r); \ } #define LL_SHL(r, a, b) { \ if (b) { \ PRInt64 _a; \ _a = a; \ if ((b) < 32) { \ (r).lo = _a.lo << ((b) & 31); \ (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \ } else { \ (r).lo = 0; \ (r).hi = _a.lo << ((b) & 31); \ } \ } else { \ (r) = (a); \ } \ } /* a is an PRInt32, b is PRInt32, r is PRInt64 */ #define LL_ISHL(r, a, b) { \ if (b) { \ PRInt64 _a; \ _a.lo = (a); \ _a.hi = 0; \ if ((b) < 32) { \ (r).lo = (a) << ((b) & 31); \ (r).hi = ((a) >> (32 - (b))); \ } else { \ (r).lo = 0; \ (r).hi = (a) << ((b) & 31); \ } \ } else { \ (r).lo = (a); \ (r).hi = 0; \ } \ } #define LL_SHR(r, a, b) { \ if (b) { \ PRInt64 _a; \ _a = a; \ if ((b) < 32) { \ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ (r).hi = (PRInt32)_a.hi >> ((b) & 31); \ } else { \ (r).lo = (PRInt32)_a.hi >> ((b) & 31); \ (r).hi = (PRInt32)_a.hi >> 31; \ } \ } else { \ (r) = (a); \ } \ } #define LL_USHR(r, a, b) { \ if (b) { \ PRInt64 _a; \ _a = a; \ if ((b) < 32) { \ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \ (r).hi = _a.hi >> ((b) & 31); \ } else { \ (r).lo = _a.hi >> ((b) & 31); \ (r).hi = 0; \ } \ } else { \ (r) = (a); \ } \ } #define LL_L2I(i, l) ((i) = (l).lo) #define LL_L2UI(ui, l) ((ui) = (l).lo) #define LL_L2F(f, l) { double _d; LL_L2D(_d, l); (f) = (PRFloat64)_d; } #define LL_L2D(d, l) { \ int _negative; \ PRInt64 _absval; \ \ _negative = (l).hi >> 31; \ if (_negative) { \ LL_NEG(_absval, l); \ } else { \ _absval = l; \ } \ (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \ if (_negative) \ (d) = -(d); \ } #define LL_I2L(l, i) { PRInt32 _i = ((PRInt32)(i)) >> 31; (l).lo = (i); (l).hi = _i; } #define LL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0) #define LL_F2L(l, f) { double _d = (double)f; LL_D2L(l, _d); } #define LL_D2L(l, d) { \ int _negative; \ double _absval, _d_hi; \ PRInt64 _lo_d; \ \ _negative = ((d) < 0); \ _absval = _negative ? -(d) : (d); \ \ (l).hi = _absval / 4.294967296e9; \ (l).lo = 0; \ LL_L2D(_d_hi, l); \ _absval -= _d_hi; \ _lo_d.hi = 0; \ if (_absval < 0) { \ _lo_d.lo = -_absval; \ LL_SUB(l, l, _lo_d); \ } else { \ _lo_d.lo = _absval; \ LL_ADD(l, l, _lo_d); \ } \ \ if (_negative) \ LL_NEG(l, l); \ } #endif /* !HAVE_LONG_LONG */ PR_END_EXTERN_C #endif /* prlong_h___ */ nspr-4.11/nspr/pr/include/prmem.h0000644000000000000000000001116712623070344015075 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prmem.h ** Description: API to NSPR memory management functions ** */ #ifndef prmem_h___ #define prmem_h___ #include "prtypes.h" #include PR_BEGIN_EXTERN_C /* ** Thread safe memory allocation. ** ** NOTE: pr wraps up malloc, free, calloc, realloc so they are already ** thread safe (and are not declared here - look in stdlib.h). */ /* ** PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free have the same signatures ** as their libc equivalent malloc, calloc, realloc, and free, and have ** the same semantics. (Note that the argument type size_t is replaced ** by PRUint32.) Memory allocated by PR_Malloc, PR_Calloc, or PR_Realloc ** must be freed by PR_Free. */ NSPR_API(void *) PR_Malloc(PRUint32 size); NSPR_API(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize); NSPR_API(void *) PR_Realloc(void *ptr, PRUint32 size); NSPR_API(void) PR_Free(void *ptr); /* ** The following are some convenience macros defined in terms of ** PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free. */ /*********************************************************************** ** FUNCTION: PR_MALLOC() ** DESCRIPTION: ** PR_NEW() allocates an untyped item of size _size from the heap. ** INPUTS: _size: size in bytes of item to be allocated ** OUTPUTS: untyped pointer to the node allocated ** RETURN: pointer to node or error returned from malloc(). ***********************************************************************/ #define PR_MALLOC(_bytes) (PR_Malloc((_bytes))) /*********************************************************************** ** FUNCTION: PR_NEW() ** DESCRIPTION: ** PR_NEW() allocates an item of type _struct from the heap. ** INPUTS: _struct: a data type ** OUTPUTS: pointer to _struct ** RETURN: pointer to _struct or error returns from malloc(). ***********************************************************************/ #define PR_NEW(_struct) ((_struct *) PR_MALLOC(sizeof(_struct))) /*********************************************************************** ** FUNCTION: PR_REALLOC() ** DESCRIPTION: ** PR_REALLOC() re-allocates _ptr bytes from the heap as a _size ** untyped item. ** INPUTS: _ptr: pointer to node to reallocate ** _size: size of node to allocate ** OUTPUTS: pointer to node allocated ** RETURN: pointer to node allocated ***********************************************************************/ #define PR_REALLOC(_ptr, _size) (PR_Realloc((_ptr), (_size))) /*********************************************************************** ** FUNCTION: PR_CALLOC() ** DESCRIPTION: ** PR_CALLOC() allocates a _size bytes untyped item from the heap ** and sets the allocated memory to all 0x00. ** INPUTS: _size: size of node to allocate ** OUTPUTS: pointer to node allocated ** RETURN: pointer to node allocated ***********************************************************************/ #define PR_CALLOC(_size) (PR_Calloc(1, (_size))) /*********************************************************************** ** FUNCTION: PR_NEWZAP() ** DESCRIPTION: ** PR_NEWZAP() allocates an item of type _struct from the heap ** and sets the allocated memory to all 0x00. ** INPUTS: _struct: a data type ** OUTPUTS: pointer to _struct ** RETURN: pointer to _struct ***********************************************************************/ #define PR_NEWZAP(_struct) ((_struct*)PR_Calloc(1, sizeof(_struct))) /*********************************************************************** ** FUNCTION: PR_DELETE() ** DESCRIPTION: ** PR_DELETE() unallocates an object previosly allocated via PR_NEW() ** or PR_NEWZAP() to the heap. ** INPUTS: pointer to previously allocated object ** OUTPUTS: the referenced object is returned to the heap ** RETURN: void ***********************************************************************/ #define PR_DELETE(_ptr) { PR_Free(_ptr); (_ptr) = NULL; } /*********************************************************************** ** FUNCTION: PR_FREEIF() ** DESCRIPTION: ** PR_FREEIF() conditionally unallocates an object previously allocated ** vial PR_NEW() or PR_NEWZAP(). If the pointer to the object is ** equal to zero (0), the object is not released. ** INPUTS: pointer to previously allocated object ** OUTPUTS: the referenced object is conditionally returned to the heap ** RETURN: void ***********************************************************************/ #define PR_FREEIF(_ptr) if (_ptr) PR_DELETE(_ptr) PR_END_EXTERN_C #endif /* prmem_h___ */ nspr-4.11/nspr/pr/include/prmon.h0000644000000000000000000000625012623070344015105 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prmon_h___ #define prmon_h___ #include "prtypes.h" #include "prinrval.h" PR_BEGIN_EXTERN_C typedef struct PRMonitor PRMonitor; /* ** Create a new monitor. Monitors are re-entrant locks with a single built-in ** condition variable. ** ** This may fail if memory is tight or if some operating system resource ** is low. */ NSPR_API(PRMonitor*) PR_NewMonitor(void); /* ** Destroy a monitor. The caller is responsible for guaranteeing that the ** monitor is no longer in use. There must be no thread waiting on the monitor's ** condition variable and that the lock is not held. ** */ NSPR_API(void) PR_DestroyMonitor(PRMonitor *mon); /* ** Enter the lock associated with the monitor. If the calling thread currently ** is in the monitor, the call to enter will silently succeed. In either case, ** it will increment the entry count by one. */ NSPR_API(void) PR_EnterMonitor(PRMonitor *mon); /* ** Decrement the entry count associated with the monitor. If the decremented ** entry count is zero, the monitor is exited. Returns PR_FAILURE if the ** calling thread has not entered the monitor. */ NSPR_API(PRStatus) PR_ExitMonitor(PRMonitor *mon); /* ** Wait for a notify on the monitor's condition variable. Sleep for "ticks" ** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is ** indefinite). ** ** While the thread is waiting it exits the monitor (as if it called ** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When ** the wait has finished the thread regains control of the monitors lock ** with the same entry count as before the wait began. ** ** The thread waiting on the monitor will be resumed when the monitor is ** notified (assuming the thread is the next in line to receive the ** notify) or when the "ticks" timeout elapses. ** ** Returns PR_FAILURE if the caller has not entered the monitor. */ NSPR_API(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks); /* ** Notify a thread waiting on the monitor's condition variable. If a thread ** is waiting on the condition variable (using PR_Wait) then it is awakened ** and attempts to reenter the monitor. */ NSPR_API(PRStatus) PR_Notify(PRMonitor *mon); /* ** Notify all of the threads waiting on the monitor's condition variable. ** All of threads waiting on the condition are scheduled to reenter the ** monitor. */ NSPR_API(PRStatus) PR_NotifyAll(PRMonitor *mon); /* ** PR_ASSERT_CURRENT_THREAD_IN_MONITOR ** If the current thread is in |mon|, this assertion is guaranteed to ** succeed. Otherwise, the behavior of this function is undefined. */ #if defined(DEBUG) || defined(FORCE_PR_ASSERT) #define PR_ASSERT_CURRENT_THREAD_IN_MONITOR(/* PRMonitor* */ mon) \ PR_AssertCurrentThreadInMonitor(mon) #else #define PR_ASSERT_CURRENT_THREAD_IN_MONITOR(/* PRMonitor* */ mon) #endif /* Don't call this function directly. */ NSPR_API(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon); PR_END_EXTERN_C #endif /* prmon_h___ */ nspr-4.11/nspr/pr/include/prmwait.h0000644000000000000000000003761412623070344015445 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if defined(_PRMWAIT_H) #else #define _PRMWAIT_H #include "prio.h" #include "prtypes.h" #include "prclist.h" PR_BEGIN_EXTERN_C /********************************************************************************/ /********************************************************************************/ /********************************************************************************/ /****************************** WARNING ****************************/ /********************************************************************************/ /**************************** This is work in progress. *************************/ /************************** Do not make any assumptions *************************/ /************************** about the stability of this *************************/ /************************** API or the underlying imple- ************************/ /************************** mentation. ************************/ /********************************************************************************/ /********************************************************************************/ /* ** STRUCTURE: PRWaitGroup ** DESCRIPTION: ** The client may define several wait groups in order to semantically ** tie a collection of file descriptors for a single purpose. This allows ** easier dispatching of threads that returned with active file descriptors ** from the wait function. */ typedef struct PRWaitGroup PRWaitGroup; /* ** ENUMERATION: PRMWStatus ** DESCRIPTION: ** This enumeration is used to indicate the completion status of ** a receive wait object. Generally stated, a positive value indicates ** that the operation is not yet complete. A zero value indicates ** success (similar to PR_SUCCESS) and any negative value is an ** indication of failure. The reason for the failure can be retrieved ** by calling PR_GetError(). ** ** PR_MW_PENDING The operation is still pending. None of the other ** fields of the object are currently valid. ** PR_MW_SUCCESS The operation is complete and it was successful. ** PR_MW_FAILURE The operation failed. The reason for the failure ** can be retrieved by calling PR_GetError(). ** PR_MW_TIMEOUT The amount of time allowed for by the object's ** 'timeout' field has expired w/o the operation ** otherwise coming to closure. ** PR_MW_INTERRUPT The operation was cancelled, either by the client ** calling PR_CancelWaitFileDesc() or destroying the ** entire wait group (PR_DestroyWaitGroup()). */ typedef enum PRMWStatus { PR_MW_PENDING = 1, PR_MW_SUCCESS = 0, PR_MW_FAILURE = -1, PR_MW_TIMEOUT = -2, PR_MW_INTERRUPT = -3 } PRMWStatus; /* ** STRUCTURE: PRMemoryDescriptor ** DESCRIPTION: ** THis is a descriptor for an interval of memory. It contains a ** pointer to the first byte of that memory and the length (in ** bytes) of the interval. */ typedef struct PRMemoryDescriptor { void *start; /* pointer to first byte of memory */ PRSize length; /* length (in bytes) of memory interval */ } PRMemoryDescriptor; /* ** STRUCTURE: PRMWaitClientData ** DESCRIPTION: ** An opague stucture for which a client MAY give provide a concrete ** definition and associate with a receive descriptor. The NSPR runtime ** does not manage this field. It is completely up to the client. */ typedef struct PRMWaitClientData PRMWaitClientData; /* ** STRUCTURE: PRRecvWait ** DESCRIPTION: ** A receive wait object contains the file descriptor that is subject ** to the wait and the amount of time (beginning epoch established ** when the object is presented to the runtime) the the channel should ** block before abandoning the process. ** ** The success of the wait operation will be noted in the object's ** 'outcome' field. The fields are not valid when the NSPR runtime ** is in possession of the object. ** ** The memory descriptor describes an interval of writable memory ** in the caller's address space where data from an initial read ** can be placed. The description may indicate a null interval. */ typedef struct PRRecvWait { PRCList internal; /* internal runtime linkages */ PRFileDesc *fd; /* file descriptor associated w/ object */ PRMWStatus outcome; /* outcome of the current/last operation */ PRIntervalTime timeout; /* time allowed for entire operation */ PRInt32 bytesRecv; /* number of bytes transferred into buffer */ PRMemoryDescriptor buffer; /* where to store first segment of input data */ PRMWaitClientData *client; /* pointer to arbitrary client defined data */ } PRRecvWait; /* ** STRUCTURE: PRMWaitEnumerator ** DESCRIPTION: ** An enumeration object is used to store the state of an existing ** enumeration over a wait group. The opaque object must be allocated ** by the client and the reference presented on each call to the ** pseudo-stateless enumerator. The enumeration objects are sharable ** only in serial fashion. */ typedef struct PRMWaitEnumerator PRMWaitEnumerator; /* ** FUNCTION: PR_AddWaitFileDesc ** DESCRIPTION: ** This function will effectively add a file descriptor to the ** list of those waiting for network receive. The new descriptor ** will be semantically tied to the wait group specified. ** ** The ownership for the storage pointed to by 'desc' is temporarily ** passed over the the NSPR runtime. It will be handed back by the ** function PR_WaitRecvReady(). ** ** INPUTS ** group A reference to a PRWaitGroup or NULL. Wait groups are ** created by calling PR_CreateWaitGroup() and are used ** to semantically group various file descriptors by the ** client's application. ** desc A reference to a valid PRRecvWait. The object of the ** reference must be preserved and not be modified ** until its ownership is returned to the client. ** RETURN ** PRStatus An indication of success. If equal to PR_FAILUE details ** of the failure are avaiable via PR_GetError(). ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** Invalid 'group' identifier or duplicate 'desc' object. ** PR_OUT_OF_MEMORY_ERROR ** Insuffient memory for internal data structures. ** PR_INVALID_STATE_ERROR ** The group is being destroyed. */ NSPR_API(PRStatus) PR_AddWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc); /* ** FUNCTION: PR_WaitRecvReady ** DESCRIPTION: ** PR_WaitRecvReady will block the calling thread until one of the ** file descriptors that have been added via PR_AddWaitFileDesc is ** available for input I/O. ** INPUT ** group A pointer to a valid PRWaitGroup or NULL (the null ** group. The function will block the caller until a ** channel from the wait group becomes ready for receive ** or there is some sort of error. ** RETURN ** PRReciveWait ** When the caller is resumed it is either returned a ** valid pointer to a previously added receive wait or ** a NULL. If the latter, the function has terminated ** for a reason that can be determined by calling ** PR_GetError(). ** If a valid pointer is returned, the reference is to the ** file descriptor contained in the receive wait object. ** The outcome of the wait operation may still fail, and ** if it has, that fact will be noted in the object's ** outcome field. Details can be retrieved from PR_GetError(). ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The 'group' is not known by the runtime. ** PR_PENDING_INTERRUPT_ERROR The thread was interrupted. ** PR_INVALID_STATE_ERROR ** The group is being destroyed. */ NSPR_API(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group); /* ** FUNCTION: PR_CancelWaitFileDesc ** DESCRIPTION: ** PR_CancelWaitFileDesc is provided as a means for cancelling operations ** on objects previously submitted by use of PR_AddWaitFileDesc(). If ** the runtime knows of the object, it will be marked as having failed ** because it was interrupted (similar to PR_Interrupt()). The first ** available thread waiting on the group will be made to return the ** PRRecvWait object with the outcome noted. ** ** INPUTS ** group The wait group under which the wait receive object was ** added. ** desc A pointer to the wait receive object that is to be ** cancelled. ** RETURN ** PRStatus If the wait receive object was located and associated ** with the specified wait group, the status returned will ** be PR_SUCCESS. There is still a race condition that would ** permit the offected object to complete normally, but it ** is assured that it will complete in the near future. ** If the receive object or wait group are invalid, the ** function will return with a status of PR_FAILURE. ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The 'group' argument is not recognized as a valid group. ** PR_COLLECTION_EMPTY_ERROR ** There are no more receive wait objects in the group's ** collection. ** PR_INVALID_STATE_ERROR ** The group is being destroyed. */ NSPR_API(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc); /* ** FUNCTION: PR_CancelWaitGroup ** DESCRIPTION: ** PR_CancelWaitGroup is provided as a means for cancelling operations ** on objects previously submitted by use of PR_AddWaitFileDesc(). Each ** successive call will return a pointer to a PRRecvWait object that ** was previously registered via PR_AddWaitFileDesc(). If no wait ** objects are associated with the wait group, a NULL will be returned. ** This function should be called in a loop until a NULL is returned ** to reclaim all the wait objects prior to calling PR_DestroyWaitGroup(). ** ** INPUTS ** group The wait group under which the wait receive object was ** added. ** RETURN ** PRRecvWait* If the wait group is valid and at least one receive wait ** object is present in the group, that object will be ** marked as PR_MW_INTERRUPT'd and removed from the group's ** queues. Otherwise a NULL will be returned and the reason ** for the NULL may be retrieved by calling PR_GetError(). ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** PR_GROUP_EMPTY_ERROR */ NSPR_API(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group); /* ** FUNCTION: PR_CreateWaitGroup ** DESCRIPTION: ** A wait group is an opaque object that a client may create in order ** to semantically group various wait requests. Each wait group is ** unique, including the default wait group (NULL). A wait request ** that was added under a wait group will only be serviced by a caller ** that specified the same wait group. ** ** INPUT ** size The size of the hash table to be used to contain the ** receive wait objects. This is just the initial size. ** It will grow as it needs to, but to avoid that hassle ** one can suggest a suitable size initially. It should ** be ~30% larger than the maximum number of receive wait ** objects expected. ** RETURN ** PRWaitGroup If successful, the function will return a pointer to an ** object that was allocated by and owned by the runtime. ** The reference remains valid until it is explicitly destroyed ** by calling PR_DestroyWaitGroup(). ** ** ERRORS ** PR_OUT_OF_MEMORY_ERROR */ NSPR_API(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size); /* ** FUNCTION: PR_DestroyWaitGroup ** DESCRIPTION: ** Undo the effects of PR_CreateWaitGroup(). Any receive wait operations ** on the group will be treated as if the each had been the target of a ** PR_CancelWaitFileDesc(). ** ** INPUT ** group Reference to a wait group previously allocated using ** PR_CreateWaitGroup(). ** RETURN ** PRStatus Will be PR_SUCCESS if the wait group was valid and there ** are no receive wait objects in that group. Otherwise ** will indicate PR_FAILURE. ** ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The 'group' argument does not reference a known object. ** PR_INVALID_STATE_ERROR ** The group still contains receive wait objects. */ NSPR_API(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group); /* ** FUNCTION: PR_CreateMWaitEnumerator ** DESCRIPTION: ** The PR_CreateMWaitEnumerator() function returns a reference to an ** opaque PRMWaitEnumerator object. The enumerator object is required ** as an argument for each successive call in the stateless enumeration ** of the indicated wait group. ** ** group The wait group that the enumeration is intended to ** process. It may be be the default wait group (NULL). ** RETURN ** PRMWaitEnumerator* group ** A reference to an object that will be used to store ** intermediate state of enumerations. ** ERRORS ** Errors are indicated by the function returning a NULL. ** PR_INVALID_ARGUMENT_ERROR ** The 'group' argument does not reference a known object. ** PR_OUT_OF_MEMORY_ERROR */ NSPR_API(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group); /* ** FUNCTION: PR_DestroyMWaitEnumerator ** DESCRIPTION: ** Destroys the object created by PR_CreateMWaitEnumerator(). The reference ** used as an argument becomes invalid. ** ** INPUT ** PRMWaitEnumerator* enumerator ** The PRMWaitEnumerator object to destroy. ** RETURN ** PRStatus ** PR_SUCCESS if successful, PR_FAILURE otherwise. ** ERRORS ** PR_INVALID_ARGUMENT_ERROR ** The enumerator is invalid. */ NSPR_API(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator); /* ** FUNCTION: PR_EnumerateWaitGroup ** DESCRIPTION: ** PR_EnumerateWaitGroup is a thread safe enumerator over a wait group. ** Each call to the enumerator must present a valid PRMWaitEnumerator ** rererence and a pointer to the "previous" element returned from the ** enumeration process or a NULL. ** ** An enumeration is started by passing a NULL as the "previous" value. ** Subsequent calls to the enumerator must pass in the result of the ** previous call. The enumeration end is signaled by the runtime returning ** a NULL as the result. ** ** Modifications to the content of the wait group are allowed during ** an enumeration. The effect is that the enumeration may have to be ** "reset" and that may result in duplicates being returned from the ** enumeration. ** ** An enumeration may be abandoned at any time. The runtime is not ** keeping any state, so there are no issues in that regard. */ NSPR_API(PRRecvWait*) PR_EnumerateWaitGroup( PRMWaitEnumerator *enumerator, const PRRecvWait *previous); PR_END_EXTERN_C #endif /* defined(_PRMWAIT_H) */ /* prmwait.h */ nspr-4.11/nspr/pr/include/prnetdb.h0000644000000000000000000004561412623070344015417 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prnetdb_h___ #define prnetdb_h___ #include "prtypes.h" #include "prio.h" PR_BEGIN_EXTERN_C /* ********************************************************************* * Translate an Internet address to/from a character string ********************************************************************* */ NSPR_API(PRStatus) PR_StringToNetAddr( const char *string, PRNetAddr *addr); NSPR_API(PRStatus) PR_NetAddrToString( const PRNetAddr *addr, char *string, PRUint32 size); /* ** Structures returned by network data base library. All addresses are ** supplied in host order, and returned in network order (suitable for ** use in system calls). */ /* ** Beware that WINSOCK.H defines h_addrtype and h_length as short. ** Client code does direct struct copies of hostent to PRHostEnt and ** hence the ifdef. */ typedef struct PRHostEnt { char *h_name; /* official name of host */ char **h_aliases; /* alias list */ #ifdef WIN32 PRInt16 h_addrtype; /* host address type */ PRInt16 h_length; /* length of address */ #else PRInt32 h_addrtype; /* host address type */ PRInt32 h_length; /* length of address */ #endif char **h_addr_list; /* list of addresses from name server */ } PRHostEnt; /* A safe size to use that will mostly work... */ #if (defined(AIX) && defined(_THREAD_SAFE)) || defined(OSF1) #define PR_NETDB_BUF_SIZE sizeof(struct protoent_data) #else #define PR_NETDB_BUF_SIZE 1024 #endif /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetHostByName() ** Lookup a host by name. ** ** INPUTS: ** char *hostname Character string defining the host name of interest ** char *buf A scratch buffer for the runtime to return result. ** This buffer is allocated by the caller. ** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to ** use is PR_NETDB_BUF_SIZE. ** OUTPUTS: ** PRHostEnt *hostentry ** This structure is filled in by the runtime if ** the function returns PR_SUCCESS. This structure ** is allocated by the caller. ** RETURN: ** PRStatus PR_SUCCESS if the lookup succeeds. If it fails ** the result will be PR_FAILURE and the reason ** for the failure can be retrieved by PR_GetError(). ***********************************************************************/ NSPR_API(PRStatus) PR_GetHostByName( const char *hostname, char *buf, PRIntn bufsize, PRHostEnt *hostentry); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetIPNodeByName() ** Lookup a host by name. Equivalent to getipnodebyname(AI_DEFAULT) ** of RFC 2553. ** ** INPUTS: ** char *hostname Character string defining the host name of interest ** PRUint16 af Address family (either PR_AF_INET or PR_AF_INET6) ** PRIntn flags Specifies the types of addresses that are searched ** for and the types of addresses that are returned. ** The only supported flag is PR_AI_DEFAULT. ** char *buf A scratch buffer for the runtime to return result. ** This buffer is allocated by the caller. ** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to ** use is PR_NETDB_BUF_SIZE. ** OUTPUTS: ** PRHostEnt *hostentry ** This structure is filled in by the runtime if ** the function returns PR_SUCCESS. This structure ** is allocated by the caller. ** RETURN: ** PRStatus PR_SUCCESS if the lookup succeeds. If it fails ** the result will be PR_FAILURE and the reason ** for the failure can be retrieved by PR_GetError(). ***********************************************************************/ #define PR_AI_ALL 0x08 #define PR_AI_V4MAPPED 0x10 #define PR_AI_ADDRCONFIG 0x20 #define PR_AI_NOCANONNAME 0x8000 #define PR_AI_DEFAULT (PR_AI_V4MAPPED | PR_AI_ADDRCONFIG) NSPR_API(PRStatus) PR_GetIPNodeByName( const char *hostname, PRUint16 af, PRIntn flags, char *buf, PRIntn bufsize, PRHostEnt *hostentry); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetHostByAddr() ** Lookup a host entry by its network address. ** ** INPUTS: ** char *hostaddr IP address of host in question ** char *buf A scratch buffer for the runtime to return result. ** This buffer is allocated by the caller. ** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to ** use is PR_NETDB_BUF_SIZE. ** OUTPUTS: ** PRHostEnt *hostentry ** This structure is filled in by the runtime if ** the function returns PR_SUCCESS. This structure ** is allocated by the caller. ** RETURN: ** PRStatus PR_SUCCESS if the lookup succeeds. If it fails ** the result will be PR_FAILURE and the reason ** for the failure can be retrieved by PR_GetError(). ***********************************************************************/ NSPR_API(PRStatus) PR_GetHostByAddr( const PRNetAddr *hostaddr, char *buf, PRIntn bufsize, PRHostEnt *hostentry); /*********************************************************************** ** FUNCTION: PR_EnumerateHostEnt() ** DESCRIPTION: ** A stateless enumerator over a PRHostEnt structure acquired from ** PR_GetHostByName() PR_GetHostByAddr() to evaluate the possible ** network addresses. ** ** INPUTS: ** PRIntn enumIndex Index of the enumeration. The enumeration starts ** and ends with a value of zero. ** ** PRHostEnt *hostEnt A pointer to a host entry struct that was ** previously returned by PR_GetHostByName() or ** PR_GetHostByAddr(). ** ** PRUint16 port The port number to be assigned as part of the ** PRNetAddr. ** ** OUTPUTS: ** PRNetAddr *address A pointer to an address structure that will be ** filled in by the call to the enumeration if the ** result of the call is greater than zero. ** ** RETURN: ** PRIntn The value that should be used for the next call ** of the enumerator ('enumIndex'). The enumeration ** is ended if this value is returned zero. ** If a value of -1 is returned, the enumeration ** has failed. The reason for the failure can be ** retrieved by calling PR_GetError(). ***********************************************************************/ NSPR_API(PRIntn) PR_EnumerateHostEnt( PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address); /*********************************************************************** ** FUNCTION: PR_InitializeNetAddr(), ** DESCRIPTION: ** Initialize the fields of a PRNetAddr, assigning well known values as ** appropriate. ** ** INPUTS ** PRNetAddrValue val The value to be assigned to the IP Address portion ** of the network address. This can only specify the ** special well known values that are equivalent to ** INADDR_ANY and INADDR_LOOPBACK. ** ** PRUint16 port The port number to be assigned in the structure. ** ** OUTPUTS: ** PRNetAddr *addr The address to be manipulated. ** ** RETURN: ** PRStatus To indicate success or failure. If the latter, the ** reason for the failure can be retrieved by calling ** PR_GetError(); ***********************************************************************/ typedef enum PRNetAddrValue { PR_IpAddrNull, /* do NOT overwrite the IP address */ PR_IpAddrAny, /* assign logical INADDR_ANY to IP address */ PR_IpAddrLoopback, /* assign logical INADDR_LOOPBACK */ PR_IpAddrV4Mapped /* IPv4 mapped address */ } PRNetAddrValue; NSPR_API(PRStatus) PR_InitializeNetAddr( PRNetAddrValue val, PRUint16 port, PRNetAddr *addr); /*********************************************************************** ** FUNCTION: PR_SetNetAddr(), ** DESCRIPTION: ** Set the fields of a PRNetAddr, assigning well known values as ** appropriate. This function is similar to PR_InitializeNetAddr ** but differs in that the address family is specified. ** ** INPUTS ** PRNetAddrValue val The value to be assigned to the IP Address portion ** of the network address. This can only specify the ** special well known values that are equivalent to ** INADDR_ANY and INADDR_LOOPBACK. ** ** PRUint16 af The address family (either PR_AF_INET or PR_AF_INET6) ** ** PRUint16 port The port number to be assigned in the structure. ** ** OUTPUTS: ** PRNetAddr *addr The address to be manipulated. ** ** RETURN: ** PRStatus To indicate success or failure. If the latter, the ** reason for the failure can be retrieved by calling ** PR_GetError(); ***********************************************************************/ NSPR_API(PRStatus) PR_SetNetAddr( PRNetAddrValue val, PRUint16 af, PRUint16 port, PRNetAddr *addr); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_IsNetAddrType() ** Determine if the network address is of the specified type. ** ** INPUTS: ** const PRNetAddr *addr A network address. ** PRNetAddrValue The type of network address ** ** RETURN: ** PRBool PR_TRUE if the network address is of the ** specified type, else PR_FALSE. ***********************************************************************/ NSPR_API(PRBool) PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_ConvertIPv4AddrToIPv6() ** Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr ** ** INPUTS: ** PRUint32 v4addr IPv4 address ** ** OUTPUTS: ** PRIPv6Addr *v6addr The converted IPv6 address ** ** RETURN: ** void ** ***********************************************************************/ NSPR_API(void) PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr *v6addr); /*********************************************************************** ** MACRO: ** DESCRIPTION: PR_NetAddrFamily() ** Get the 'family' field of a PRNetAddr union. ** ** INPUTS: ** const PRNetAddr *addr A network address. ** ** RETURN: ** PRUint16 The 'family' field of 'addr'. ***********************************************************************/ #define PR_NetAddrFamily(addr) ((addr)->raw.family) /*********************************************************************** ** MACRO: ** DESCRIPTION: PR_NetAddrInetPort() ** Get the 'port' field of a PRNetAddr union. ** ** INPUTS: ** const PRNetAddr *addr A network address. ** ** RETURN: ** PRUint16 The 'port' field of 'addr'. ***********************************************************************/ #define PR_NetAddrInetPort(addr) \ ((addr)->raw.family == PR_AF_INET6 ? (addr)->ipv6.port : (addr)->inet.port) /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetProtoByName() ** Lookup a protocol entry based on protocol's name ** ** INPUTS: ** char *protocolname Character string of the protocol's name. ** char *buf A scratch buffer for the runtime to return result. ** This buffer is allocated by the caller. ** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to ** use is PR_NETDB_BUF_SIZE. ** OUTPUTS: ** PRHostEnt *PRProtoEnt ** This structure is filled in by the runtime if ** the function returns PR_SUCCESS. This structure ** is allocated by the caller. ** RETURN: ** PRStatus PR_SUCCESS if the lookup succeeds. If it fails ** the result will be PR_FAILURE and the reason ** for the failure can be retrieved by PR_GetError(). ***********************************************************************/ typedef struct PRProtoEnt { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ #ifdef WIN32 PRInt16 p_num; /* protocol # */ #else PRInt32 p_num; /* protocol # */ #endif } PRProtoEnt; NSPR_API(PRStatus) PR_GetProtoByName( const char* protocolname, char* buffer, PRInt32 bufsize, PRProtoEnt* result); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetProtoByNumber() ** Lookup a protocol entry based on protocol's number ** ** INPUTS: ** PRInt32 protocolnumber ** Number assigned to the protocol. ** char *buf A scratch buffer for the runtime to return result. ** This buffer is allocated by the caller. ** PRIntn bufsize Number of bytes in 'buf'. A recommnded value to ** use is PR_NETDB_BUF_SIZE. ** OUTPUTS: ** PRHostEnt *PRProtoEnt ** This structure is filled in by the runtime if ** the function returns PR_SUCCESS. This structure ** is allocated by the caller. ** RETURN: ** PRStatus PR_SUCCESS if the lookup succeeds. If it fails ** the result will be PR_FAILURE and the reason ** for the failure can be retrieved by PR_GetError(). ***********************************************************************/ NSPR_API(PRStatus) PR_GetProtoByNumber( PRInt32 protocolnumber, char* buffer, PRInt32 bufsize, PRProtoEnt* result); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetAddrInfoByName() ** Look up a host by name. Equivalent to getaddrinfo(host, NULL, ...) of ** RFC 3493. ** ** INPUTS: ** char *hostname Character string defining the host name of interest ** PRUint16 af May be PR_AF_UNSPEC or PR_AF_INET. ** PRIntn flags May be either PR_AI_ADDRCONFIG or ** PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME. Include ** PR_AI_NOCANONNAME to suppress the determination of ** the canonical name corresponding to hostname. ** RETURN: ** PRAddrInfo* Handle to a data structure containing the results ** of the host lookup. Use PR_EnumerateAddrInfo to ** inspect the PRNetAddr values stored in this object. ** When no longer needed, this handle must be destroyed ** with a call to PR_FreeAddrInfo. If a lookup error ** occurs, then NULL will be returned. ***********************************************************************/ typedef struct PRAddrInfo PRAddrInfo; NSPR_API(PRAddrInfo*) PR_GetAddrInfoByName( const char *hostname, PRUint16 af, PRIntn flags); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_FreeAddrInfo() ** Destroy the PRAddrInfo handle allocated by PR_GetAddrInfoByName(). ** ** INPUTS: ** PRAddrInfo *addrInfo ** The handle resulting from a successful call to ** PR_GetAddrInfoByName(). ** RETURN: ** void ***********************************************************************/ NSPR_API(void) PR_FreeAddrInfo(PRAddrInfo *addrInfo); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_EnumerateAddrInfo() ** A stateless enumerator over a PRAddrInfo handle acquired from ** PR_GetAddrInfoByName() to inspect the possible network addresses. ** ** INPUTS: ** void *enumPtr Index pointer of the enumeration. The enumeration ** starts and ends with a value of NULL. ** const PRAddrInfo *addrInfo ** The PRAddrInfo handle returned by a successful ** call to PR_GetAddrInfoByName(). ** PRUint16 port The port number to be assigned as part of the ** PRNetAddr. ** OUTPUTS: ** PRNetAddr *result A pointer to an address structure that will be ** filled in by the call to the enumeration if the ** result of the call is not NULL. ** RETURN: ** void* The value that should be used for the next call ** of the enumerator ('enumPtr'). The enumeration ** is ended if this value is NULL. ***********************************************************************/ NSPR_API(void *) PR_EnumerateAddrInfo( void *enumPtr, const PRAddrInfo *addrInfo, PRUint16 port, PRNetAddr *result); /*********************************************************************** ** FUNCTION: ** DESCRIPTION: PR_GetCanonNameFromAddrInfo() ** Extracts the canonical name of the hostname passed to ** PR_GetAddrInfoByName(). ** ** INPUTS: ** const PRAddrInfo *addrInfo ** The PRAddrInfo handle returned by a successful ** call to PR_GetAddrInfoByName(). ** RETURN: ** const char * A const pointer to the canonical hostname stored ** in the given PRAddrInfo handle. This pointer is ** invalidated once the PRAddrInfo handle is destroyed ** by a call to PR_FreeAddrInfo(). ***********************************************************************/ NSPR_API(const char *) PR_GetCanonNameFromAddrInfo( const PRAddrInfo *addrInfo); /*********************************************************************** ** FUNCTIONS: PR_ntohs, PR_ntohl, PR_ntohll, PR_htons, PR_htonl, PR_htonll ** ** DESCRIPTION: API entries for the common byte ordering routines. ** ** PR_ntohs 16 bit conversion from network to host ** PR_ntohl 32 bit conversion from network to host ** PR_ntohll 64 bit conversion from network to host ** PR_htons 16 bit conversion from host to network ** PR_htonl 32 bit conversion from host to network ** PR_ntonll 64 bit conversion from host to network ** ***********************************************************************/ NSPR_API(PRUint16) PR_ntohs(PRUint16); NSPR_API(PRUint32) PR_ntohl(PRUint32); NSPR_API(PRUint64) PR_ntohll(PRUint64); NSPR_API(PRUint16) PR_htons(PRUint16); NSPR_API(PRUint32) PR_htonl(PRUint32); NSPR_API(PRUint64) PR_htonll(PRUint64); PR_END_EXTERN_C #endif /* prnetdb_h___ */ nspr-4.11/nspr/pr/include/prolock.h0000644000000000000000000001116112623070344015420 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prolock_h___ #define prolock_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** A locking mechanism, built on the existing PRLock definiion, ** is provided that will permit applications to define a Lock ** Hierarchy (or Lock Ordering) schema. An application designed ** using the Ordered Lock functions will terminate with a ** diagnostic message when a lock inversion condition is ** detected. ** ** The lock ordering detection is complile-time enabled only. in ** optimized builds of NSPR, the Ordered Lock functions map ** directly to PRLock functions, providing no lock order ** detection. ** ** The Ordered Lock Facility is compiled in when DEBUG is defined at ** compile time. Ordered Lock can be forced on in optimized builds by ** defining FORCE_NSPR_ORDERED_LOCK at compile time. Both the ** application using Ordered Lock and NSPR must be compiled with the ** facility enabled to achieve the desired results. ** ** Application designers should use the macro interfaces to the Ordered ** Lock facility to ensure that it is compiled out in optimized builds. ** ** Application designers are responsible for defining their own ** lock hierarchy. ** ** Ordered Lock is thread-safe and SMP safe. ** ** See Also: prlock.h ** ** /lth. 10-Jun-1998. ** */ /* ** Opaque type for ordered lock. ** ... Don't even think of looking in here. ** */ #if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) typedef void * PROrderedLock; #else /* ** Map PROrderedLock and methods onto PRLock when ordered locking ** is not compiled in. ** */ #include "prlock.h" typedef PRLock PROrderedLock; #endif /* ----------------------------------------------------------------------- ** FUNCTION: PR_CreateOrderedLock() -- Create an Ordered Lock ** ** DESCRIPTION: PR_CreateOrderedLock() creates an ordered lock. ** ** INPUTS: ** order: user defined order of this lock. ** name: name of the lock. For debugging purposes. ** ** OUTPUTS: returned ** ** RETURNS: PR_OrderedLock pointer ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_CREATE_ORDERED_LOCK(order,name)\ PR_CreateOrderedLock((order),(name)) #else #define PR_CREATE_ORDERED_LOCK(order) PR_NewLock() #endif NSPR_API(PROrderedLock *) PR_CreateOrderedLock( PRInt32 order, const char *name ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_DestroyOrderedLock() -- Destroy an Ordered Lock ** ** DESCRIPTION: PR_DestroyOrderedLock() destroys the ordered lock ** referenced by lock. ** ** INPUTS: lock: pointer to a PROrderedLock ** ** OUTPUTS: the lock is destroyed ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyOrderedLock((lock)) #else #define PR_DESTROY_ORDERED_LOCK(lock) PR_DestroyLock((lock)) #endif NSPR_API(void) PR_DestroyOrderedLock( PROrderedLock *lock ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_LockOrderedLock() -- Lock an ordered lock ** ** DESCRIPTION: PR_LockOrderedLock() locks the ordered lock ** referenced by lock. If the order of lock is less than or equal ** to the order of the highest lock held by the locking thread, ** the function asserts. ** ** INPUTS: lock: a pointer to a PROrderedLock ** ** OUTPUTS: The lock is held or the function asserts. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_LOCK_ORDERED_LOCK(lock) PR_LockOrderedLock((lock)) #else #define PR_LOCK_ORDERED_LOCK(lock) PR_Lock((lock)) #endif NSPR_API(void) PR_LockOrderedLock( PROrderedLock *lock ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_UnlockOrderedLock() -- unlock and Ordered Lock ** ** DESCRIPTION: PR_UnlockOrderedLock() unlocks the lock referenced ** by lock. ** ** INPUTS: lock: a pointer to a PROrderedLock ** ** OUTPUTS: the lock is unlocked ** ** RETURNS: ** PR_SUCCESS ** PR_FAILURE ** ** RESTRICTIONS: ** */ #if defined(DEBUG) || defined(FORCE_NSPR_ORDERED_LOCKS) #define PR_UNLOCK_ORDERED_LOCK(lock) PR_UnlockOrderedLock((lock)) #else #define PR_UNLOCK_ORDERED_LOCK(lock) PR_Unlock((lock)) #endif NSPR_API(PRStatus) PR_UnlockOrderedLock( PROrderedLock *lock ); PR_END_EXTERN_C #endif /* prolock_h___ */ nspr-4.11/nspr/pr/include/prpdce.h0000644000000000000000000000462012623070344015226 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: prpdce.h * Description: This file is the API defined to allow for DCE (aka POSIX) * thread emulation in an NSPR environment. It is not the * intent that this be a fully supported API. */ #if !defined(PRPDCE_H) #define PRPDCE_H #include "prlock.h" #include "prcvar.h" #include "prtypes.h" #include "prinrval.h" PR_BEGIN_EXTERN_C #define _PR_NAKED_CV_LOCK (PRLock*)0xdce1dce1 /* ** Test and acquire a lock. ** ** If the lock is acquired by the calling thread, the ** return value will be PR_SUCCESS. If the lock is ** already held, by another thread or this thread, the ** result will be PR_FAILURE. */ NSPR_API(PRStatus) PRP_TryLock(PRLock *lock); /* ** Create a naked condition variable ** ** A "naked" condition variable is one that is not created bound ** to a lock. The CV created with this function is the only type ** that may be used in the subsequent "naked" condition variable ** operations (see PRP_NakedWait, PRP_NakedNotify, PRP_NakedBroadcast); */ NSPR_API(PRCondVar*) PRP_NewNakedCondVar(void); /* ** Destroy a naked condition variable ** ** Destroy the condition variable created by PR_NewNakedCondVar. */ NSPR_API(void) PRP_DestroyNakedCondVar(PRCondVar *cvar); /* ** Wait on a condition ** ** Wait on the condition variable 'cvar'. It is asserted that ** the lock protecting the condition 'lock' is held by the ** calling thread. If more time expires than that declared in ** 'timeout' the condition will be notified. Waits can be ** interrupted by another thread. ** ** NB: The CV ('cvar') must be one created using PR_NewNakedCondVar. */ NSPR_API(PRStatus) PRP_NakedWait( PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout); /* ** Notify a thread waiting on a condition ** ** Notify the condition specified 'cvar'. ** ** NB: The CV ('cvar') must be one created using PR_NewNakedCondVar. */ NSPR_API(PRStatus) PRP_NakedNotify(PRCondVar *cvar); /* ** Notify all threads waiting on a condition ** ** Notify the condition specified 'cvar'. ** ** NB: The CV ('cvar') must be one created using PR_NewNakedCondVar. */ NSPR_API(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar); PR_END_EXTERN_C #endif /* PRPDCE_H */ nspr-4.11/nspr/pr/include/prprf.h0000644000000000000000000001061112623070344015077 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prprf_h___ #define prprf_h___ /* ** API for PR printf like routines. Supports the following formats ** %d - decimal ** %u - unsigned decimal ** %x - unsigned hex ** %X - unsigned uppercase hex ** %o - unsigned octal ** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above ** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above ** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above ** %s - string ** %c - character ** %p - pointer (deals with machine dependent pointer size) ** %f - float ** %g - float */ #include "prtypes.h" #include "prio.h" #include #include PR_BEGIN_EXTERN_C /* ** sprintf into a fixed size buffer. Guarantees that a NUL is at the end ** of the buffer. Returns the length of the written output, NOT including ** the NUL, or (PRUint32)-1 if an error occurs. */ NSPR_API(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...); /* ** sprintf into a PR_MALLOC'd buffer. Return a pointer to the malloc'd ** buffer on success, NULL on failure. Call "PR_smprintf_free" to release ** the memory returned. */ NSPR_API(char*) PR_smprintf(const char *fmt, ...); /* ** Free the memory allocated, for the caller, by PR_smprintf */ NSPR_API(void) PR_smprintf_free(char *mem); /* ** "append" sprintf into a PR_MALLOC'd buffer. "last" is the last value of ** the PR_MALLOC'd buffer. sprintf will append data to the end of last, ** growing it as necessary using realloc. If last is NULL, PR_sprintf_append ** will allocate the initial string. The return value is the new value of ** last for subsequent calls, or NULL if there is a malloc failure. */ NSPR_API(char*) PR_sprintf_append(char *last, const char *fmt, ...); /* ** sprintf into a function. The function "f" is called with a string to ** place into the output. "arg" is an opaque pointer used by the stuff ** function to hold any state needed to do the storage of the output ** data. The return value is a count of the number of characters fed to ** the stuff function, or (PRUint32)-1 if an error occurs. */ typedef PRIntn (*PRStuffFunc)(void *arg, const char *s, PRUint32 slen); NSPR_API(PRUint32) PR_sxprintf(PRStuffFunc f, void *arg, const char *fmt, ...); /* ** fprintf to a PRFileDesc */ NSPR_API(PRUint32) PR_fprintf(struct PRFileDesc* fd, const char *fmt, ...); /* ** va_list forms of the above. */ NSPR_API(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen, const char *fmt, va_list ap); NSPR_API(char*) PR_vsmprintf(const char *fmt, va_list ap); NSPR_API(char*) PR_vsprintf_append(char *last, const char *fmt, va_list ap); NSPR_API(PRUint32) PR_vsxprintf(PRStuffFunc f, void *arg, const char *fmt, va_list ap); NSPR_API(PRUint32) PR_vfprintf(struct PRFileDesc* fd, const char *fmt, va_list ap); /* *************************************************************************** ** FUNCTION: PR_sscanf ** DESCRIPTION: ** PR_sscanf() scans the input character string, performs data ** conversions, and stores the converted values in the data objects ** pointed to by its arguments according to the format control ** string. ** ** PR_sscanf() behaves the same way as the sscanf() function in the ** Standard C Library (stdio.h), with the following exceptions: ** - PR_sscanf() handles the NSPR integer and floating point types, ** such as PRInt16, PRInt32, PRInt64, and PRFloat64, whereas ** sscanf() handles the standard C types like short, int, long, ** and double. ** - PR_sscanf() has no multibyte character support, while sscanf() ** does. ** INPUTS: ** const char *buf ** a character string holding the input to scan ** const char *fmt ** the format control string for the conversions ** ... ** variable number of arguments, each of them is a pointer to ** a data object in which the converted value will be stored ** OUTPUTS: none ** RETURNS: PRInt32 ** The number of values converted and stored. ** RESTRICTIONS: ** Multibyte characters in 'buf' or 'fmt' are not allowed. *************************************************************************** */ NSPR_API(PRInt32) PR_sscanf(const char *buf, const char *fmt, ...); PR_END_EXTERN_C #endif /* prprf_h___ */ nspr-4.11/nspr/pr/include/prproces.h0000644000000000000000000000440312623070344015605 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prproces_h___ #define prproces_h___ #include "prtypes.h" #include "prio.h" PR_BEGIN_EXTERN_C /************************************************************************/ /*****************************PROCESS OPERATIONS*************************/ /************************************************************************/ typedef struct PRProcess PRProcess; typedef struct PRProcessAttr PRProcessAttr; NSPR_API(PRProcessAttr *) PR_NewProcessAttr(void); NSPR_API(void) PR_ResetProcessAttr(PRProcessAttr *attr); NSPR_API(void) PR_DestroyProcessAttr(PRProcessAttr *attr); NSPR_API(void) PR_ProcessAttrSetStdioRedirect( PRProcessAttr *attr, PRSpecialFD stdioFd, PRFileDesc *redirectFd ); /* * OBSOLETE -- use PR_ProcessAttrSetStdioRedirect instead. */ NSPR_API(void) PR_SetStdioRedirect( PRProcessAttr *attr, PRSpecialFD stdioFd, PRFileDesc *redirectFd ); NSPR_API(PRStatus) PR_ProcessAttrSetCurrentDirectory( PRProcessAttr *attr, const char *dir ); NSPR_API(PRStatus) PR_ProcessAttrSetInheritableFD( PRProcessAttr *attr, PRFileDesc *fd, const char *name ); /* ** Create a new process ** ** Create a new process executing the file specified as 'path' and with ** the supplied arguments and environment. ** ** This function may fail because of illegal access (permissions), ** invalid arguments or insufficient resources. ** ** A process may be created such that the creator can later synchronize its ** termination using PR_WaitProcess(). */ NSPR_API(PRProcess*) PR_CreateProcess( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr); NSPR_API(PRStatus) PR_CreateProcessDetached( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr); NSPR_API(PRStatus) PR_DetachProcess(PRProcess *process); NSPR_API(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode); NSPR_API(PRStatus) PR_KillProcess(PRProcess *process); PR_END_EXTERN_C #endif /* prproces_h___ */ nspr-4.11/nspr/pr/include/prrng.h0000644000000000000000000000463512623070344015107 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prrng.h -- NSPR Random Number Generator ** ** ** lth. 29-Oct-1999. */ #ifndef prrng_h___ #define prrng_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** PR_GetRandomNoise() -- Get random noise from the host platform ** ** Description: ** PR_GetRandomNoise() provides, depending on platform, a random value. ** The length of the random value is dependent on platform and the ** platform's ability to provide a random value at that moment. ** ** The intent of PR_GetRandomNoise() is to provide a "seed" value for a ** another random number generator that may be suitable for ** cryptographic operations. This implies that the random value ** provided may not be, by itself, cryptographically secure. The value ** generated by PR_GetRandomNoise() is at best, extremely difficult to ** predict and is as non-deterministic as the underlying platfrom can ** provide. ** ** Inputs: ** buf -- pointer to a caller supplied buffer to contain the ** generated random number. buf must be at least as large as ** is specified in the 'size' argument. ** ** size -- the requested size of the generated random number ** ** Outputs: ** a random number provided in 'buf'. ** ** Returns: ** PRSize value equal to the size of the random number actually ** generated, or zero. The generated size may be less than the size ** requested. A return value of zero means that PR_GetRandomNoise() is ** not implemented on this platform, or there is no available noise ** available to be returned at the time of the call. ** ** Restrictions: ** Calls to PR_GetRandomNoise() may use a lot of CPU on some platforms. ** Some platforms may block for up to a few seconds while they ** accumulate some noise. Busy machines generate lots of noise, but ** care is advised when using PR_GetRandomNoise() frequently in your ** application. ** ** History: ** Parts of the model dependent implementation for PR_GetRandomNoise() ** were taken in whole or part from code previously in Netscape's NSS ** component. ** */ NSPR_API(PRSize) PR_GetRandomNoise( void *buf, PRSize size ); PR_END_EXTERN_C #endif /* prrng_h___ */ /* end prrng.h */ nspr-4.11/nspr/pr/include/prrwlock.h0000644000000000000000000000542612623070344015621 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prrwlock.h ** Description: API to basic reader-writer lock functions of NSPR. ** **/ #ifndef prrwlock_h___ #define prrwlock_h___ #include "prtypes.h" PR_BEGIN_EXTERN_C /* * PRRWLock -- * * The reader writer lock, PRRWLock, is an opaque object to the clients * of NSPR. All routines operate on a pointer to this opaque entity. */ typedef struct PRRWLock PRRWLock; #define PR_RWLOCK_RANK_NONE 0 /*********************************************************************** ** FUNCTION: PR_NewRWLock ** DESCRIPTION: ** Returns a pointer to a newly created reader-writer lock object. ** INPUTS: Lock rank ** Lock name ** OUTPUTS: void ** RETURN: PRRWLock* ** If the lock cannot be created because of resource constraints, NULL ** is returned. ** ***********************************************************************/ NSPR_API(PRRWLock*) PR_NewRWLock(PRUint32 lock_rank, const char *lock_name); /*********************************************************************** ** FUNCTION: PR_DestroyRWLock ** DESCRIPTION: ** Destroys a given RW lock object. ** INPUTS: PRRWLock *lock - Lock to be freed. ** OUTPUTS: void ** RETURN: None ***********************************************************************/ NSPR_API(void) PR_DestroyRWLock(PRRWLock *lock); /*********************************************************************** ** FUNCTION: PR_RWLock_Rlock ** DESCRIPTION: ** Apply a read lock (non-exclusive) on a RWLock ** INPUTS: PRRWLock *lock - Lock to be read-locked. ** OUTPUTS: void ** RETURN: None ***********************************************************************/ NSPR_API(void) PR_RWLock_Rlock(PRRWLock *lock); /*********************************************************************** ** FUNCTION: PR_RWLock_Wlock ** DESCRIPTION: ** Apply a write lock (exclusive) on a RWLock ** INPUTS: PRRWLock *lock - Lock to write-locked. ** OUTPUTS: void ** RETURN: None ***********************************************************************/ NSPR_API(void) PR_RWLock_Wlock(PRRWLock *lock); /*********************************************************************** ** FUNCTION: PR_RWLock_Unlock ** DESCRIPTION: ** Release a RW lock. Unlocking an unlocked lock has undefined results. ** INPUTS: PRRWLock *lock - Lock to unlocked. ** OUTPUTS: void ** RETURN: void ***********************************************************************/ NSPR_API(void) PR_RWLock_Unlock(PRRWLock *lock); PR_END_EXTERN_C #endif /* prrwlock_h___ */ nspr-4.11/nspr/pr/include/prshm.h0000644000000000000000000002057112623070344015105 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prshm.h -- NSPR Shared Memory ** ** NSPR Named Shared Memory API provides a cross-platform named ** shared-memory interface. NSPR Named Shared Memory is modeled on ** similar constructs in Unix and Windows operating systems. Shared ** memory allows multiple processes to access one or more common shared ** memory regions, using it as an inter-process communication channel. ** ** Notes on Platform Independence: ** NSPR Named Shared Memory is built on the native services offered ** by most platforms. The NSPR Named Shared Memory API tries to ** provide a least common denominator interface so that it works ** across all supported platforms. To ensure that it works everywhere, ** some platform considerations must be accomodated and the protocol ** for using NSPR Shared Memory API must be observed. ** ** Protocol: ** Multiple shared memories can be created using NSPR's Shared Memory ** feature. For each named shared memory, as defined by the name ** given in the PR_OpenSharedMemory() call, a protocol for using the ** shared memory API is required to ensure desired behavior. Failing ** to follow the protocol may yield unpredictable results. ** ** PR_OpenSharedMemory() will create the shared memory segment, if it ** does not already exist, or open a connection that the existing ** shared memory segment if it already exists. ** ** PR_AttachSharedMemory() should be called following ** PR_OpenSharedMemory() to map the memory segment to an address in ** the application's address space. ** ** PR_AttachSharedMemory() may be called to re-map a shared memory ** segment after detaching the same PRSharedMemory object. Be ** sure to detach it when done. ** ** PR_DetachSharedMemory() should be called to un-map the shared ** memory segment from the application's address space. ** ** PR_CloseSharedMemory() should be called when no further use of the ** PRSharedMemory object is required within a process. Following a ** call to PR_CloseSharedMemory() the PRSharedMemory object is ** invalid and cannot be reused. ** ** PR_DeleteSharedMemory() should be called before process ** termination. After calling PR_DeleteSharedMemory() any further use ** of the shared memory associated with the name may cause ** unpredictable results. ** ** Files: ** The name passed to PR_OpenSharedMemory() should be a valid filename ** for a unix platform. PR_OpenSharedMemory() creates file using the ** name passed in. Some platforms may mangle the name before creating ** the file and the shared memory. ** ** The unix implementation may use SysV IPC shared memory, Posix ** shared memory, or memory mapped files; the filename may used to ** define the namespace. On Windows, the name is significant, but ** there is no file associated with name. ** ** No assumptions about the persistence of data in the named file ** should be made. Depending on platform, the shared memory may be ** mapped onto system paging space and be discarded at process ** termination. ** ** All names provided to PR_OpenSharedMemory() should be valid ** filename syntax or name syntax for shared memory for the target ** platform. Referenced directories should have permissions ** appropriate for writing. ** ** Limits: ** Different platforms have limits on both the number and size of ** shared memory resources. The default system limits on some ** platforms may be smaller than your requirements. These limits may ** be adjusted on some platforms either via boot-time options or by ** setting the size of the system paging space to accomodate more ** and/or larger shared memory segment(s). ** ** Security: ** On unix platforms, depending on implementation, contents of the ** backing store for the shared memory can be exposed via the file ** system. Set permissions and or access controls at create and attach ** time to ensure you get the desired security. ** ** On windows platforms, no special security measures are provided. ** ** Example: ** The test case pr/tests/nameshm1.c provides an example of use as ** well as testing the operation of NSPR's Named Shared Memory. ** ** lth. 18-Aug-1999. */ #ifndef prshm_h___ #define prshm_h___ #include "prtypes.h" #include "prio.h" PR_BEGIN_EXTERN_C /* ** Declare opaque type PRSharedMemory. */ typedef struct PRSharedMemory PRSharedMemory; /* ** FUNCTION: PR_OpenSharedMemory() ** ** DESCRIPTION: ** PR_OpenSharedMemory() creates a new shared-memory segment or ** associates a previously created memory segment with name. ** ** When parameter create is (PR_SHM_EXCL | PR_SHM_CREATE) and the ** shared memory already exists, the function returns NULL with the ** error set to PR_FILE_EXISTS_ERROR. ** ** When parameter create is PR_SHM_CREATE and the shared memory ** already exists, a handle to that memory segment is returned. If ** the segment does not exist, it is created and a pointer to the ** related PRSharedMemory structure is returned. ** ** When parameter create is 0, and the shared memory exists, a ** pointer to a PRSharedMemory is returned. If the shared memory does ** not exist, NULL is returned with the error set to ** PR_FILE_NOT_FOUND_ERROR. ** ** INPUTS: ** name -- the name the shared-memory segment is known as. ** size -- the size of the shared memory segment. ** flags -- Options for creating the shared memory ** mode -- Same as is passed to PR_Open() ** ** OUTPUTS: ** The shared memory is allocated. ** ** RETURNS: Pointer to opaque structure PRSharedMemory or NULL. ** NULL is returned on error. The reason for the error can be ** retrieved via PR_GetError() and PR_GetOSError(); ** */ NSPR_API( PRSharedMemory * ) PR_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ); /* Define values for PR_OpenShareMemory(...,create) */ #define PR_SHM_CREATE 0x1 /* create if not exist */ #define PR_SHM_EXCL 0x2 /* fail if already exists */ /* ** FUNCTION: PR_AttachSharedMemory() ** ** DESCRIPTION: ** PR_AttachSharedMemory() maps the shared-memory described by ** shm to the current process. ** ** INPUTS: ** shm -- The handle returned from PR_OpenSharedMemory(). ** flags -- options for mapping the shared memory. ** PR_SHM_READONLY causes the memory to be attached ** read-only. ** ** OUTPUTS: ** On success, the shared memory segment represented by shm is mapped ** into the process' address space. ** ** RETURNS: Address where shared memory is mapped, or NULL. ** NULL is returned on error. The reason for the error can be ** retrieved via PR_GetError() and PR_GetOSError(); ** ** */ NSPR_API( void * ) PR_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ); /* Define values for PR_AttachSharedMemory(...,flags) */ #define PR_SHM_READONLY 0x01 /* ** FUNCTION: PR_DetachSharedMemory() ** ** DESCRIPTION: ** PR_DetachSharedMemory() detaches the shared-memory described ** by shm. ** ** INPUTS: ** shm -- The handle returned from PR_OpenSharedMemory(). ** addr -- The address at which the memory was attached. ** ** OUTPUTS: ** The shared memory mapped to an address via a previous call to ** PR_AttachSharedMemory() is unmapped. ** ** RETURNS: PRStatus ** */ NSPR_API( PRStatus ) PR_DetachSharedMemory( PRSharedMemory *shm, void *addr ); /* ** FUNCTION: PR_CloseSharedMemory() ** ** DESCRIPTION: ** PR_CloseSharedMemory() closes the shared-memory described by ** shm. ** ** INPUTS: ** shm -- The handle returned from PR_OpenSharedMemory(). ** ** OUTPUTS: ** the shared memory represented by shm is closed ** ** RETURNS: PRStatus ** */ NSPR_API( PRStatus ) PR_CloseSharedMemory( PRSharedMemory *shm ); /* ** FUNCTION: PR_DeleteSharedMemory() ** ** DESCRIPTION: ** The shared memory resource represented by name is released. ** ** INPUTS: ** name -- the name the shared-memory segment ** ** OUTPUTS: ** depending on platform, resources may be returned to the underlying ** operating system. ** ** RETURNS: PRStatus ** */ NSPR_API( PRStatus ) PR_DeleteSharedMemory( const char *name ); PR_END_EXTERN_C #endif /* prshm_h___ */ nspr-4.11/nspr/pr/include/prshma.h0000644000000000000000000001577612623070344015261 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prshma.h -- NSPR Anonymous Shared Memory ** ** NSPR provides an anonymous shared memory based on NSPR's PRFileMap ** type. The anonymous file-mapped shared memory provides an inheritable ** shared memory, as in: the child process inherits the shared memory. ** Compare the file-mapped anonymous shared memory to to a named shared ** memory described in prshm.h. The intent is to provide a shared ** memory that is accessable only by parent and child processes. ... ** It's a security thing. ** ** Depending on the underlying platform, the file-mapped shared memory ** may be backed by a file. ... surprise! ... On some platforms, no ** real file backs the shared memory. On platforms where the shared ** memory is backed by a file, the file's name in the filesystem is ** visible to other processes for only the duration of the creation of ** the file, hopefully a very short time. This restricts processess ** that do not inherit the shared memory from opening the file and ** reading or writing its contents. Further, when all processes ** using an anonymous shared memory terminate, the backing file is ** deleted. ... If you are not paranoid, you're not paying attention. ** ** The file-mapped shared memory requires a protocol for the parent ** process and child process to share the memory. NSPR provides two ** protocols. Use one or the other; don't mix and match. ** ** In the first protocol, the job of passing the inheritable shared ** memory is done via helper-functions with PR_CreateProcess(). In the ** second protocol, the parent process is responsible for creating the ** child process; the parent and child are mutually responsible for ** passing a FileMap string. NSPR provides helper functions for ** extracting data from the PRFileMap object. ... See the examples ** below. ** ** Both sides should adhere strictly to the protocol for proper ** operation. The pseudo-code below shows the use of a file-mapped ** shared memory by a parent and child processes. In the examples, the ** server creates the file-mapped shared memory, the client attaches to ** it. ** ** First protocol. ** Server: ** ** fm = PR_OpenAnonFileMap(dirName, size, FilemapProt); ** addr = PR_MemMap(fm); ** attr = PR_NewProcessAttr(); ** PR_ProcessAttrSetInheritableFileMap( attr, fm, shmname ); ** PR_CreateProcess(Client); ** PR_DestroyProcessAttr(attr); ** ... yadda ... ** PR_MemUnmap( addr ); ** PR_CloseFileMap(fm); ** ** ** Client: ** ... started by server via PR_CreateProcess() ** fm = PR_GetInheritedFileMap( shmname ); ** addr = PR_MemMap(fm); ** ... yadda ... ** PR_MemUnmap(addr); ** PR_CloseFileMap(fm); ** ** ** Second Protocol: ** Server: ** ** fm = PR_OpenAnonFileMap(dirName, size, FilemapProt); ** fmstring = PR_ExportFileMapAsString( fm ); ** addr = PR_MemMap(fm); ** ... application specific technique to pass fmstring to child ** ... yadda ... Server uses his own magic to create child ** PR_MemUnmap( addr ); ** PR_CloseFileMap(fm); ** ** ** Client: ** ... started by server via his own magic ** ... application specific technique to find fmstring from parent ** fm = PR_ImportFileMapFromString( fmstring ) ** addr = PR_MemMap(fm); ** ... yadda ... ** PR_MemUnmap(addr); ** PR_CloseFileMap(fm); ** ** ** lth. 2-Jul-1999. ** ** Note: The second protocol was requested by NelsonB (7/1999); this is ** to accomodate servers which already create their own child processes ** using platform native methods. ** */ #ifndef prshma_h___ #define prshma_h___ #include "prtypes.h" #include "prio.h" #include "prproces.h" PR_BEGIN_EXTERN_C /* ** PR_OpenAnonFileMap() -- Creates an anonymous file-mapped shared memory ** ** Description: ** PR_OpenAnonFileMap() creates an anonymous shared memory. If the ** shared memory already exists, a handle is returned to that shared ** memory object. ** ** On Unix platforms, PR_OpenAnonFileMap() uses 'dirName' as a ** directory name, without the trailing '/', to contain the anonymous ** file. A filename is generated for the name. ** ** On Windows platforms, dirName is ignored. ** ** Inputs: ** dirName -- A directory name to contain the anonymous file. ** size -- The size of the shared memory ** prot -- How the shared memory is mapped. See prio.h ** ** Outputs: ** PRFileMap * ** ** Returns: ** Pointer to PRFileMap or NULL on error. ** */ NSPR_API( PRFileMap *) PR_OpenAnonFileMap( const char *dirName, PRSize size, PRFileMapProtect prot ); /* ** PR_ProcessAttrSetInheritableFileMap() -- Prepare FileMap for export ** to my children processes via PR_CreateProcess() ** ** Description: ** PR_ProcessAttrSetInheritableFileMap() connects the PRFileMap to ** PRProcessAttr with shmname. A subsequent call to PR_CreateProcess() ** makes the PRFileMap importable by the child process. ** ** Inputs: ** attr -- PRProcessAttr, used to pass data to PR_CreateProcess() ** fm -- PRFileMap structure to be passed to the child process ** shmname -- The name for the PRFileMap; used by child. ** ** Outputs: ** PRFileMap * ** ** Returns: ** PRStatus ** */ NSPR_API(PRStatus) PR_ProcessAttrSetInheritableFileMap( PRProcessAttr *attr, PRFileMap *fm, const char *shmname ); /* ** PR_GetInheritedFileMap() -- Import a PRFileMap previously exported ** by my parent process via PR_CreateProcess() ** ** Description: ** PR_GetInheritedFileMap() retrieves a PRFileMap object exported from ** its parent process via PR_CreateProcess(). ** ** Inputs: ** shmname -- The name provided to PR_ProcessAttrSetInheritableFileMap() ** ** Outputs: ** PRFileMap * ** ** Returns: ** PRFileMap pointer or NULL. ** */ NSPR_API( PRFileMap *) PR_GetInheritedFileMap( const char *shmname ); /* ** PR_ExportFileMapAsString() -- Creates a string identifying a PRFileMap ** ** Description: ** Creates an identifier, as a string, from a PRFileMap object ** previously created with PR_OpenAnonFileMap(). ** ** Inputs: ** fm -- PRFileMap pointer to be represented as a string. ** bufsize -- sizeof(buf) ** buf -- a buffer of length PR_FILEMAP_STRING_BUFSIZE ** ** Outputs: ** buf contains the stringized PRFileMap identifier ** ** Returns: ** PRStatus ** */ NSPR_API( PRStatus ) PR_ExportFileMapAsString( PRFileMap *fm, PRSize bufsize, char *buf ); #define PR_FILEMAP_STRING_BUFSIZE 128 /* ** PR_ImportFileMapFromString() -- Creates a PRFileMap from the identifying string ** ** Description: ** PR_ImportFileMapFromString() creates a PRFileMap object from a ** string previously created by PR_ExportFileMapAsString(). ** ** Inputs: ** fmstring -- string created by PR_ExportFileMapAsString() ** ** Returns: ** PRFileMap pointer or NULL. ** */ NSPR_API( PRFileMap * ) PR_ImportFileMapFromString( const char *fmstring ); PR_END_EXTERN_C #endif /* prshma_h___ */ nspr-4.11/nspr/pr/include/prsystem.h0000644000000000000000000000516412623070344015643 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prsystem_h___ #define prsystem_h___ /* ** API to NSPR functions returning system info. */ #include "prtypes.h" PR_BEGIN_EXTERN_C /* ** Get the host' directory separator. ** Pathnames are then assumed to be of the form: ** []*() */ NSPR_API(char) PR_GetDirectorySeparator(void); /* ** OBSOLETE -- the function name is misspelled. ** Use PR_GetDirectorySeparator instead. */ NSPR_API(char) PR_GetDirectorySepartor(void); /* ** Get the host' path separator. ** Paths are assumed to be of the form: ** []* */ NSPR_API(char) PR_GetPathSeparator(void); /* Types of information available via PR_GetSystemInfo(...) */ typedef enum { PR_SI_HOSTNAME, /* the hostname with the domain name (if any) * removed */ PR_SI_SYSNAME, PR_SI_RELEASE, PR_SI_ARCHITECTURE, PR_SI_HOSTNAME_UNTRUNCATED /* the hostname exactly as configured * on the system */ } PRSysInfo; /* ** If successful returns a null termintated string in 'buf' for ** the information indicated in 'cmd'. If unseccussful the reason for ** the failure can be retrieved from PR_GetError(). ** ** The buffer is allocated by the caller and should be at least ** SYS_INFO_BUFFER_LENGTH bytes in length. */ #define SYS_INFO_BUFFER_LENGTH 256 NSPR_API(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen); /* ** Return the number of bytes in a page */ NSPR_API(PRInt32) PR_GetPageSize(void); /* ** Return log2 of the size of a page */ NSPR_API(PRInt32) PR_GetPageShift(void); /* ** PR_GetNumberOfProcessors() -- returns the number of CPUs ** ** Description: ** PR_GetNumberOfProcessors() extracts the number of processors ** (CPUs available in an SMP system) and returns the number. ** ** Parameters: ** none ** ** Returns: ** The number of available processors or -1 on error ** */ NSPR_API(PRInt32) PR_GetNumberOfProcessors( void ); /* ** PR_GetPhysicalMemorySize() -- returns the amount of system RAM ** ** Description: ** PR_GetPhysicalMemorySize() determines the amount of physical RAM ** in the system and returns the size in bytes. ** ** Parameters: ** none ** ** Returns: ** The amount of system RAM, or 0 on failure. ** */ NSPR_API(PRUint64) PR_GetPhysicalMemorySize(void); PR_END_EXTERN_C #endif /* prsystem_h___ */ nspr-4.11/nspr/pr/include/prthread.h0000644000000000000000000002343112623070344015563 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prthread_h___ #define prthread_h___ /* ** API for NSPR threads. On some architectures (Mac OS Classic ** notably) pre-emptibility is not guaranteed. Hard priority scheduling ** is not guaranteed, so programming using priority based synchronization ** is a no-no. ** ** NSPR threads are scheduled based loosely on their client set priority. ** In general, a thread of a higher priority has a statistically better ** chance of running relative to threads of lower priority. However, ** NSPR uses multiple strategies to provide execution vehicles for thread ** abstraction of various host platforms. As it turns out, there is little ** NSPR can do to affect the scheduling attributes of "GLOBAL" threads. ** However, a semblance of GLOBAL threads is used to implement "LOCAL" ** threads. An arbitrary number of such LOCAL threads can be assigned to ** a single GLOBAL thread. ** ** For scheduling, NSPR will attempt to run the highest priority LOCAL ** thread associated with a given GLOBAL thread. It is further assumed ** that the host OS will apply some form of "fair" scheduling on the ** GLOBAL threads. ** ** Threads have a "system flag" which when set indicates the thread ** doesn't count for determining when the process should exit (the ** process exits when the last user thread exits). ** ** Threads also have a "scope flag" which controls whether the threads ** are scheduled in the local scope or scheduled by the OS globally. This ** indicates whether a thread is permanently bound to a native OS thread. ** An unbound thread competes for scheduling resources in the same process. ** ** Another flag is "state flag" which control whether the thread is joinable. ** It allows other threads to wait for the created thread to reach completion. ** ** Threads can have "per-thread-data" attached to them. Each thread has a ** per-thread error number and error string which are updated when NSPR ** operations fail. */ #include "prtypes.h" #include "prinrval.h" PR_BEGIN_EXTERN_C typedef struct PRThread PRThread; typedef struct PRThreadStack PRThreadStack; typedef enum PRThreadType { PR_USER_THREAD, PR_SYSTEM_THREAD } PRThreadType; typedef enum PRThreadScope { PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD } PRThreadScope; typedef enum PRThreadState { PR_JOINABLE_THREAD, PR_UNJOINABLE_THREAD } PRThreadState; typedef enum PRThreadPriority { PR_PRIORITY_FIRST = 0, /* just a placeholder */ PR_PRIORITY_LOW = 0, /* the lowest possible priority */ PR_PRIORITY_NORMAL = 1, /* most common expected priority */ PR_PRIORITY_HIGH = 2, /* slightly more aggressive scheduling */ PR_PRIORITY_URGENT = 3, /* it does little good to have more than one */ PR_PRIORITY_LAST = 3 /* this is just a placeholder */ } PRThreadPriority; /* ** Create a new thread: ** "type" is the type of thread to create ** "start(arg)" will be invoked as the threads "main" ** "priority" will be created thread's priority ** "scope" will specify whether the thread is local or global ** "state" will specify whether the thread is joinable or not ** "stackSize" the size of the stack, in bytes. The value can be zero ** and then a machine specific stack size will be chosen. ** ** This can return NULL if some kind of error occurs, such as if memory is ** tight. ** ** If you want the thread to start up waiting for the creator to do ** something, enter a lock before creating the thread and then have the ** threads start routine enter and exit the same lock. When you are ready ** for the thread to run, exit the lock. ** ** If you want to detect the completion of the created thread, the thread ** should be created joinable. Then, use PR_JoinThread to synchrnoize the ** termination of another thread. ** ** When the start function returns the thread exits. If it is the last ** PR_USER_THREAD to exit then the process exits. */ NSPR_API(PRThread*) PR_CreateThread(PRThreadType type, void (PR_CALLBACK *start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize); /* ** Wait for thread termination: ** "thread" is the target thread ** ** This can return PR_FAILURE if no joinable thread could be found ** corresponding to the specified target thread. ** ** The calling thread is blocked until the target thread completes. ** Several threads cannot wait for the same thread to complete; one thread ** will operate successfully and others will terminate with an error PR_FAILURE. ** The calling thread will not be blocked if the target thread has already ** terminated. */ NSPR_API(PRStatus) PR_JoinThread(PRThread *thread); /* ** Return the current thread object for the currently running code. ** Never returns NULL. */ NSPR_API(PRThread*) PR_GetCurrentThread(void); #ifndef NO_NSPR_10_SUPPORT #define PR_CurrentThread() PR_GetCurrentThread() /* for nspr1.0 compat. */ #endif /* NO_NSPR_10_SUPPORT */ /* ** Get the priority of "thread". */ NSPR_API(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread); /* ** Change the priority of the "thread" to "priority". ** ** PR_SetThreadPriority works in a best-effort manner. On some platforms a ** special privilege, such as root access, is required to change thread ** priorities, especially to raise thread priorities. If the caller doesn't ** have enough privileges to change thread priorites, the function has no ** effect except causing a future PR_GetThreadPriority call to return ** |priority|. */ NSPR_API(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority priority); /* ** Set the name of the current thread, which will be visible in a debugger ** and accessible via a call to PR_GetThreadName(). */ NSPR_API(PRStatus) PR_SetCurrentThreadName(const char *name); /* ** Return the name of "thread", if set. Otherwise return NULL. */ NSPR_API(const char *) PR_GetThreadName(const PRThread *thread); /* ** This routine returns a new index for per-thread-private data table. ** The index is visible to all threads within a process. This index can ** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines ** to save and retrieve data associated with the index for a thread. ** ** Each index is associationed with a destructor function ('dtor'). The function ** may be specified as NULL when the index is created. If it is not NULL, the ** function will be called when: ** - the thread exits and the private data for the associated index ** is not NULL, ** - new thread private data is set and the current private data is ** not NULL. ** ** The index independently maintains specific values for each binding thread. ** A thread can only get access to its own thread-specific-data. ** ** Upon a new index return the value associated with the index for all threads ** is NULL, and upon thread creation the value associated with all indices for ** that thread is NULL. ** ** Returns PR_FAILURE if the total number of indices will exceed the maximun ** allowed. */ typedef void (PR_CALLBACK *PRThreadPrivateDTOR)(void *priv); NSPR_API(PRStatus) PR_NewThreadPrivateIndex( PRUintn *newIndex, PRThreadPrivateDTOR destructor); /* ** Define some per-thread-private data. ** "tpdIndex" is an index into the per-thread private data table ** "priv" is the per-thread-private data ** ** If the per-thread private data table has a previously registered ** destructor function and a non-NULL per-thread-private data value, ** the destructor function is invoked. ** ** This can return PR_FAILURE if the index is invalid. */ NSPR_API(PRStatus) PR_SetThreadPrivate(PRUintn tpdIndex, void *priv); /* ** Recover the per-thread-private data for the current thread. "tpdIndex" is ** the index into the per-thread private data table. ** ** The returned value may be NULL which is indistinguishable from an error ** condition. ** ** A thread can only get access to its own thread-specific-data. */ NSPR_API(void*) PR_GetThreadPrivate(PRUintn tpdIndex); /* ** This routine sets the interrupt request for a target thread. The interrupt ** request remains in the thread's state until it is delivered exactly once ** or explicitly canceled. ** ** A thread that has been interrupted will fail all NSPR blocking operations ** that return a PRStatus (I/O, waiting on a condition, etc). ** ** PR_Interrupt may itself fail if the target thread is invalid. */ NSPR_API(PRStatus) PR_Interrupt(PRThread *thread); /* ** Clear the interrupt request for the calling thread. If no such request ** is pending, this operation is a noop. */ NSPR_API(void) PR_ClearInterrupt(void); /* ** Block the interrupt for the calling thread. */ NSPR_API(void) PR_BlockInterrupt(void); /* ** Unblock the interrupt for the calling thread. */ NSPR_API(void) PR_UnblockInterrupt(void); /* ** Make the current thread sleep until "ticks" time amount of time ** has expired. If "ticks" is PR_INTERVAL_NO_WAIT then the call is ** equivalent to calling PR_Yield. Calling PR_Sleep with an argument ** equivalent to PR_INTERVAL_NO_TIMEOUT is an error and will result ** in a PR_FAILURE error return. */ NSPR_API(PRStatus) PR_Sleep(PRIntervalTime ticks); /* ** Get the scoping of this thread. */ NSPR_API(PRThreadScope) PR_GetThreadScope(const PRThread *thread); /* ** Get the type of this thread. */ NSPR_API(PRThreadType) PR_GetThreadType(const PRThread *thread); /* ** Get the join state of this thread. */ NSPR_API(PRThreadState) PR_GetThreadState(const PRThread *thread); PR_END_EXTERN_C #endif /* prthread_h___ */ nspr-4.11/nspr/pr/include/prtime.h0000644000000000000000000002366612623070344015264 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* *---------------------------------------------------------------------- * * prtime.h -- * * NSPR date and time functions * *----------------------------------------------------------------------- */ #ifndef prtime_h___ #define prtime_h___ #include "prlong.h" PR_BEGIN_EXTERN_C /**********************************************************************/ /************************* TYPES AND CONSTANTS ************************/ /**********************************************************************/ #define PR_MSEC_PER_SEC 1000L #define PR_USEC_PER_SEC 1000000L #define PR_NSEC_PER_SEC 1000000000L #define PR_USEC_PER_MSEC 1000L #define PR_NSEC_PER_MSEC 1000000L /* * PRTime -- * * NSPR represents basic time as 64-bit signed integers relative * to midnight (00:00:00), January 1, 1970 Greenwich Mean Time (GMT). * (GMT is also known as Coordinated Universal Time, UTC.) * The units of time are in microseconds. Negative times are allowed * to represent times prior to the January 1970 epoch. Such values are * intended to be exported to other systems or converted to human * readable form. * * Notes on porting: PRTime corresponds to time_t in ANSI C. NSPR 1.0 * simply uses PRInt64. */ typedef PRInt64 PRTime; /* * Time zone and daylight saving time corrections applied to GMT to * obtain the local time of some geographic location */ typedef struct PRTimeParameters { PRInt32 tp_gmt_offset; /* the offset from GMT in seconds */ PRInt32 tp_dst_offset; /* contribution of DST in seconds */ } PRTimeParameters; /* * PRExplodedTime -- * * Time broken down into human-readable components such as year, month, * day, hour, minute, second, and microsecond. Time zone and daylight * saving time corrections may be applied. If they are applied, the * offsets from the GMT must be saved in the 'tm_params' field so that * all the information is available to reconstruct GMT. * * Notes on porting: PRExplodedTime corrresponds to struct tm in * ANSI C, with the following differences: * - an additional field tm_usec; * - replacing tm_isdst by tm_params; * - the month field is spelled tm_month, not tm_mon; * - we use absolute year, AD, not the year since 1900. * The corresponding type in NSPR 1.0 is called PRTime. Below is * a table of date/time type correspondence in the three APIs: * API time since epoch time in components * ANSI C time_t struct tm * NSPR 1.0 PRInt64 PRTime * NSPR 2.0 PRTime PRExplodedTime */ typedef struct PRExplodedTime { PRInt32 tm_usec; /* microseconds past tm_sec (0-99999) */ PRInt32 tm_sec; /* seconds past tm_min (0-61, accomodating up to two leap seconds) */ PRInt32 tm_min; /* minutes past tm_hour (0-59) */ PRInt32 tm_hour; /* hours past tm_day (0-23) */ PRInt32 tm_mday; /* days past tm_mon (1-31, note that it starts from 1) */ PRInt32 tm_month; /* months past tm_year (0-11, Jan = 0) */ PRInt16 tm_year; /* absolute year, AD (note that we do not count from 1900) */ PRInt8 tm_wday; /* calculated day of the week (0-6, Sun = 0) */ PRInt16 tm_yday; /* calculated day of the year (0-365, Jan 1 = 0) */ PRTimeParameters tm_params; /* time parameters used by conversion */ } PRExplodedTime; /* * PRTimeParamFn -- * * A function of PRTimeParamFn type returns the time zone and * daylight saving time corrections for some geographic location, * given the current time in GMT. The input argument gmt should * point to a PRExplodedTime that is in GMT, i.e., whose * tm_params contains all 0's. * * For any time zone other than GMT, the computation is intended to * consist of two steps: * - Figure out the time zone correction, tp_gmt_offset. This number * usually depends on the geographic location only. But it may * also depend on the current time. For example, all of China * is one time zone right now. But this situation may change * in the future. * - Figure out the daylight saving time correction, tp_dst_offset. * This number depends on both the geographic location and the * current time. Most of the DST rules are expressed in local * current time. If so, one should apply the time zone correction * to GMT before applying the DST rules. */ typedef PRTimeParameters (PR_CALLBACK *PRTimeParamFn)(const PRExplodedTime *gmt); /**********************************************************************/ /****************************** FUNCTIONS *****************************/ /**********************************************************************/ /* * The PR_Now routine returns the current time relative to the * epoch, midnight, January 1, 1970 UTC. The units of the returned * value are microseconds since the epoch. * * The values returned are not guaranteed to advance in a linear fashion * due to the application of time correction protocols which synchronize * computer clocks to some external time source. Consequently it should * not be depended on for interval timing. * * The implementation is machine dependent. * Cf. time_t time(time_t *tp) in ANSI C. */ NSPR_API(PRTime) PR_Now(void); /* * Expand time binding it to time parameters provided by PRTimeParamFn. * The calculation is envisoned to proceed in the following steps: * - From given PRTime, calculate PRExplodedTime in GMT * - Apply the given PRTimeParamFn to the GMT that we just calculated * to obtain PRTimeParameters. * - Add the PRTimeParameters offsets to GMT to get the local time * as PRExplodedTime. */ NSPR_API(void) PR_ExplodeTime( PRTime usecs, PRTimeParamFn params, PRExplodedTime *exploded); /* Reverse operation of PR_ExplodeTime */ NSPR_API(PRTime) PR_ImplodeTime(const PRExplodedTime *exploded); /* * Adjust exploded time to normalize field overflows after manipulation. * Note that the following fields of PRExplodedTime should not be * manipulated: * - tm_month and tm_year: because the number of days in a month and * number of days in a year are not constant, it is ambiguous to * manipulate the month and year fields, although one may be tempted * to. For example, what does "a month from January 31st" mean? * - tm_wday and tm_yday: these fields are calculated by NSPR. Users * should treat them as "read-only". */ NSPR_API(void) PR_NormalizeTime( PRExplodedTime *exploded, PRTimeParamFn params); /**********************************************************************/ /*********************** TIME PARAMETER FUNCTIONS *********************/ /**********************************************************************/ /* Time parameters that suit current host machine */ NSPR_API(PRTimeParameters) PR_LocalTimeParameters(const PRExplodedTime *gmt); /* Time parameters that represent Greenwich Mean Time */ NSPR_API(PRTimeParameters) PR_GMTParameters(const PRExplodedTime *gmt); /* * Time parameters that represent the US Pacific Time Zone, with the * current daylight saving time rules (for testing only) */ NSPR_API(PRTimeParameters) PR_USPacificTimeParameters(const PRExplodedTime *gmt); /* * This parses a time/date string into a PRExplodedTime * struct. It populates all fields but it can't split * the offset from UTC into tp_gmt_offset and tp_dst_offset in * most cases (exceptions: PST/PDT, MST/MDT, CST/CDT, EST/EDT, GMT/BST). * In those cases tp_gmt_offset will be the sum of these two and * tp_dst_offset will be 0. * It returns PR_SUCCESS on success, and PR_FAILURE * if the time/date string can't be parsed. * * Many formats are handled, including: * * 14 Apr 89 03:20:12 * 14 Apr 89 03:20 GMT * Fri, 17 Mar 89 4:01:33 * Fri, 17 Mar 89 4:01 GMT * Mon Jan 16 16:12 PDT 1989 * Mon Jan 16 16:12 +0130 1989 * 6 May 1992 16:41-JST (Wednesday) * 22-AUG-1993 10:59:12.82 * 22-AUG-1993 10:59pm * 22-AUG-1993 12:59am * 22-AUG-1993 12:59 PM * Friday, August 04, 1995 3:54 PM * 06/21/95 04:24:34 PM * 20/06/95 21:07 * 95-06-08 19:32:48 EDT * * If the input string doesn't contain a description of the timezone, * we consult the `default_to_gmt' to decide whether the string should * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). * The correct value for this argument depends on what standard specified * the time string which you are parsing. */ NSPR_API(PRStatus) PR_ParseTimeStringToExplodedTime ( const char *string, PRBool default_to_gmt, PRExplodedTime *result); /* * This uses PR_ParseTimeStringToExplodedTime to parse * a time/date string and PR_ImplodeTime to transform it into * a PRTime (microseconds after "1-Jan-1970 00:00:00 GMT"). * It returns PR_SUCCESS on success, and PR_FAILURE * if the time/date string can't be parsed. */ NSPR_API(PRStatus) PR_ParseTimeString ( const char *string, PRBool default_to_gmt, PRTime *result); /* Format a time value into a buffer. Same semantics as strftime() */ NSPR_API(PRUint32) PR_FormatTime(char *buf, int buflen, const char *fmt, const PRExplodedTime *time); /* Format a time value into a buffer. Time is always in US English format, * regardless of locale setting. */ NSPR_API(PRUint32) PR_FormatTimeUSEnglish(char *buf, PRUint32 bufSize, const char *format, const PRExplodedTime *time); PR_END_EXTERN_C #endif /* prtime_h___ */ nspr-4.11/nspr/pr/include/prtpool.h0000644000000000000000000000441512623070344015452 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prtpool_h___ #define prtpool_h___ #include "prtypes.h" #include "prthread.h" #include "prio.h" #include "prerror.h" /* * NOTE: * THIS API IS A PRELIMINARY VERSION IN NSPR 4.0 AND IS SUBJECT TO * CHANGE */ PR_BEGIN_EXTERN_C typedef struct PRJobIoDesc { PRFileDesc *socket; PRErrorCode error; PRIntervalTime timeout; } PRJobIoDesc; typedef struct PRThreadPool PRThreadPool; typedef struct PRJob PRJob; typedef void (PR_CALLBACK *PRJobFn) (void *arg); /* Create thread pool */ NSPR_API(PRThreadPool *) PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads, PRUint32 stacksize); /* queue a job */ NSPR_API(PRJob *) PR_QueueJob(PRThreadPool *tpool, PRJobFn fn, void *arg, PRBool joinable); /* queue a job, when a socket is readable */ NSPR_API(PRJob *) PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when a socket is writeable */ NSPR_API(PRJob *) PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when a socket has a pending connection */ NSPR_API(PRJob *) PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when the socket connection to addr succeeds or fails */ NSPR_API(PRJob *) PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod, const PRNetAddr *addr, PRJobFn fn, void * arg, PRBool joinable); /* queue a job, when a timer exipres */ NSPR_API(PRJob *) PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, PRJobFn fn, void * arg, PRBool joinable); /* cancel a job */ NSPR_API(PRStatus) PR_CancelJob(PRJob *job); /* join a job */ NSPR_API(PRStatus) PR_JoinJob(PRJob *job); /* shutdown pool */ NSPR_API(PRStatus) PR_ShutdownThreadPool(PRThreadPool *tpool); /* join pool, wait for exit of all threads */ NSPR_API(PRStatus) PR_JoinThreadPool(PRThreadPool *tpool); PR_END_EXTERN_C #endif /* prtpool_h___ */ nspr-4.11/nspr/pr/include/prtrace.h0000644000000000000000000005364112623070344015420 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prtrace_h___ #define prtrace_h___ /* ** prtrace.h -- NSPR's Trace Facility. ** ** The Trace Facility provides a means to trace application ** program events within a process. When implementing an ** application program an engineer may insert a "Trace" function ** call, passing arguments to be traced. The "Trace" function ** combines the user trace data with identifying data and ** writes this data in time ordered sequence into a circular ** in-memory buffer; when the buffer fills, it wraps. ** ** Functions are provided to set and/or re-configure the size of ** the trace buffer, control what events are recorded in the ** buffer, enable and disable tracing based on specific user ** supplied data and other control functions. Methods are provided ** to record the trace entries in the in-memory trace buffer to ** a file. ** ** Tracing may cause a performance degredation to the application ** depending on the number and placement of calls to the tracing ** facility. When tracing is compiled in and all tracing is ** disabled via the runtime controls, the overhead should be ** minimal. ... Famous last words, eh? ** ** When DEBUG is defined at compile time, the Trace Facility is ** compiled as part of NSPR and any application using NSPR's ** header files will have tracing compiled in. When DEBUG is not ** defined, the Trace Facility is not compiled into NSPR nor ** exported in its header files. If the Trace Facility is ** desired in a non-debug build, then FORCE_NSPR_TRACE may be ** defined at compile time for both the optimized build of NSPR ** and the application. NSPR and any application using NSPR's ** Trace Facility must be compiled with the same level of trace ** conditioning or unresolved references may be realized at link ** time. ** ** For any of the Trace Facility methods that requires a trace ** handle as an input argument, the caller must ensure that the ** trace handle argument is valid. An invalid trace handle ** argument may cause unpredictable results. ** ** Trace Facility methods are thread-safe and SMP safe. ** ** Users of the Trace Facility should use the defined macros to ** invoke trace methods, not the function calls directly. e.g. ** PR_TRACE( h1,0,1,2, ...); not PR_Trace(h1,0,1,2, ...); ** ** Application designers should be aware of the effects of ** debug and optimized build differences when using result of the ** Trace Facility macros in expressions. ** ** See Also: prcountr.h ** ** /lth. 08-Jun-1998. */ #include "prtypes.h" #include "prthread.h" #include "prtime.h" PR_BEGIN_EXTERN_C /* ** Opaque type for the trace handle ** ... Don't even think about looking in here. ** */ typedef void * PRTraceHandle; /* ** PRTraceEntry -- A trace entry in the in-memory trace buffer ** looks like this. ** */ typedef struct PRTraceEntry { PRThread *thread; /* The thread creating the trace entry */ PRTraceHandle handle; /* PRTraceHandle creating the trace entry */ PRTime time; /* Value of PR_Now() at time of trace entry */ PRUint32 userData[8]; /* user supplied trace data */ } PRTraceEntry; /* ** PRTraceOption -- command operands to ** PR_[Set|Get]TraceOption(). See descriptive meanings there. ** */ typedef enum PRTraceOption { PRTraceBufSize, PRTraceEnable, PRTraceDisable, PRTraceSuspend, PRTraceResume, PRTraceSuspendRecording, PRTraceResumeRecording, PRTraceLockHandles, PRTraceUnLockHandles, PRTraceStopRecording } PRTraceOption; /* ----------------------------------------------------------------------- ** FUNCTION: PR_DEFINE_TRACE() -- Define a PRTraceHandle ** ** DESCRIPTION: PR_DEFINE_TRACE() is used to define a trace ** handle. ** */ #define PR_DEFINE_TRACE(name) PRTraceHandle name /* ----------------------------------------------------------------------- ** FUNCTION: PR_INIT_TRACE_HANDLE() -- Set the value of a PRTraceHandle ** ** DESCRIPTION: ** PR_INIT_TRACE_HANDLE() sets the value of a PRTraceHandle ** to value. e.g. PR_INIT_TRACE_HANDLE( myHandle, NULL ); ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_INIT_TRACE_HANDLE(handle,value)\ (handle) = (PRCounterHandle)(value) #else #define PR_INIT_TRACE_HANDLE(handle,value) #endif /* ----------------------------------------------------------------------- ** FUNCTION: PR_CreateTrace() -- Create a trace handle ** ** DESCRIPTION: ** PR_CreateTrace() creates a new trace handle. Tracing is ** enabled for this handle when it is created. The trace handle ** is intended for use in other Trace Facility calls. ** ** PR_CreateTrace() registers the QName, RName and description ** data so that this data can be retrieved later. ** ** INPUTS: ** qName: pointer to string. QName for this trace handle. ** ** rName: pointer to string. RName for this trace handle. ** ** description: pointer to string. Descriptive data about this ** trace handle. ** ** OUTPUTS: ** Creates the trace handle. ** Registers the QName and RName with the trace facility. ** ** RETURNS: ** PRTraceHandle ** ** RESTRICTIONS: ** qName is limited to 31 characters. ** rName is limited to 31 characters. ** description is limited to 255 characters. ** */ #define PRTRACE_NAME_MAX 31 #define PRTRACE_DESC_MAX 255 #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_CREATE_TRACE(handle,qName,rName,description)\ (handle) = PR_CreateTrace((qName),(rName),(description)) #else #define PR_CREATE_TRACE(handle,qName,rName,description) #endif NSPR_API(PRTraceHandle) PR_CreateTrace( const char *qName, /* QName for this trace handle */ const char *rName, /* RName for this trace handle */ const char *description /* description for this trace handle */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_DestroyTrace() -- Destroy a trace handle ** ** DESCRIPTION: ** PR_DestroyTrace() removes the referenced trace handle and ** associated QName, RName and description data from the Trace ** Facility. ** ** INPUTS: handle. A PRTraceHandle ** ** OUTPUTS: ** The trace handle is unregistered. ** The QName, RName and description are removed. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_DESTROY_TRACE(handle)\ PR_DestroyTrace((handle)) #else #define PR_DESTROY_TRACE(handle) #endif NSPR_API(void) PR_DestroyTrace( PRTraceHandle handle /* Handle to be destroyed */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_Trace() -- Make a trace entry in the in-memory trace ** ** DESCRIPTION: ** PR_Trace() makes an entry in the in-memory trace buffer for ** the referenced trace handle. The next logically available ** PRTraceEntry is used; when the next trace entry would overflow ** the trace table, the table wraps. ** ** PR_Trace() for a specific trace handle may be disabled by ** calling PR_SetTraceOption() specifying PRTraceDisable for the ** trace handle to be disabled. ** ** INPUTS: ** handle: PRTraceHandle. The trace handle for this trace. ** ** userData[0..7]: unsigned 32bit integers. user supplied data ** that is copied into the PRTraceEntry ** ** OUTPUTS: ** A PRTraceEntry is (conditionally) formatted in the in-memory ** trace buffer. ** ** RETURNS: void. ** ** RESTRICTIONS: ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7)\ PR_Trace((handle),(ud0),(ud1),(ud2),(ud3),(ud4),(ud5),(ud6),(ud7)) #else #define PR_TRACE(handle,ud0,ud1,ud2,ud3,ud4,ud5,ud6,ud7) #endif NSPR_API(void) PR_Trace( PRTraceHandle handle, /* use this trace handle */ PRUint32 userData0, /* User supplied data word 0 */ PRUint32 userData1, /* User supplied data word 1 */ PRUint32 userData2, /* User supplied data word 2 */ PRUint32 userData3, /* User supplied data word 3 */ PRUint32 userData4, /* User supplied data word 4 */ PRUint32 userData5, /* User supplied data word 5 */ PRUint32 userData6, /* User supplied data word 6 */ PRUint32 userData7 /* User supplied data word 7 */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_SetTraceOption() -- Control the Trace Facility ** ** DESCRIPTION: ** PR_SetTraceOption() controls the Trace Facility. Depending on ** command and value, attributes of the Trace Facility may be ** changed. ** ** INPUTS: ** command: An enumerated value in the set of PRTraceOption. ** value: pointer to the data to be set. Type of the data is ** dependent on command; for each value of command, the type ** and meaning of dereferenced value is shown. ** ** PRTraceBufSize: unsigned long: the size of the trace buffer, ** in bytes. ** ** PRTraceEnable: PRTraceHandle. The trace handle to be ** enabled. ** ** PRTraceDisable: PRTraceHandle. The trace handle to be ** disabled. ** ** PRTraceSuspend: void. value must be NULL. All tracing is ** suspended. ** ** PRTraceResume: void. value must be NULL. Tracing for all ** previously enabled, prior to a PRTraceSuspend, is resumed. ** ** PRTraceStopRecording: void. value must be NULL. If recording ** (see: ** PR_RecordTraceEntries()) is being done, ** PRTraceStopRecording causes PR_RecordTraceEntries() to return ** to its caller. If recording is not being done, this function ** has no effect. ** ** PRTraceSuspendRecording: void. Must be NULL. If recording is ** being done, PRTraceSuspendRecording causes further writes to ** the trace file to be suspended. Data in the in-memory ** trace buffer that would ordinarily be written to the ** trace file will not be written. Trace entries will continue ** to be entered in the in-memory buffer. If the Trace Facility ** recording is already in a suspended state, the call has no ** effect. ** ** PRTraceResumeRecording: void. value must be NULL. If ** recording for the Trace Facility has been previously been ** suspended, this causes recording to resume. Recording resumes ** with the next in-memory buffer segment that would be written ** if trace recording had not been suspended. If recording is ** not currently suspended, the call has no effect. ** ** PRTraceLockHandles: void. value must be NULL. Locks the ** trace handle lock. While the trace handle lock is held, ** calls to PR_CreateTrace() will block until the lock is ** released. ** ** PRTraceUnlockHandles: void. value must be NULL. Unlocks the ** trace handle lock. ** ** OUTPUTS: ** The operation of the Trace Facility may be changed. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_SET_TRACE_OPTION(command,value)\ PR_SetTraceOption((command),(value)) #else #define PR_SET_TRACE_OPTION(command,value) #endif NSPR_API(void) PR_SetTraceOption( PRTraceOption command, /* One of the enumerated values */ void *value /* command value or NULL */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetTraceOption() -- Retrieve settings from the Trace Facility ** ** DESCRIPTION: ** PR_GetTraceOption() retrieves the current setting of the ** Trace Facility control depending on command. ** ** ** PRTraceBufSize: unsigned long: the size of the trace buffer, ** in bytes. ** ** ** INPUTS: ** command: one of the enumerated values in PRTraceOptions ** valid for PR_GetTraceOption(). ** ** OUTPUTS: ** dependent on command. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_OPTION(command,value)\ PR_GetTraceOption((command),(value)) #else #define PR_GET_TRACE_OPTION(command,value) #endif NSPR_API(void) PR_GetTraceOption( PRTraceOption command, /* One of the enumerated values */ void *value /* command value or NULL */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetTraceHandleFromName() -- Retrieve an existing ** handle by name. ** ** DESCRIPTION: ** PR_GetTraceHandleFromName() retreives an existing tracehandle ** using the name specified by qName and rName. ** ** INPUTS: ** qName: pointer to string. QName for this trace handle. ** ** rName: pointer to string. RName for this trace handle. ** ** ** OUTPUTS: returned. ** ** RETURNS: ** PRTraceHandle associated with qName and rName or NULL when ** there is no match. ** ** RESTRICTIONS: ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName)\ (handle) = PR_GetTraceHandleFromName((qName),(rName)) #else #define PR_GET_TRACE_HANDLE_FROM_NAME(handle,qName,rName) #endif NSPR_API(PRTraceHandle) PR_GetTraceHandleFromName( const char *qName, /* QName search argument */ const char *rName /* RName search argument */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetTraceNameFromHandle() -- Retreive trace name ** by bandle. ** ** DESCRIPTION: ** PR_GetTraceNameFromHandle() retreives the existing qName, ** rName, and description for the referenced trace handle. ** ** INPUTS: handle: PRTraceHandle. ** ** OUTPUTS: pointers to the Trace Facility's copy of qName, ** rName and description. ... Don't mess with these values. ** They're mine. ** ** RETURNS: void ** ** RESTRICTIONS: ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description)\ PR_GetTraceNameFromHandle((handle),(qName),(rName),(description)) #else #define PR_GET_TRACE_NAME_FROM_HANDLE(handle,qName,rName,description) #endif NSPR_API(void) PR_GetTraceNameFromHandle( PRTraceHandle handle, /* handle as search argument */ const char **qName, /* pointer to associated QName */ const char **rName, /* pointer to associated RName */ const char **description /* pointer to associated description */ ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_FindNextTraceQname() -- Retrieive a QName handle ** iterator. ** ** DESCRIPTION: ** PR_FindNextTraceQname() retreives the first or next trace ** QName handle, depending on the value of handle, from the trace ** database. The PRTraceHandle returned can be used as an ** iterator to traverse the QName handles in the Trace database. ** ** INPUTS: ** handle: When NULL, PR_FindNextQname() returns the first QName ** handle. When a handle is a valid PRTraceHandle previously ** retreived using PR_FindNextQname() the next QName handle is ** retreived. ** ** OUTPUTS: returned. ** ** RETURNS: ** PRTraceHandle or NULL when there are no trace handles. ** ** RESTRICTIONS: ** Iterating thru the trace handles via FindFirst/FindNext ** should be done under protection of the trace handle lock. ** See: PR_SetTraceOption( PRLockTraceHandles ). ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_FIND_NEXT_TRACE_QNAME(next,handle)\ (next) = PR_FindNextTraceQname((handle)) #else #define PR_FIND_NEXT_TRACE_QNAME(next,handle) #endif NSPR_API(PRTraceHandle) PR_FindNextTraceQname( PRTraceHandle handle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_FindNextTraceRname() -- Retrieive an RName handle ** iterator. ** ** DESCRIPTION: ** PR_FindNextTraceRname() retreives the first or next trace ** RName handle, depending on the value of handle, from the trace ** database. The PRTraceHandle returned can be used as an ** iterator to traverse the RName handles in the Trace database. ** ** INPUTS: ** rhandle: When NULL, PR_FindNextRname() returns the first ** RName handle. When a handle is a valid PRTraceHandle ** previously retreived using PR_FindNextRname() the next RName ** handle is retreived. ** qhandle: A valid PRTraceHandle retruned from a previous call ** to PR_FIND_NEXT_TRACE_QNAME(). ** ** OUTPUTS: returned. ** ** RETURNS: ** PRTraceHandle or NULL when there are no trace handles. ** ** RESTRICTIONS: ** Iterating thru the trace handles via FindNext should be done ** under protection of the trace handle lock. See: ( ** PR_SetTraceOption( PRLockTraceHandles ). ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle)\ (next) = PR_FindNextTraceRname((rhandle),(qhandle)) #else #define PR_FIND_NEXT_TRACE_RNAME(next,rhandle,qhandle) #endif NSPR_API(PRTraceHandle) PR_FindNextTraceRname( PRTraceHandle rhandle, PRTraceHandle qhandle ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_RecordTraceEntries() -- Write trace entries to external media ** ** DESCRIPTION: ** PR_RecordTraceEntries() causes entries in the in-memory trace ** buffer to be written to external media. ** ** When PR_RecordTraceEntries() is called from an application ** thread, the function appears to block until another thread ** calls PR_SetTraceOption() with the PRTraceStopRecording ** option. This suggests that PR_RecordTraceEntries() should be ** called from a user supplied thread whose only job is to ** record trace entries. ** ** The environment variable NSPR_TRACE_LOG controls the operation ** of this function. When NSPR_TRACE_LOG is not defined in the ** environment, no recording of trace entries occurs. When ** NSPR_TRACE_LOG is defined, the value of its definition must be ** the filename of the file to receive the trace entry buffer. ** ** PR_RecordTraceEntries() attempts to record the in-memory ** buffer to a file, subject to the setting of the environment ** variable NSPR_TRACE_LOG. It is possible because of system ** load, the thread priority of the recording thread, number of ** active trace records being written over time, and other ** variables that some trace records can be lost. ... In other ** words: don't bet the farm on getting everything. ** ** INPUTS: none ** ** OUTPUTS: none ** ** RETURNS: PR_STATUS ** PR_SUCCESS no errors were found. ** PR_FAILURE errors were found. ** ** RESTRICTIONS: ** Only one thread can call PR_RecordTraceEntries() within a ** process. ** ** On error, PR_RecordTraceEntries() may return prematurely. ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_RECORD_TRACE_ENTRIES()\ PR_RecordTraceEntries() #else #define PR_RECORD_TRACE_ENTRIES() #endif NSPR_API(void) PR_RecordTraceEntries( void ); /* ----------------------------------------------------------------------- ** FUNCTION: PR_GetTraceEntries() -- Retreive trace entries from ** the Trace Facility ** ** DESCRIPTION: ** PR_GetTraceEntries() retreives trace entries from the Trace ** Facility. Up to count trace entries are copied from the Trace ** Facility into buffer. Only those trace entries that have not ** been copied via a previous call to PR_GetTraceEntries() are ** copied. The actual number copied is placed in the PRInt32 ** variable pointed to by found. ** ** If more than count trace entries have entered the Trace ** Facility since the last call to PR_GetTraceEntries() ** a lost data condition is returned. In this case, the most ** recent count trace entries are copied into buffer and found is ** set to count. ** ** INPUTS: ** count. The number of trace entries to be copied into buffer. ** ** ** OUTPUTS: ** buffer. An array of PRTraceEntries. The buffer is supplied ** by the caller. ** ** found: 32bit signed integer. The number of PRTraceEntries ** actually copied. found is always less than or equal to count. ** ** RETURNS: ** zero when there is no lost data. ** non-zero when some PRTraceEntries have been lost. ** ** RESTRICTIONS: ** This is a real performance pig. The copy out operation is bad ** enough, but depending on then frequency of calls to the ** function, serious performance impact to the operating ** application may be realized. ... YMMV. ** */ #if defined (DEBUG) || defined (FORCE_NSPR_TRACE) #define PR_GET_TRACE_ENTRIES(buffer,count,found)\ PR_GetTraceEntries((buffer),(count),(found)) #else #define PR_GET_TRACE_ENTRIES(buffer,count,found) #endif NSPR_API(PRIntn) PR_GetTraceEntries( PRTraceEntry *buffer, /* where to write output */ PRInt32 count, /* number to get */ PRInt32 *found /* number you got */ ); PR_END_EXTERN_C #endif /* prtrace_h___ */ nspr-4.11/nspr/pr/include/prtypes.h0000644000000000000000000005044112623070344015461 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prtypes.h ** Description: Definitions of NSPR's basic types ** ** Prototypes and macros used to make up for deficiencies that we have found ** in ANSI environments. ** ** Since we do not wrap and all the other standard headers, authors ** of portable code will not know in general that they need these definitions. ** Instead of requiring these authors to find the dependent uses in their code ** and take the following steps only in those C files, we take steps once here ** for all C files. **/ #ifndef prtypes_h___ #define prtypes_h___ #ifdef MDCPUCFG #include MDCPUCFG #else #include "prcpucfg.h" #endif #include /*********************************************************************** ** MACROS: PR_EXTERN ** PR_IMPLEMENT ** DESCRIPTION: ** These are only for externally visible routines and globals. For ** internal routines, just use "extern" for type checking and that ** will not export internal cross-file or forward-declared symbols. ** Define a macro for declaring procedures return types. We use this to ** deal with windoze specific type hackery for DLL definitions. Use ** PR_EXTERN when the prototype for the method is declared. Use ** PR_IMPLEMENT for the implementation of the method. ** ** Example: ** in dowhim.h ** PR_EXTERN( void ) DoWhatIMean( void ); ** in dowhim.c ** PR_IMPLEMENT( void ) DoWhatIMean( void ) { return; } ** ** ***********************************************************************/ #if defined(WIN32) #define PR_EXPORT(__type) extern __declspec(dllexport) __type #define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type #define PR_IMPORT(__type) __declspec(dllimport) __type #define PR_IMPORT_DATA(__type) __declspec(dllimport) __type #define PR_EXTERN(__type) extern __declspec(dllexport) __type #define PR_IMPLEMENT(__type) __declspec(dllexport) __type #define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type #define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type #define PR_CALLBACK #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x #elif defined(XP_BEOS) #define PR_EXPORT(__type) extern __declspec(dllexport) __type #define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type #define PR_IMPORT(__type) extern __declspec(dllexport) __type #define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type #define PR_EXTERN(__type) extern __declspec(dllexport) __type #define PR_IMPLEMENT(__type) __declspec(dllexport) __type #define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type #define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type #define PR_CALLBACK #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x #elif defined(XP_OS2) && defined(__declspec) #define PR_EXPORT(__type) extern __declspec(dllexport) __type #define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type #define PR_IMPORT(__type) extern __declspec(dllimport) __type #define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type #define PR_EXTERN(__type) extern __declspec(dllexport) __type #define PR_IMPLEMENT(__type) __declspec(dllexport) __type #define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type #define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type #define PR_CALLBACK #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x #elif defined(SYMBIAN) #define PR_EXPORT(__type) extern __declspec(dllexport) __type #define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type #ifdef __WINS__ #define PR_IMPORT(__type) extern __declspec(dllexport) __type #define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type #else #define PR_IMPORT(__type) extern __declspec(dllimport) __type #define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type #endif #define PR_EXTERN(__type) extern __type #define PR_IMPLEMENT(__type) __type #define PR_EXTERN_DATA(__type) extern __type #define PR_IMPLEMENT_DATA(__type) __type #define PR_CALLBACK #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x #else /* Unix */ /* GCC 3.3 and later support the visibility attribute. */ #if (__GNUC__ >= 4) || \ (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) #define PR_VISIBILITY_DEFAULT __attribute__((visibility("default"))) #else #define PR_VISIBILITY_DEFAULT #endif #define PR_EXPORT(__type) extern PR_VISIBILITY_DEFAULT __type #define PR_EXPORT_DATA(__type) extern PR_VISIBILITY_DEFAULT __type #define PR_IMPORT(__type) extern PR_VISIBILITY_DEFAULT __type #define PR_IMPORT_DATA(__type) extern PR_VISIBILITY_DEFAULT __type #define PR_EXTERN(__type) extern PR_VISIBILITY_DEFAULT __type #define PR_IMPLEMENT(__type) PR_VISIBILITY_DEFAULT __type #define PR_EXTERN_DATA(__type) extern PR_VISIBILITY_DEFAULT __type #define PR_IMPLEMENT_DATA(__type) PR_VISIBILITY_DEFAULT __type #define PR_CALLBACK #define PR_CALLBACK_DECL #define PR_STATIC_CALLBACK(__x) static __x #endif #if defined(_NSPR_BUILD_) #define NSPR_API(__type) PR_EXPORT(__type) #define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type) #else #define NSPR_API(__type) PR_IMPORT(__type) #define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type) #endif /*********************************************************************** ** MACROS: PR_BEGIN_MACRO ** PR_END_MACRO ** DESCRIPTION: ** Macro body brackets so that macros with compound statement definitions ** behave syntactically more like functions when called. ***********************************************************************/ #define PR_BEGIN_MACRO do { #define PR_END_MACRO } while (0) /*********************************************************************** ** MACROS: PR_BEGIN_EXTERN_C ** PR_END_EXTERN_C ** DESCRIPTION: ** Macro shorthands for conditional C++ extern block delimiters. ***********************************************************************/ #ifdef __cplusplus #define PR_BEGIN_EXTERN_C extern "C" { #define PR_END_EXTERN_C } #else #define PR_BEGIN_EXTERN_C #define PR_END_EXTERN_C #endif /*********************************************************************** ** MACROS: PR_BIT ** PR_BITMASK ** DESCRIPTION: ** Bit masking macros. XXX n must be <= 31 to be portable ***********************************************************************/ #define PR_BIT(n) ((PRUint32)1 << (n)) #define PR_BITMASK(n) (PR_BIT(n) - 1) /*********************************************************************** ** MACROS: PR_ROUNDUP ** PR_MIN ** PR_MAX ** PR_ABS ** DESCRIPTION: ** Commonly used macros for operations on compatible types. ***********************************************************************/ #define PR_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) #define PR_MIN(x,y) ((x)<(y)?(x):(y)) #define PR_MAX(x,y) ((x)>(y)?(x):(y)) #define PR_ABS(x) ((x)<0?-(x):(x)) /*********************************************************************** ** MACROS: PR_ARRAY_SIZE ** DESCRIPTION: ** The number of elements in an array. ***********************************************************************/ #define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) PR_BEGIN_EXTERN_C /* ** Starting in NSPR 4.9.5, NSPR's exact-width integer types should match ** the exact-width integer types defined in . This allows sloppy ** code to use PRInt{N} and int{N}_t interchangeably. ** ** The 8-bit and 16-bit integer types can only be defined using char and ** short. All platforms define the 32-bit integer types using int. So only ** the 64-bit integer types could be defined differently. ** ** NSPR's original strategy was to use the "shortest" 64-bit integer type: ** if long is 64-bit, then prefer it over long long. This strategy is also ** used by Linux/glibc, FreeBSD, and NetBSD. ** ** Other platforms use a different strategy: simply define the 64-bit ** integer types using long long. We define the PR_ALTERNATE_INT64_TYPEDEF ** macro on these platforms. Note that PR_ALTERNATE_INT64_TYPEDEF is for ** internal use by NSPR headers only. Do not define or test this macro in ** your code. ** ** NOTE: NSPR can't use because C99 requires C++ code to define ** __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS to make all the macros ** defined in available. This strange requirement is gone in ** C11. When most platforms ignore this C99 requirement, NSPR will be able ** to use . A patch to do that is in NSPR bug 634793. */ #if defined(__APPLE__) || defined(__ANDROID__) || defined(__OpenBSD__) #define PR_ALTERNATE_INT64_TYPEDEF #endif /************************************************************************ ** TYPES: PRUint8 ** PRInt8 ** DESCRIPTION: ** The int8 types are known to be 8 bits each. There is no type that ** is equivalent to a plain "char". ************************************************************************/ #if PR_BYTES_PER_BYTE == 1 typedef unsigned char PRUint8; /* ** Some cfront-based C++ compilers do not like 'signed char' and ** issue the warning message: ** warning: "signed" not implemented (ignored) ** For these compilers, we have to define PRInt8 as plain 'char'. ** Make sure that plain 'char' is indeed signed under these compilers. */ #if (defined(HPUX) && defined(__cplusplus) \ && !defined(__GNUC__) && __cplusplus < 199707L) \ || (defined(SCO) && defined(__cplusplus) \ && !defined(__GNUC__) && __cplusplus == 1L) typedef char PRInt8; #else typedef signed char PRInt8; #endif #else #error No suitable type for PRInt8/PRUint8 #endif /************************************************************************ * MACROS: PR_INT8_MAX * PR_INT8_MIN * PR_UINT8_MAX * DESCRIPTION: * The maximum and minimum values of a PRInt8 or PRUint8. ************************************************************************/ #define PR_INT8_MAX 127 #define PR_INT8_MIN (-128) #define PR_UINT8_MAX 255U /************************************************************************ ** TYPES: PRUint16 ** PRInt16 ** DESCRIPTION: ** The int16 types are known to be 16 bits each. ************************************************************************/ #if PR_BYTES_PER_SHORT == 2 typedef unsigned short PRUint16; typedef short PRInt16; #else #error No suitable type for PRInt16/PRUint16 #endif /************************************************************************ * MACROS: PR_INT16_MAX * PR_INT16_MIN * PR_UINT16_MAX * DESCRIPTION: * The maximum and minimum values of a PRInt16 or PRUint16. ************************************************************************/ #define PR_INT16_MAX 32767 #define PR_INT16_MIN (-32768) #define PR_UINT16_MAX 65535U /************************************************************************ ** TYPES: PRUint32 ** PRInt32 ** DESCRIPTION: ** The int32 types are known to be 32 bits each. ************************************************************************/ #if PR_BYTES_PER_INT == 4 typedef unsigned int PRUint32; typedef int PRInt32; #define PR_INT32(x) x #define PR_UINT32(x) x ## U #elif PR_BYTES_PER_LONG == 4 typedef unsigned long PRUint32; typedef long PRInt32; #define PR_INT32(x) x ## L #define PR_UINT32(x) x ## UL #else #error No suitable type for PRInt32/PRUint32 #endif /************************************************************************ * MACROS: PR_INT32_MAX * PR_INT32_MIN * PR_UINT32_MAX * DESCRIPTION: * The maximum and minimum values of a PRInt32 or PRUint32. ************************************************************************/ #define PR_INT32_MAX PR_INT32(2147483647) #define PR_INT32_MIN (-PR_INT32_MAX - 1) #define PR_UINT32_MAX PR_UINT32(4294967295) /************************************************************************ ** TYPES: PRUint64 ** PRInt64 ** DESCRIPTION: ** The int64 types are known to be 64 bits each. Care must be used when ** declaring variables of type PRUint64 or PRInt64. Different hardware ** architectures and even different compilers have varying support for ** 64 bit values. The only guaranteed portability requires the use of ** the LL_ macros (see prlong.h). ** ** MACROS: PR_INT64 ** PR_UINT64 ** DESCRIPTION: ** The PR_INT64 and PR_UINT64 macros provide a portable way for ** specifying 64-bit integer constants. They can only be used if ** PRInt64 and PRUint64 are defined as compiler-supported 64-bit ** integer types (i.e., if HAVE_LONG_LONG is defined, which is true ** for all the supported compilers topday). If PRInt64 and PRUint64 ** are defined as structs, the LL_INIT macro defined in prlong.h has ** to be used. ** ** MACROS: PR_INT64_MAX ** PR_INT64_MIN ** PR_UINT64_MAX ** DESCRIPTION: ** The maximum and minimum values of a PRInt64 or PRUint64. ************************************************************************/ #ifdef HAVE_LONG_LONG /* Keep this in sync with prlong.h. */ #if PR_BYTES_PER_LONG == 8 && !defined(PR_ALTERNATE_INT64_TYPEDEF) typedef long PRInt64; typedef unsigned long PRUint64; #define PR_INT64(x) x ## L #define PR_UINT64(x) x ## UL #elif defined(WIN32) && !defined(__GNUC__) typedef __int64 PRInt64; typedef unsigned __int64 PRUint64; #define PR_INT64(x) x ## i64 #define PR_UINT64(x) x ## ui64 #else typedef long long PRInt64; typedef unsigned long long PRUint64; #define PR_INT64(x) x ## LL #define PR_UINT64(x) x ## ULL #endif /* PR_BYTES_PER_LONG == 8 */ #define PR_INT64_MAX PR_INT64(0x7fffffffffffffff) #define PR_INT64_MIN (-PR_INT64_MAX - 1) #define PR_UINT64_MAX PR_UINT64(-1) #else /* !HAVE_LONG_LONG */ typedef struct { #ifdef IS_LITTLE_ENDIAN PRUint32 lo, hi; #else PRUint32 hi, lo; #endif } PRInt64; typedef PRInt64 PRUint64; #define PR_INT64_MAX (PRInt64){0x7fffffff, 0xffffffff} #define PR_INT64_MIN (PRInt64){0xffffffff, 0xffffffff} #define PR_UINT64_MAX (PRUint64){0xffffffff, 0xffffffff} #endif /* !HAVE_LONG_LONG */ /************************************************************************ ** TYPES: PRUintn ** PRIntn ** DESCRIPTION: ** The PRIntn types are most appropriate for automatic variables. They are ** guaranteed to be at least 16 bits, though various architectures may ** define them to be wider (e.g., 32 or even 64 bits). These types are ** never valid for fields of a structure. ************************************************************************/ #if PR_BYTES_PER_INT >= 2 typedef int PRIntn; typedef unsigned int PRUintn; #else #error 'sizeof(int)' not sufficient for platform use #endif /************************************************************************ ** TYPES: PRFloat64 ** DESCRIPTION: ** NSPR's floating point type is always 64 bits. ************************************************************************/ typedef double PRFloat64; /************************************************************************ ** TYPES: PRSize ** DESCRIPTION: ** A type for representing the size of objects. ************************************************************************/ typedef size_t PRSize; /************************************************************************ ** TYPES: PROffset32, PROffset64 ** DESCRIPTION: ** A type for representing byte offsets from some location. ************************************************************************/ typedef PRInt32 PROffset32; typedef PRInt64 PROffset64; /************************************************************************ ** TYPES: PRPtrDiff ** DESCRIPTION: ** A type for pointer difference. Variables of this type are suitable ** for storing a pointer or pointer subtraction. ************************************************************************/ typedef ptrdiff_t PRPtrdiff; /************************************************************************ ** TYPES: PRUptrdiff ** DESCRIPTION: ** A type for pointer difference. Variables of this type are suitable ** for storing a pointer or pointer sutraction. ************************************************************************/ #ifdef _WIN64 typedef PRUint64 PRUptrdiff; #else typedef unsigned long PRUptrdiff; #endif /************************************************************************ ** TYPES: PRBool ** DESCRIPTION: ** Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE ** for clarity of target type in assignments and actual arguments. Use ** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans ** just as you would C int-valued conditions. ************************************************************************/ typedef PRIntn PRBool; #define PR_TRUE 1 #define PR_FALSE 0 /************************************************************************ ** TYPES: PRPackedBool ** DESCRIPTION: ** Use PRPackedBool within structs where bitfields are not desirable ** but minimum and consistant overhead matters. ************************************************************************/ typedef PRUint8 PRPackedBool; /* ** Status code used by some routines that have a single point of failure or ** special status return. */ typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; #ifndef __PRUNICHAR__ #define __PRUNICHAR__ #ifdef WIN32 typedef wchar_t PRUnichar; #else typedef PRUint16 PRUnichar; #endif #endif /* ** WARNING: The undocumented data types PRWord and PRUword are ** only used in the garbage collection and arena code. Do not ** use PRWord and PRUword in new code. ** ** A PRWord is an integer that is the same size as a void*. ** It implements the notion of a "word" in the Java Virtual ** Machine. (See Sec. 3.4 "Words", The Java Virtual Machine ** Specification, Addison-Wesley, September 1996. ** http://java.sun.com/docs/books/vmspec/index.html.) */ #ifdef _WIN64 typedef PRInt64 PRWord; typedef PRUint64 PRUword; #else typedef long PRWord; typedef unsigned long PRUword; #endif /* * PR_PRETEND_NORETURN, specified at the end of a function declaration, * indicates that for the purposes of static analysis, this function does not * return. (The function definition does not need to be annotated.) * * void PR_Assert(const char *s, const char *file, PRIntn ln) * PR_PRETEND_NORETURN; * * Some static analyzers, like scan-build from clang, can use this information * to eliminate false positives. From the upstream documentation of * scan-build: * This attribute is useful for annotating assertion handlers that actually * can return, but for the purpose of using the analyzer we want to pretend * that such functions do not return. */ #ifdef __clang_analyzer__ #if __has_extension(attribute_analyzer_noreturn) #define PR_PRETEND_NORETURN __attribute__((analyzer_noreturn)) #endif #endif #ifndef PR_PRETEND_NORETURN #define PR_PRETEND_NORETURN /* no support */ #endif #if defined(NO_NSPR_10_SUPPORT) #else /********* ???????????????? FIX ME ??????????????????????????? *****/ /********************** Some old definitions until pr=>ds transition is done ***/ /********************** Also, we are still using NSPR 1.0. GC ******************/ /* ** Fundamental NSPR macros, used nearly everywhere. */ #define PR_PUBLIC_API PR_IMPLEMENT /* ** Macro body brackets so that macros with compound statement definitions ** behave syntactically more like functions when called. */ #define NSPR_BEGIN_MACRO do { #define NSPR_END_MACRO } while (0) /* ** Macro shorthands for conditional C++ extern block delimiters. */ #ifdef NSPR_BEGIN_EXTERN_C #undef NSPR_BEGIN_EXTERN_C #endif #ifdef NSPR_END_EXTERN_C #undef NSPR_END_EXTERN_C #endif #ifdef __cplusplus #define NSPR_BEGIN_EXTERN_C extern "C" { #define NSPR_END_EXTERN_C } #else #define NSPR_BEGIN_EXTERN_C #define NSPR_END_EXTERN_C #endif #include "obsolete/protypes.h" /********* ????????????? End Fix me ?????????????????????????????? *****/ #endif /* NO_NSPR_10_SUPPORT */ /* ** Compile-time assert. "condition" must be a constant expression. ** The macro can be used only in places where an "extern" declaration is ** allowed. */ #define PR_STATIC_ASSERT(condition) \ extern void pr_static_assert(int arg[(condition) ? 1 : -1]) PR_END_EXTERN_C #endif /* prtypes_h___ */ nspr-4.11/nspr/pr/include/prvrsion.h0000755000000000000000000000674712623070344015652 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* author: jstewart */ #if defined(_PRVERSION_H) #else #define _PRVERSION_H #include "prtypes.h" PR_BEGIN_EXTERN_C /* All components participating in the PR version protocol must expose * a structure and a function. The structure is defined below and named * according to the naming conventions outlined further below. The function * is called libVersionPoint and returns a pointer to this structure. */ /* on NT, always pack the structure the same. */ #ifdef _WIN32 #pragma pack(push, 8) #endif typedef struct { /* * The first field defines which version of this structure is in use. * At this time, only version 2 is specified. If this value is not * 2, you must read no further into the structure. */ PRInt32 version; /* for Version 2, this is the body format. */ PRInt64 buildTime; /* 64 bits - usecs since midnight, 1/1/1970 */ char * buildTimeString;/* a human readable version of the time */ PRUint8 vMajor; /* Major version of this component */ PRUint8 vMinor; /* Minor version of this component */ PRUint8 vPatch; /* Patch level of this component */ PRBool beta; /* true if this is a beta component */ PRBool debug; /* true if this is a debug component */ PRBool special; /* true if this component is a special build */ char * filename; /* The original filename */ char * description; /* description of this component */ char * security; /* level of security in this component */ char * copyright; /* The copyright for this file */ char * comment; /* free form field for misc usage */ char * specialString; /* the special variant for this build */ } PRVersionDescription; /* on NT, restore the previous packing */ #ifdef _WIN32 #pragma pack(pop) #endif /* * All components must define an entrypoint named libVersionPoint which * is of type versionEntryPointType. * * For example, for a library named libfoo, we would have: * * PRVersionDescription prVersionDescription_libfoo = * { * ... * }; * * PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) * { * return &prVersionDescription_libfoo; * } */ typedef const PRVersionDescription *(*versionEntryPointType)(void); /* * Where you declare your libVersionPoint, do it like this: * PR_IMPLEMENT(const PRVersionDescription *) libVersionPoint(void) { * fill it in... * } */ /* * NAMING CONVENTION FOR struct * * all components should also expose a static PRVersionDescription * The name of the struct should be calculated as follows: * Take the value of filename. (If filename is not specified, calculate * a short, unique string.) Convert all non-alphanumeric characters * to '_'. To this, prepend "PRVersionDescription_". Thus for libfoo.so, * the symbol name is "PRVersionDescription_libfoo_so". * so the file should have * PRVersionDescription PRVersionDescription_libfoo_so { fill it in }; * on NT, this file should be declspec export. */ PR_END_EXTERN_C #endif /* defined(_PRVERSION_H) */ /* prvrsion.h */ nspr-4.11/nspr/pr/include/prwin16.h0000644000000000000000000001357112623070344015264 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef prwin16_h___ #define prwin16_h___ /* ** Condition use of this header on platform. */ #if (defined(XP_PC) && !defined(_WIN32) && !defined(XP_OS2) && defined(MOZILLA_CLIENT)) || defined(WIN16) #include PR_BEGIN_EXTERN_C /* ** Win16 stdio special case. ** To get stdio to work for Win16, all calls to printf() and related ** things must be called from the environment of the .EXE; calls to ** printf() from the .DLL send output to the bit-bucket. ** ** To make sure that PR_fprintf(), and related functions, work correctly, ** the actual stream I/O to stdout, stderr, stdin must be done in the ** .EXE. To do this, a hack is placed in _MD_Write() such that the ** fd for stdio handles results in a call to the .EXE. ** ** file w16stdio.c contains the functions that get called from NSPR ** to do the actual I/O. w16stdio.o must be statically linked with ** any application needing stdio for Win16. ** ** The address of these functions must be made available to the .DLL ** so he can call back to the .EXE. To do this, function ** PR_MD_RegisterW16StdioCallbacks() is called from the .EXE. ** The arguments are the functions defined in w16stdio.c ** At runtime, MD_Write() calls the registered functions, if any ** were registered. ** ** prinit.h contains a macro PR_STDIO_INIT() that calls the registration ** function for Win16; For other platforms, the macro is a No-Op. ** ** Note that stdio is not operational at all on Win16 GUI applications. ** This special case exists to provide stdio capability from the NSPR ** .DLL for command line applications only. NSPR's test cases are ** almost exclusively command line applications. ** ** See also: w16io.c, w16stdio.c */ typedef PRInt32 (PR_CALLBACK *PRStdinRead)( void *buf, PRInt32 amount); typedef PRInt32 (PR_CALLBACK *PRStdoutWrite)( void *buf, PRInt32 amount); typedef PRInt32 (PR_CALLBACK *PRStderrWrite)( void *buf, PRInt32 amount); NSPR_API(PRStatus) PR_MD_RegisterW16StdioCallbacks( PRStdinRead inReadf, /* i: function pointer for stdin read */ PRStdoutWrite outWritef, /* i: function pointer for stdout write */ PRStderrWrite errWritef /* i: function pointer for stderr write */ ); NSPR_API(PRInt32) _PL_W16StdioWrite( void *buf, PRInt32 amount ); NSPR_API(PRInt32) _PL_W16StdioRead( void *buf, PRInt32 amount ); #define PR_STDIO_INIT() PR_MD_RegisterW16StdioCallbacks( \ _PL_W16StdioRead, _PL_W16StdioWrite, _PL_W16StdioWrite ); \ PR_INIT_CALLBACKS(); /* ** Win16 hackery. ** */ struct PRMethodCallbackStr { int (PR_CALLBACK *auxOutput)(const char *outputString); size_t (PR_CALLBACK *strftime)(char *s, size_t len, const char *fmt, const struct tm *p); void * (PR_CALLBACK *malloc)( size_t size ); void * (PR_CALLBACK *calloc)(size_t n, size_t size ); void * (PR_CALLBACK *realloc)( void* old_blk, size_t size ); void (PR_CALLBACK *free)( void *ptr ); void * (PR_CALLBACK *getenv)( const char *name); int (PR_CALLBACK *putenv)( const char *assoc); /* void * (PR_CALLBACK *perror)( const char *prefix ); */ }; NSPR_API(void) PR_MDRegisterCallbacks(struct PRMethodCallbackStr *); int PR_CALLBACK _PL_W16CallBackPuts( const char *outputString ); size_t PR_CALLBACK _PL_W16CallBackStrftime( char *s, size_t len, const char *fmt, const struct tm *p ); void * PR_CALLBACK _PL_W16CallBackMalloc( size_t size ); void * PR_CALLBACK _PL_W16CallBackCalloc( size_t n, size_t size ); void * PR_CALLBACK _PL_W16CallBackRealloc( void *old_blk, size_t size ); void PR_CALLBACK _PL_W16CallBackFree( void *ptr ); void * PR_CALLBACK _PL_W16CallBackGetenv( const char *name ); int PR_CALLBACK _PL_W16CallBackPutenv( const char *assoc ); /* ** Hackery! ** ** These functions are provided as static link points. ** This is to satisfy the quick port of Gromit to NSPR 2.0 ** ... Don't do this! ... alas, It may never go away. ** */ NSPR_API(int) PR_MD_printf(const char *, ...); NSPR_API(void) PR_MD_exit(int); NSPR_API(size_t) PR_MD_strftime(char *, size_t, const char *, const struct tm *); NSPR_API(int) PR_MD_sscanf(const char *, const char *, ...); NSPR_API(void*) PR_MD_malloc( size_t size ); NSPR_API(void*) PR_MD_calloc( size_t n, size_t size ); NSPR_API(void*) PR_MD_realloc( void* old_blk, size_t size ); NSPR_API(void) PR_MD_free( void *ptr ); NSPR_API(char*) PR_MD_getenv( const char *name ); NSPR_API(int) PR_MD_putenv( const char *assoc ); NSPR_API(int) PR_MD_fprintf(FILE *fPtr, const char *fmt, ...); #define PR_INIT_CALLBACKS() \ { \ static struct PRMethodCallbackStr cbf = { \ _PL_W16CallBackPuts, \ _PL_W16CallBackStrftime, \ _PL_W16CallBackMalloc, \ _PL_W16CallBackCalloc, \ _PL_W16CallBackRealloc, \ _PL_W16CallBackFree, \ _PL_W16CallBackGetenv, \ _PL_W16CallBackPutenv, \ }; \ PR_MDRegisterCallbacks( &cbf ); \ } /* ** Get the exception context for Win16 MFC applications threads */ NSPR_API(void *) PR_W16GetExceptionContext(void); /* ** Set the exception context for Win16 MFC applications threads */ NSPR_API(void) PR_W16SetExceptionContext(void *context); PR_END_EXTERN_C #else /* ** For platforms other than Win16, define ** PR_STDIO_INIT() as a No-Op. */ #define PR_STDIO_INIT() #endif /* WIN16 || MOZILLA_CLIENT */ #endif /* prwin16_h___ */ nspr-4.11/nspr/pr/src/.cvsignore0000644000000000000000000000002312623070344014735 0ustar 00000000000000Makefile _pr_bld.h nspr-4.11/nspr/pr/src/Makefile.in0000644000000000000000000002165512623070344015020 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk DIRS = io linking malloc md memory misc threads ifeq ($(USE_PTHREADS), 1) DIRS += pthreads endif ifeq ($(USE_BTHREADS), 1) DIRS += bthreads endif ifeq ($(USE_CPLUS), 1) DIRS += cplus endif # # Define platform-dependent OS_LIBS # ifeq ($(OS_ARCH),SunOS) MAPFILE = $(OBJDIR)/nsprmap.sun GARBAGE += $(MAPFILE) ifdef NS_USE_GCC ifdef GCC_USE_GNU_LD MKSHLIB += -Wl,--version-script,$(MAPFILE) else MKSHLIB += -Wl,-M,$(MAPFILE) endif else MKSHLIB += -M $(MAPFILE) endif # # In Solaris 2.6 or earlier, -lrt is called -lposix4. # LIBRT_TEST=$(firstword $(sort 5.7 $(OS_RELEASE))) ifeq (5.7, $(LIBRT_TEST)) LIBRT=-lrt else LIBRT=-lposix4 endif ifdef USE_PTHREADS OS_LIBS = -lpthread ${LIBRT} -lsocket -lnsl -ldl -lc else OS_LIBS = -lsocket -lnsl -ldl -lc endif # USE_PTHREADS ifeq ($(CPU_ARCH),sparc) ifndef USE_64 DSO_LDOPTS += -Wl,-f,\$$ORIGIN/cpu/\$$ISALIST/lib$(ULTRASPARC_LIBRARY)$(LIBRARY_VERSION).so endif endif # sparc endif # SunOS ifeq ($(OS_ARCH), IRIX) ifeq ($(USE_PTHREADS), 1) OS_LIBS = -lpthread endif OS_LIBS += -lc endif ifeq ($(OS_ARCH),AIX) DSO_LDOPTS += -binitfini::_PR_Fini OS_LIBS = -lodm -lcfg ifeq ($(CLASSIC_NSPR),1) ifeq ($(OS_RELEASE),4.1) OS_LIBS += -lsvld -lc else OS_LIBS += -ldl -lc endif else ifeq ($(OS_RELEASE),4.1) OS_LIBS += -lpthreads -lsvld -lC_r -lC -lc_r -lm /usr/lib/libc.a else OS_LIBS += -lpthreads -ldl -lC_r -lC -lc_r -lm /usr/lib/libc.a endif endif endif # On AIX, we override malloc in non-pthread versions. On AIX 4.2 or # above, this requires that we use the rtl-enabled version of libc.a. ifeq ($(OS_ARCH),AIX) ifneq (,$(filter-out 3.2 4.1,$(OS_RELEASE))) ifneq ($(USE_PTHREADS),1) BUILD_AIX_RTL_LIBC = 1 AIX_RTL_LIBC = $(OBJDIR)/libc.a endif endif endif ifeq ($(OS_ARCH),OS2) MAPFILE = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).def ADD_TO_DEF_FILE = cat $(srcdir)/os2extra.def >> $(MAPFILE) GARBAGE += $(MAPFILE) MKSHLIB += $(MAPFILE) endif ifeq ($(OS_ARCH),OSF1) ifeq ($(USE_PTHREADS), 1) OS_LIBS = -lpthread -lrt endif ifneq ($(OS_RELEASE),V2.0) OS_LIBS += -lc_r endif endif # Linux, GNU/Hurd, and GNU/kFreeBSD systems ifneq (,$(filter Linux GNU%,$(OS_ARCH))) ifeq ($(USE_PTHREADS), 1) ifeq ($(OS_TARGET),Android) # Android has no libpthread.so in NDK OS_LIBS = -ldl else OS_LIBS = -lpthread -ldl endif else OS_LIBS = -ldl endif ifneq ($(OS_TARGET),Android) # Android has no librt - realtime functions are in libc OS_LIBS += -lrt endif endif ifeq ($(OS_ARCH),HP-UX) ifeq ($(USE_PTHREADS), 1) ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE))) OS_LIBS = -ldce else OS_LIBS = -lpthread -lrt endif endif ifeq ($(PTHREADS_USER), 1) OS_LIBS = -lpthread endif ifeq ($(basename $(OS_RELEASE)),A.09) OS_LIBS += -ldld -L/lib/pa1.1 -lm else OS_LIBS += -ldld -lm -lc endif ifneq ($(OS_TEST),ia64) ifndef USE_64 DSO_LDOPTS += +I PR_HPUX10xInit endif endif endif ifeq ($(OS_ARCH),UNIXWARE) OS_LIBS = -lsocket -lc endif ifeq ($(OS_ARCH),WINNT) ifdef NS_USE_GCC OS_LIBS = -ladvapi32 -lws2_32 -lmswsock -lwinmm else OS_LIBS = advapi32.lib ws2_32.lib mswsock.lib winmm.lib endif endif ifeq ($(OS_ARCH),WINCE) OS_LIBS = ws2.lib endif ifeq ($(OS_TARGET),Android) OS_LIBS += -llog endif ifeq ($(OS_TARGET),MacOSX) OS_LIBS = -framework CoreServices -framework CoreFoundation endif EXTRA_LIBS += $(OS_LIBS) # # Define platform-dependent OBJS # OBJS = \ $(OBJDIR)/prvrsion.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prfdcach.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmwait.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmapopt.$(OBJ_SUFFIX) \ io/$(OBJDIR)/priometh.$(OBJ_SUFFIX) \ io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prlayer.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prlog.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prmmap.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prpolevt.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prprf.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prscanf.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prstdio.$(OBJ_SUFFIX) \ threads/$(OBJDIR)/prcmon.$(OBJ_SUFFIX) \ threads/$(OBJDIR)/prrwlock.$(OBJ_SUFFIX) \ threads/$(OBJDIR)/prtpd.$(OBJ_SUFFIX) \ linking/$(OBJDIR)/prlink.$(OBJ_SUFFIX) \ malloc/$(OBJDIR)/prmalloc.$(OBJ_SUFFIX) \ malloc/$(OBJDIR)/prmem.$(OBJ_SUFFIX) \ md/$(OBJDIR)/prosdep.$(OBJ_SUFFIX) \ memory/$(OBJDIR)/prshm.$(OBJ_SUFFIX) \ memory/$(OBJDIR)/prshma.$(OBJ_SUFFIX) \ memory/$(OBJDIR)/prseg.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/pralarm.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/pratom.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prcountr.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prdtoa.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prenv.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prerr.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prerror.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prerrortable.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prinit.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prinrval.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/pripc.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prlog2.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prlong.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prnetdb.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/praton.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prolock.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prrng.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prsystem.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prthinfo.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prtpool.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prtrace.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/prtime.$(OBJ_SUFFIX) ifdef USE_PTHREADS OBJS += \ pthreads/$(OBJDIR)/ptsynch.$(OBJ_SUFFIX) \ pthreads/$(OBJDIR)/ptio.$(OBJ_SUFFIX) \ pthreads/$(OBJDIR)/ptthread.$(OBJ_SUFFIX) \ pthreads/$(OBJDIR)/ptmisc.$(OBJ_SUFFIX) else OBJS += \ io/$(OBJDIR)/prdir.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prfile.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prio.$(OBJ_SUFFIX) \ io/$(OBJDIR)/prsocket.$(OBJ_SUFFIX) \ misc/$(OBJDIR)/pripcsem.$(OBJ_SUFFIX) ifndef USE_BTHREADS OBJS += \ threads/$(OBJDIR)/prcthr.$(OBJ_SUFFIX) \ threads/$(OBJDIR)/prdump.$(OBJ_SUFFIX) \ threads/$(OBJDIR)/prmon.$(OBJ_SUFFIX) \ threads/$(OBJDIR)/prsem.$(OBJ_SUFFIX) \ threads/combined/$(OBJDIR)/prucpu.$(OBJ_SUFFIX) \ threads/combined/$(OBJDIR)/prucv.$(OBJ_SUFFIX) \ threads/combined/$(OBJDIR)/prulock.$(OBJ_SUFFIX) \ threads/combined/$(OBJDIR)/prustack.$(OBJ_SUFFIX) \ threads/combined/$(OBJDIR)/pruthr.$(OBJ_SUFFIX) endif endif ifeq ($(USE_CPLUS), 1) OBJS += \ cplus/$(OBJDIR)/rcbase.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rccv.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rcfileio.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rcinrval.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rcio.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rclock.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rcnetdb.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rcnetio.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rcthread.$(OBJ_SUFFIX) \ cplus/$(OBJDIR)/rctime.$(OBJ_SUFFIX) endif ifeq ($(OS_ARCH), WINNT) RES=$(OBJDIR)/nspr.res RESNAME=nspr.rc endif # WINNT include $(srcdir)/md/$(PR_MD_ARCH_DIR)/objs.mk ifdef USE_BTHREADS include $(srcdir)/bthreads/objs.mk endif LIBRARY_NAME = nspr LIBRARY_VERSION = $(MOD_MAJOR_VERSION) RELEASE_LIBS = $(TARGETS) include $(topsrcdir)/config/rules.mk ifeq ($(BUILD_AIX_RTL_LIBC),1) TARGETS += $(AIX_RTL_LIBC) # XXX is this a shared library? endif # # Version information generation (begin) # ECHO = echo INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private TINC = $(OBJDIR)/_pr_bld.h ifeq ($(OS_TARGET),OS2) PROD = nspr$(MOD_MAJOR_VERSION).$(DLL_SUFFIX) else PROD = $(notdir $(SHARED_LIBRARY)) endif NOW = $(MOD_DEPTH)/config/$(OBJDIR)/now SH_DATE = $(shell date "+%Y-%m-%d %T") SH_NOW = $(shell $(NOW)) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) SUF = i64 else SUF = LL endif DEFINES += -D_NSPR_BUILD_ GARBAGE += $(TINC) $(TINC): @$(MAKE_OBJDIR) @$(ECHO) '#define _BUILD_STRING "$(SH_DATE)"' > $(TINC) @if test ! -z "$(SH_NOW)"; then \ $(ECHO) '#define _BUILD_TIME $(SH_NOW)$(SUF)' >> $(TINC); \ else \ true; \ fi @$(ECHO) '#define _PRODUCTION "$(PROD)"' >> $(TINC) $(OBJDIR)/prvrsion.$(OBJ_SUFFIX): prvrsion.c $(TINC) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(CC) -Fo$@ -c $(CFLAGS) -I$(OBJDIR) $< else $(CC) -o $@ -c $(CFLAGS) -I$(OBJDIR) $< endif # # Version information generation (end) # # We use a 'build' target here to ensure that we build $(TARGETS) after # looping over $(DIRS) to create the object files in a parallel build. # Recipe commands are executed sequentially in a parallel build while # target dependencies are executed in parallel. export:: $(MAKE) build # # The Client build wants the shared libraries in $(dist_bindir) # so we also install them there. # build:: $(TARGETS) $(INSTALL) -m 444 $(TARGETS) $(dist_libdir) ifdef SHARED_LIBRARY ifeq ($(OS_ARCH),HP-UX) $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_libdir) $(INSTALL) -m 755 $(SHARED_LIBRARY) $(dist_bindir) else $(INSTALL) -m 444 $(SHARED_LIBRARY) $(dist_bindir) endif endif ifeq ($(BUILD_AIX_RTL_LIBC),1) $(AIX_RTL_LIBC): /usr/ccs/lib/libc.a rtl_enable -o $@ $< endif nspr-4.11/nspr/pr/src/bthreads/.cvsignore0000644000000000000000000000001112623070344016526 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/bthreads/Makefile.in0000644000000000000000000000116212623070344016603 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk include $(srcdir)/bsrcs.mk CSRCS += $(BTCSRCS) TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private include $(topsrcdir)/config/rules.mk DEFINES += -D_NSPR_BUILD_ export:: $(TARGETS) nspr-4.11/nspr/pr/src/bthreads/bsrcs.mk0000644000000000000000000000071512623070344016206 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # this file lists the source files to be compiled (used in Makefile) and # then enumerated as object files (in objs.mk) for inclusion in the NSPR # shared library BTCSRCS = \ btthread.c \ btlocks.c \ btcvar.c \ btmon.c \ btsem.c \ btmisc.c \ $(NULL) nspr-4.11/nspr/pr/src/bthreads/btcvar.c0000644000000000000000000001630012623070344016163 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "primpl.h" /* ** Create a new condition variable. ** ** "lock" is the lock used to protect the condition variable. ** ** Condition variables are synchronization objects that threads can use ** to wait for some condition to occur. ** ** This may fail if memory is tight or if some operating system resource ** is low. In such cases, a NULL will be returned. */ PR_IMPLEMENT(PRCondVar*) PR_NewCondVar (PRLock *lock) { PRCondVar *cv = PR_NEW( PRCondVar ); PR_ASSERT( NULL != lock ); if( NULL != cv ) { cv->lock = lock; cv->sem = create_sem(0, "CVSem"); cv->handshakeSem = create_sem(0, "CVHandshake"); cv->signalSem = create_sem( 0, "CVSignal"); cv->signalBenCount = 0; cv->ns = cv->nw = 0; PR_ASSERT( cv->sem >= B_NO_ERROR ); PR_ASSERT( cv->handshakeSem >= B_NO_ERROR ); PR_ASSERT( cv->signalSem >= B_NO_ERROR ); } return cv; } /* PR_NewCondVar */ /* ** Destroy a condition variable. There must be no thread ** waiting on the condvar. The caller is responsible for guaranteeing ** that the condvar is no longer in use. ** */ PR_IMPLEMENT(void) PR_DestroyCondVar (PRCondVar *cvar) { status_t result = delete_sem( cvar->sem ); PR_ASSERT( result == B_NO_ERROR ); result = delete_sem( cvar->handshakeSem ); PR_ASSERT( result == B_NO_ERROR ); result = delete_sem( cvar->signalSem ); PR_ASSERT( result == B_NO_ERROR ); PR_DELETE( cvar ); } /* ** The thread that waits on a condition is blocked in a "waiting on ** condition" state until another thread notifies the condition or a ** caller specified amount of time expires. The lock associated with ** the condition variable will be released, which must have be held ** prior to the call to wait. ** ** Logically a notified thread is moved from the "waiting on condition" ** state and made "ready." When scheduled, it will attempt to reacquire ** the lock that it held when wait was called. ** ** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and ** PR_INTERVAL_NO_WAIT. The former value requires that a condition be ** notified (or the thread interrupted) before it will resume from the ** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect ** is to release the lock, possibly causing a rescheduling within the ** runtime, then immediately attempting to reacquire the lock and resume. ** ** Any other value for timeout will cause the thread to be rescheduled ** either due to explicit notification or an expired interval. The latter ** must be determined by treating time as one part of the monitored data ** being protected by the lock and tested explicitly for an expired ** interval. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable or the thread was interrupted (PR_Interrupt()). ** The particular reason can be extracted with PR_GetError(). */ PR_IMPLEMENT(PRStatus) PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout) { status_t err; if( timeout == PR_INTERVAL_NO_WAIT ) { PR_Unlock( cvar->lock ); PR_Lock( cvar->lock ); return PR_SUCCESS; } if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) { if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) { atomic_add( &cvar->signalBenCount, -1 ); return PR_FAILURE; } } cvar->nw += 1; if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } PR_Unlock( cvar->lock ); if( timeout==PR_INTERVAL_NO_TIMEOUT ) { err = acquire_sem(cvar->sem); } else { err = acquire_sem_etc(cvar->sem, 1, B_RELATIVE_TIMEOUT, PR_IntervalToMicroseconds(timeout) ); } if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) { while (acquire_sem(cvar->signalSem) == B_INTERRUPTED); } if (cvar->ns > 0) { release_sem_etc(cvar->handshakeSem, 1, B_DO_NOT_RESCHEDULE); cvar->ns -= 1; } cvar->nw -= 1; if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } PR_Lock( cvar->lock ); if(err!=B_NO_ERROR) { return PR_FAILURE; } return PR_SUCCESS; } /* ** Notify ONE thread that is currently waiting on 'cvar'. Which thread is ** dependent on the implementation of the runtime. Common sense would dictate ** that all threads waiting on a single condition have identical semantics, ** therefore which one gets notified is not significant. ** ** The calling thead must hold the lock that protects the condition, as ** well as the invariants that are tightly bound to the condition, when ** notify is called. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable. */ PR_IMPLEMENT(PRStatus) PR_NotifyCondVar (PRCondVar *cvar) { status_t err ; if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) { if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) { atomic_add( &cvar->signalBenCount, -1 ); return PR_FAILURE; } } if (cvar->nw > cvar->ns) { cvar->ns += 1; release_sem_etc(cvar->sem, 1, B_DO_NOT_RESCHEDULE); if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } while (acquire_sem(cvar->handshakeSem) == B_INTERRUPTED) { err = B_INTERRUPTED; } } else { if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } } return PR_SUCCESS; } /* ** Notify all of the threads waiting on the condition variable. The order ** that the threads are notified is indeterminant. The lock that protects ** the condition must be held. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable. */ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar (PRCondVar *cvar) { int32 handshakes; status_t err = B_OK; if( atomic_add( &cvar->signalBenCount, 1 ) > 0 ) { if (acquire_sem(cvar->signalSem) == B_INTERRUPTED) { atomic_add( &cvar->signalBenCount, -1 ); return PR_FAILURE; } } if (cvar->nw > cvar->ns) { handshakes = cvar->nw - cvar->ns; cvar->ns = cvar->nw; release_sem_etc(cvar->sem, handshakes, B_DO_NOT_RESCHEDULE); if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } while (acquire_sem_etc(cvar->handshakeSem, handshakes, 0, 0) == B_INTERRUPTED) { err = B_INTERRUPTED; } } else { if( atomic_add( &cvar->signalBenCount, -1 ) > 1 ) { release_sem_etc(cvar->signalSem, 1, B_DO_NOT_RESCHEDULE); } } return PR_SUCCESS; } nspr-4.11/nspr/pr/src/bthreads/btlocks.c0000644000000000000000000000336612623070344016353 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: btlocks.c ** Description: Implemenation for thread locks using bthreads ** Exports: prlock.h */ #include "primpl.h" #include #include void _PR_InitLocks (void) { } PR_IMPLEMENT(PRLock*) PR_NewLock (void) { PRLock *lock; status_t semresult; if (!_pr_initialized) _PR_ImplicitInitialization(); lock = PR_NEWZAP(PRLock); if (lock != NULL) { lock->benaphoreCount = 0; lock->semaphoreID = create_sem( 0, "nsprLockSem" ); if( lock->semaphoreID < B_NO_ERROR ) { PR_DELETE( lock ); lock = NULL; } } return lock; } PR_IMPLEMENT(void) PR_DestroyLock (PRLock* lock) { status_t result; PR_ASSERT(NULL != lock); result = delete_sem(lock->semaphoreID); PR_ASSERT(result == B_NO_ERROR); PR_DELETE(lock); } PR_IMPLEMENT(void) PR_Lock (PRLock* lock) { PR_ASSERT(lock != NULL); if( atomic_add( &lock->benaphoreCount, 1 ) > 0 ) { if( acquire_sem(lock->semaphoreID ) != B_NO_ERROR ) { atomic_add( &lock->benaphoreCount, -1 ); return; } } lock->owner = find_thread( NULL ); } PR_IMPLEMENT(PRStatus) PR_Unlock (PRLock* lock) { PR_ASSERT(lock != NULL); lock->owner = NULL; if( atomic_add( &lock->benaphoreCount, -1 ) > 1 ) { release_sem_etc( lock->semaphoreID, 1, B_DO_NOT_RESCHEDULE ); } return PR_SUCCESS; } PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock) { PR_ASSERT(lock != NULL); PR_ASSERT(lock->owner == find_thread( NULL )); } nspr-4.11/nspr/pr/src/bthreads/btmisc.c0000644000000000000000000000245212623070344016166 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include // void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")} // void _MD_StartInterrupts(void) {PT_LOG("_MD_StartInterrupts")} /* this is a total hack.. */ struct protoent* getprotobyname(const char* name) { return 0; } struct protoent* getprotobynumber(int number) { return 0; } /* this is needed by prinit for some reason */ void _PR_InitStacks (void) { } /* this is needed by prinit for some reason */ void _PR_InitTPD (void) { } /* ** Create extra virtual processor threads. Generally used with MP systems. */ PR_IMPLEMENT(void) PR_SetConcurrency (PRUintn numCPUs) { } /* ** Set thread recycle mode to on (1) or off (0) */ PR_IMPLEMENT(void) PR_SetThreadRecycleMode (PRUint32 flag) { } /* ** Get context registers, return with error for now. */ PR_IMPLEMENT(PRWord *) _MD_HomeGCRegisters( PRThread *t, int isCurrent, int *np ) { return 0; } PR_IMPLEMENT(void *) PR_GetSP( PRThread *t ) { return 0; } PR_IMPLEMENT(PRStatus) PR_EnumerateThreads( PREnumerator func, void *arg ) { return PR_FAILURE; } nspr-4.11/nspr/pr/src/bthreads/btmon.c0000644000000000000000000001154212623070344016024 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "primpl.h" /* ** Create a new monitor. Monitors are re-entrant locks with a single built-in ** condition variable. ** ** This may fail if memory is tight or if some operating system resource ** is low. */ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor (void) { PRMonitor *mon; PRCondVar *cvar; PRLock *lock; mon = PR_NEWZAP( PRMonitor ); if( mon ) { lock = PR_NewLock(); if( !lock ) { PR_DELETE( mon ); return( 0 ); } cvar = PR_NewCondVar( lock ); if( !cvar ) { PR_DestroyLock( lock ); PR_DELETE( mon ); return( 0 ); } mon->cvar = cvar; mon->name = NULL; } return( mon ); } PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) { PRMonitor* mon = PR_NewMonitor(); if( mon ) { mon->name = name; } return mon; } /* ** Destroy a monitor. The caller is responsible for guaranteeing that the ** monitor is no longer in use. There must be no thread waiting on the ** monitor's condition variable and that the lock is not held. ** */ PR_IMPLEMENT(void) PR_DestroyMonitor (PRMonitor *mon) { PR_DestroyLock( mon->cvar->lock ); PR_DestroyCondVar( mon->cvar ); PR_DELETE( mon ); } /* ** Enter the lock associated with the monitor. If the calling thread currently ** is in the monitor, the call to enter will silently succeed. In either case, ** it will increment the entry count by one. */ PR_IMPLEMENT(void) PR_EnterMonitor (PRMonitor *mon) { if( mon->cvar->lock->owner == find_thread( NULL ) ) { mon->entryCount++; } else { PR_Lock( mon->cvar->lock ); mon->entryCount = 1; } } /* ** Decrement the entry count associated with the monitor. If the decremented ** entry count is zero, the monitor is exited. Returns PR_FAILURE if the ** calling thread has not entered the monitor. */ PR_IMPLEMENT(PRStatus) PR_ExitMonitor (PRMonitor *mon) { if( mon->cvar->lock->owner != find_thread( NULL ) ) { return( PR_FAILURE ); } if( --mon->entryCount == 0 ) { return( PR_Unlock( mon->cvar->lock ) ); } return( PR_SUCCESS ); } /* ** Wait for a notify on the monitor's condition variable. Sleep for "ticks" ** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is ** indefinite). ** ** While the thread is waiting it exits the monitor (as if it called ** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When ** the wait has finished the thread regains control of the monitors lock ** with the same entry count as before the wait began. ** ** The thread waiting on the monitor will be resumed when the monitor is ** notified (assuming the thread is the next in line to receive the ** notify) or when the "ticks" timeout elapses. ** ** Returns PR_FAILURE if the caller has not entered the monitor. */ PR_IMPLEMENT(PRStatus) PR_Wait (PRMonitor *mon, PRIntervalTime ticks) { PRUint32 entryCount; PRUintn status; PRThread *meThread; thread_id me = find_thread( NULL ); meThread = PR_GetCurrentThread(); if( mon->cvar->lock->owner != me ) return( PR_FAILURE ); entryCount = mon->entryCount; mon->entryCount = 0; status = PR_WaitCondVar( mon->cvar, ticks ); mon->entryCount = entryCount; return( status ); } /* ** Notify a thread waiting on the monitor's condition variable. If a thread ** is waiting on the condition variable (using PR_Wait) then it is awakened ** and attempts to reenter the monitor. */ PR_IMPLEMENT(PRStatus) PR_Notify (PRMonitor *mon) { if( mon->cvar->lock->owner != find_thread( NULL ) ) { return( PR_FAILURE ); } PR_NotifyCondVar( mon->cvar ); return( PR_SUCCESS ); } /* ** Notify all of the threads waiting on the monitor's condition variable. ** All of threads waiting on the condition are scheduled to reenter the ** monitor. */ PR_IMPLEMENT(PRStatus) PR_NotifyAll (PRMonitor *mon) { if( mon->cvar->lock->owner != find_thread( NULL ) ) { return( PR_FAILURE ); } PR_NotifyAllCondVar( mon->cvar ); return( PR_SUCCESS ); } /* ** Return the number of times that the current thread has entered the ** lock. Returns zero if the current thread has not entered the lock. */ PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon) { return( (mon->cvar->lock->owner == find_thread( NULL )) ? mon->entryCount : 0 ); } /* ** If the current thread is in |mon|, this assertion is guaranteed to ** succeed. Otherwise, the behavior of this function is undefined. */ PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon) { PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mon->cvar->lock); } nspr-4.11/nspr/pr/src/bthreads/btsem.c0000644000000000000000000000474612623070344016027 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "primpl.h" /* ** Create a new semaphore object. */ PR_IMPLEMENT(PRSemaphore*) PR_NewSem (PRUintn value) { PRSemaphore *semaphore; if (!_pr_initialized) _PR_ImplicitInitialization(); semaphore = PR_NEWZAP(PRSemaphore); if (NULL != semaphore) { if ((semaphore->sem = create_sem(value, "nspr_sem")) < B_NO_ERROR) return NULL; else return semaphore; } return NULL; } /* ** Destroy the given semaphore object. ** */ PR_IMPLEMENT(void) PR_DestroySem (PRSemaphore *sem) { status_t result; PR_ASSERT(sem != NULL); result = delete_sem(sem->sem); PR_ASSERT(result == B_NO_ERROR); PR_DELETE(sem); } /* ** Wait on a Semaphore. ** ** This routine allows a calling thread to wait or proceed depending upon ** the state of the semahore sem. The thread can proceed only if the ** counter value of the semaphore sem is currently greater than 0. If the ** value of semaphore sem is positive, it is decremented by one and the ** routine returns immediately allowing the calling thread to continue. If ** the value of semaphore sem is 0, the calling thread blocks awaiting the ** semaphore to be released by another thread. ** ** This routine can return PR_PENDING_INTERRUPT if the waiting thread ** has been interrupted. */ PR_IMPLEMENT(PRStatus) PR_WaitSem (PRSemaphore *sem) { PR_ASSERT(sem != NULL); if (acquire_sem(sem->sem) == B_NO_ERROR) return PR_SUCCESS; else return PR_FAILURE; } /* ** This routine increments the counter value of the semaphore. If other ** threads are blocked for the semaphore, then the scheduler will ** determine which ONE thread will be unblocked. */ PR_IMPLEMENT(void) PR_PostSem (PRSemaphore *sem) { status_t result; PR_ASSERT(sem != NULL); result = release_sem_etc(sem->sem, 1, B_DO_NOT_RESCHEDULE); PR_ASSERT(result == B_NO_ERROR); } /* ** Returns the value of the semaphore referenced by sem without affecting ** the state of the semaphore. The value represents the semaphore value ** at the time of the call, but may not be the actual value when the ** caller inspects it. */ PR_IMPLEMENT(PRUintn) PR_GetValueSem (PRSemaphore *sem) { sem_info info; PR_ASSERT(sem != NULL); get_sem_info(sem->sem, &info); return info.count; } nspr-4.11/nspr/pr/src/bthreads/btthread.c0000644000000000000000000004040112623070344016476 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include "prlog.h" #include "primpl.h" #include "prcvar.h" #include "prpdce.h" #include #include #include /* values for PRThread.state */ #define BT_THREAD_PRIMORD 0x01 /* this is the primordial thread */ #define BT_THREAD_SYSTEM 0x02 /* this is a system thread */ #define BT_THREAD_JOINABLE 0x04 /* this is a joinable thread */ struct _BT_Bookeeping { PRLock *ml; /* a lock to protect ourselves */ sem_id cleanUpSem; /* the primoridal thread will block on this sem while waiting for the user threads */ PRInt32 threadCount; /* user thred count */ } bt_book = { NULL, B_ERROR, 0 }; #define BT_TPD_LIMIT 128 /* number of TPD slots we'll provide (arbitrary) */ /* these will be used to map an index returned by PR_NewThreadPrivateIndex() to the corresponding beos native TLS slot number, and to the destructor for that slot - note that, because it is allocated globally, this data will be automatically zeroed for us when the program begins */ static int32 tpd_beosTLSSlots[BT_TPD_LIMIT]; static PRThreadPrivateDTOR tpd_dtors[BT_TPD_LIMIT]; static vint32 tpd_slotsUsed=0; /* number of currently-allocated TPD slots */ static int32 tls_prThreadSlot; /* TLS slot in which PRThread will be stored */ /* this mutex will be used to synchronize access to every PRThread.md.joinSem and PRThread.md.is_joining (we could actually allocate one per thread, but that seems a bit excessive, especially considering that there will probably be little contention, PR_JoinThread() is allowed to block anyway, and the code protected by the mutex is short/fast) */ static PRLock *joinSemLock; static PRUint32 _bt_MapNSPRToNativePriority( PRThreadPriority priority ); static PRThreadPriority _bt_MapNativeToNSPRPriority( PRUint32 priority ); static void _bt_CleanupThread(void *arg); static PRThread *_bt_AttachThread(); void _PR_InitThreads (PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) { PRThread *primordialThread; PRUint32 beThreadPriority; /* allocate joinSem mutex */ joinSemLock = PR_NewLock(); if (joinSemLock == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return; } /* ** Create and initialize NSPR structure for our primordial thread. */ primordialThread = PR_NEWZAP(PRThread); if( NULL == primordialThread ) { PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 ); return; } primordialThread->md.joinSem = B_ERROR; /* ** Set the priority to the desired level. */ beThreadPriority = _bt_MapNSPRToNativePriority( priority ); set_thread_priority( find_thread( NULL ), beThreadPriority ); primordialThread->priority = priority; /* set the thread's state - note that the thread is not joinable */ primordialThread->state |= BT_THREAD_PRIMORD; if (type == PR_SYSTEM_THREAD) primordialThread->state |= BT_THREAD_SYSTEM; /* ** Allocate a TLS slot for the PRThread structure (just using ** native TLS, as opposed to NSPR TPD, will make PR_GetCurrentThread() ** somewhat faster, and will leave one more TPD slot for our client) */ tls_prThreadSlot = tls_allocate(); /* ** Stuff our new PRThread structure into our thread specific ** slot. */ tls_set(tls_prThreadSlot, primordialThread); /* allocate lock for bt_book */ bt_book.ml = PR_NewLock(); if( NULL == bt_book.ml ) { PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 ); return; } } PRUint32 _bt_MapNSPRToNativePriority( PRThreadPriority priority ) { switch( priority ) { case PR_PRIORITY_LOW: return( B_LOW_PRIORITY ); case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY ); case PR_PRIORITY_HIGH: return( B_DISPLAY_PRIORITY ); case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY ); default: return( B_NORMAL_PRIORITY ); } } PRThreadPriority _bt_MapNativeToNSPRPriority(PRUint32 priority) { if (priority < B_NORMAL_PRIORITY) return PR_PRIORITY_LOW; if (priority < B_DISPLAY_PRIORITY) return PR_PRIORITY_NORMAL; if (priority < B_URGENT_DISPLAY_PRIORITY) return PR_PRIORITY_HIGH; return PR_PRIORITY_URGENT; } PRUint32 _bt_mapNativeToNSPRPriority( int32 priority ) { switch( priority ) { case PR_PRIORITY_LOW: return( B_LOW_PRIORITY ); case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY ); case PR_PRIORITY_HIGH: return( B_DISPLAY_PRIORITY ); case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY ); default: return( B_NORMAL_PRIORITY ); } } /* This method is called by all NSPR threads as they exit */ void _bt_CleanupThread(void *arg) { PRThread *me = PR_GetCurrentThread(); int32 i; /* first, clean up all thread-private data */ for (i = 0; i < tpd_slotsUsed; i++) { void *oldValue = tls_get(tpd_beosTLSSlots[i]); if ( oldValue != NULL && tpd_dtors[i] != NULL ) (*tpd_dtors[i])(oldValue); } /* if this thread is joinable, wait for someone to join it */ if (me->state & BT_THREAD_JOINABLE) { /* protect access to our joinSem */ PR_Lock(joinSemLock); if (me->md.is_joining) { /* someone is already waiting to join us (they've allocated a joinSem for us) - let them know we're ready */ delete_sem(me->md.joinSem); PR_Unlock(joinSemLock); } else { /* noone is currently waiting for our demise - it is our responsibility to allocate the joinSem and block on it */ me->md.joinSem = create_sem(0, "join sem"); /* we're done accessing our joinSem */ PR_Unlock(joinSemLock); /* wait for someone to join us */ while (acquire_sem(me->md.joinSem) == B_INTERRUPTED); } } /* if this is a user thread, we must update our books */ if ((me->state & BT_THREAD_SYSTEM) == 0) { /* synchronize access to bt_book */ PR_Lock( bt_book.ml ); /* decrement the number of currently-alive user threads */ bt_book.threadCount--; if (bt_book.threadCount == 0 && bt_book.cleanUpSem != B_ERROR) { /* we are the last user thread, and the primordial thread is blocked in PR_Cleanup() waiting for us to finish - notify it */ delete_sem(bt_book.cleanUpSem); } PR_Unlock( bt_book.ml ); } /* finally, delete this thread's PRThread */ PR_DELETE(me); } /** * This is a wrapper that all threads invoke that allows us to set some * things up prior to a thread's invocation and clean up after a thread has * exited. */ static void* _bt_root (void* arg) { PRThread *thred = (PRThread*)arg; PRIntn rv; void *privData; status_t result; int i; /* save our PRThread object into our TLS */ tls_set(tls_prThreadSlot, thred); thred->startFunc(thred->arg); /* run the dang thing */ /* clean up */ _bt_CleanupThread(NULL); return 0; } PR_IMPLEMENT(PRThread*) PR_CreateThread (PRThreadType type, void (*start)(void* arg), void* arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PRUint32 bePriority; PRThread* thred; if (!_pr_initialized) _PR_ImplicitInitialization(); thred = PR_NEWZAP(PRThread); if (thred == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } thred->md.joinSem = B_ERROR; thred->arg = arg; thred->startFunc = start; thred->priority = priority; if( state == PR_JOINABLE_THREAD ) { thred->state |= BT_THREAD_JOINABLE; } /* keep some books */ PR_Lock( bt_book.ml ); if (type == PR_USER_THREAD) { bt_book.threadCount++; } PR_Unlock( bt_book.ml ); bePriority = _bt_MapNSPRToNativePriority( priority ); thred->md.tid = spawn_thread((thread_func)_bt_root, "moz-thread", bePriority, thred); if (thred->md.tid < B_OK) { PR_SetError(PR_UNKNOWN_ERROR, thred->md.tid); PR_DELETE(thred); return NULL; } if (resume_thread(thred->md.tid) < B_OK) { PR_SetError(PR_UNKNOWN_ERROR, 0); PR_DELETE(thred); return NULL; } return thred; } PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack) { /* PR_GetCurrentThread() will attach a thread if necessary */ return PR_GetCurrentThread(); } PR_IMPLEMENT(void) PR_DetachThread() { /* we don't support detaching */ } PR_IMPLEMENT(PRStatus) PR_JoinThread (PRThread* thred) { status_t eval, status; PR_ASSERT(thred != NULL); if ((thred->state & BT_THREAD_JOINABLE) == 0) { PR_SetError( PR_INVALID_ARGUMENT_ERROR, 0 ); return( PR_FAILURE ); } /* synchronize access to the thread's joinSem */ PR_Lock(joinSemLock); if (thred->md.is_joining) { /* another thread is already waiting to join the specified thread - we must fail */ PR_Unlock(joinSemLock); return PR_FAILURE; } /* let others know we are waiting to join */ thred->md.is_joining = PR_TRUE; if (thred->md.joinSem == B_ERROR) { /* the thread hasn't finished yet - it is our responsibility to allocate a joinSem and wait on it */ thred->md.joinSem = create_sem(0, "join sem"); /* we're done changing the joinSem now */ PR_Unlock(joinSemLock); /* wait for the thread to finish */ while (acquire_sem(thred->md.joinSem) == B_INTERRUPTED); } else { /* the thread has already finished, and has allocated the joinSem itself - let it know it can finally die */ delete_sem(thred->md.joinSem); PR_Unlock(joinSemLock); } /* make sure the thread is dead */ wait_for_thread(thred->md.tid, &eval); return PR_SUCCESS; } PR_IMPLEMENT(PRThread*) PR_GetCurrentThread () { PRThread* thred; if (!_pr_initialized) _PR_ImplicitInitialization(); thred = (PRThread *)tls_get( tls_prThreadSlot); if (thred == NULL) { /* this thread doesn't have a PRThread structure (it must be a native thread not created by the NSPR) - assimilate it */ thred = _bt_AttachThread(); } PR_ASSERT(NULL != thred); return thred; } PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope (const PRThread* thred) { PR_ASSERT(thred != NULL); return PR_GLOBAL_THREAD; } PR_IMPLEMENT(PRThreadType) PR_GetThreadType (const PRThread* thred) { PR_ASSERT(thred != NULL); return (thred->state & BT_THREAD_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD; } PR_IMPLEMENT(PRThreadState) PR_GetThreadState (const PRThread* thred) { PR_ASSERT(thred != NULL); return (thred->state & BT_THREAD_JOINABLE)? PR_JOINABLE_THREAD: PR_UNJOINABLE_THREAD; } PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority (const PRThread* thred) { PR_ASSERT(thred != NULL); return thred->priority; } /* PR_GetThreadPriority */ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri) { PRUint32 bePriority; PR_ASSERT( thred != NULL ); thred->priority = newPri; bePriority = _bt_MapNSPRToNativePriority( newPri ); set_thread_priority( thred->md.tid, bePriority ); } PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex (PRUintn* newIndex, PRThreadPrivateDTOR destructor) { int32 index; if (!_pr_initialized) _PR_ImplicitInitialization(); /* reserve the next available tpd slot */ index = atomic_add( &tpd_slotsUsed, 1 ); if (index >= BT_TPD_LIMIT) { /* no slots left - decrement value, then fail */ atomic_add( &tpd_slotsUsed, -1 ); PR_SetError( PR_TPD_RANGE_ERROR, 0 ); return( PR_FAILURE ); } /* allocate a beos-native TLS slot for this index (the new slot automatically contains NULL) */ tpd_beosTLSSlots[index] = tls_allocate(); /* remember the destructor */ tpd_dtors[index] = destructor; *newIndex = (PRUintn)index; return( PR_SUCCESS ); } PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate (PRUintn index, void* priv) { void *oldValue; /* ** Sanity checking */ if(index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT) { PR_SetError( PR_TPD_RANGE_ERROR, 0 ); return( PR_FAILURE ); } /* if the old value isn't NULL, and the dtor for this slot isn't NULL, we must destroy the data */ oldValue = tls_get(tpd_beosTLSSlots[index]); if (oldValue != NULL && tpd_dtors[index] != NULL) (*tpd_dtors[index])(oldValue); /* save new value */ tls_set(tpd_beosTLSSlots[index], priv); return( PR_SUCCESS ); } PR_IMPLEMENT(void*) PR_GetThreadPrivate (PRUintn index) { /* make sure the index is valid */ if (index < 0 || index >= tpd_slotsUsed || index >= BT_TPD_LIMIT) { PR_SetError( PR_TPD_RANGE_ERROR, 0 ); return NULL; } /* return the value */ return tls_get( tpd_beosTLSSlots[index] ); } PR_IMPLEMENT(PRStatus) PR_Interrupt (PRThread* thred) { PRIntn rv; PR_ASSERT(thred != NULL); /* ** there seems to be a bug in beos R5 in which calling ** resume_thread() on a blocked thread returns B_OK instead ** of B_BAD_THREAD_STATE (beos bug #20000422-19095). as such, ** to interrupt a thread, we will simply suspend then resume it ** (no longer call resume_thread(), check for B_BAD_THREAD_STATE, ** the suspend/resume to wake up a blocked thread). this wakes ** up blocked threads properly, and doesn't hurt unblocked threads ** (they simply get stopped then re-started immediately) */ rv = suspend_thread( thred->md.tid ); if( rv != B_NO_ERROR ) { /* this doesn't appear to be a valid thread_id */ PR_SetError( PR_UNKNOWN_ERROR, rv ); return PR_FAILURE; } rv = resume_thread( thred->md.tid ); if( rv != B_NO_ERROR ) { PR_SetError( PR_UNKNOWN_ERROR, rv ); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(void) PR_ClearInterrupt () { } PR_IMPLEMENT(PRStatus) PR_Yield () { /* we just sleep for long enough to cause a reschedule (100 microseconds) */ snooze(100); } #define BT_MILLION 1000000UL PR_IMPLEMENT(PRStatus) PR_Sleep (PRIntervalTime ticks) { bigtime_t tps; status_t status; if (!_pr_initialized) _PR_ImplicitInitialization(); tps = PR_IntervalToMicroseconds( ticks ); status = snooze(tps); if (status == B_NO_ERROR) return PR_SUCCESS; PR_SetError(PR_NOT_IMPLEMENTED_ERROR, status); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) PR_Cleanup () { PRThread *me = PR_GetCurrentThread(); PR_ASSERT(me->state & BT_THREAD_PRIMORD); if ((me->state & BT_THREAD_PRIMORD) == 0) { return PR_FAILURE; } PR_Lock( bt_book.ml ); if (bt_book.threadCount != 0) { /* we'll have to wait for some threads to finish - create a sem to block on */ bt_book.cleanUpSem = create_sem(0, "cleanup sem"); } PR_Unlock( bt_book.ml ); /* note that, if all the user threads were already dead, we wouldn't have created a sem above, so this acquire_sem() will fail immediately */ while (acquire_sem(bt_book.cleanUpSem) == B_INTERRUPTED); return PR_SUCCESS; } PR_IMPLEMENT(void) PR_ProcessExit (PRIntn status) { exit(status); } PRThread *_bt_AttachThread() { PRThread *thread; thread_info tInfo; /* make sure this thread doesn't already have a PRThread structure */ PR_ASSERT(tls_get(tls_prThreadSlot) == NULL); /* allocate a PRThread structure for this thread */ thread = PR_NEWZAP(PRThread); if (thread == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } /* get the native thread's current state */ get_thread_info(find_thread(NULL), &tInfo); /* initialize new PRThread */ thread->md.tid = tInfo.thread; thread->md.joinSem = B_ERROR; thread->priority = _bt_MapNativeToNSPRPriority(tInfo.priority); /* attached threads are always non-joinable user threads */ thread->state = 0; /* increment user thread count */ PR_Lock(bt_book.ml); bt_book.threadCount++; PR_Unlock(bt_book.ml); /* store this thread's PRThread */ tls_set(tls_prThreadSlot, thread); /* the thread must call _bt_CleanupThread() before it dies, in order to clean up its PRThread, synchronize with the primordial thread, etc. */ on_exit_thread(_bt_CleanupThread, NULL); return thread; } nspr-4.11/nspr/pr/src/bthreads/objs.mk0000644000000000000000000000063612623070344016031 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # This makefile appends to the variable OBJS the bthread object modules # that will be part of the nspr20 library. include $(srcdir)/bthreads/bsrcs.mk OBJS += $(BTCSRCS:%.c=bthreads/$(OBJDIR)/%.$(OBJ_SUFFIX)) nspr-4.11/nspr/pr/src/cplus/.cvsignore0000644000000000000000000000001112623070344016060 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/cplus/Makefile.in0000644000000000000000000000146512623070344016143 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CXXSRCS = \ rcbase.cpp \ rccv.cpp \ rcfileio.cpp \ rcinrval.cpp \ rcio.cpp \ rclock.cpp \ rcnetdb.cpp \ rcnetio.cpp \ rcthread.cpp \ rctime.cpp \ $(NULL) OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX))) TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk HEADERS = $(wildcard $(srcdir)/*.h) export:: $(TARGETS) nspr-4.11/nspr/pr/src/cplus/rcascii.h0000644000000000000000000001044712623070344015664 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Class definitions to format ASCII data. */ #if defined(_RCASCII_H) #else #define _RCASCII_H /* ** RCFormatStuff ** This class maintains no state - that is the responsibility of ** the class' client. For each call to Sx_printf(), the StuffFunction ** will be called for each embedded "%" in the 'fmt' string and once ** for each interveaning literal. */ class PR_IMPLEMENT(RCFormatStuff) { public: RCFormatStuff(); virtual ~RCFormatStuff(); /* ** Process the arbitrary argument list using as indicated by ** the 'fmt' string. Each segment of the processing the stuff ** function is called with the relavent translation. */ virtual PRInt32 Sx_printf(void *state, const char *fmt, ...); /* ** The 'state' argument is not processed by the runtime. It ** is merely passed from the Sx_printf() call. It is intended ** to be used by the client to figure out what to do with the ** new string. ** ** The new string ('stuff') is ASCII translation driven by the ** Sx_printf()'s 'fmt' string. It is not guaranteed to be a null ** terminated string. ** ** The return value is the number of bytes copied from the 'stuff' ** string. It is accumulated for each of the calls to the stuff ** function and returned from the original caller of Sx_printf(). */ virtual PRSize StuffFunction( void *state, const char *stuff, PRSize stufflen) = 0; }; /* RCFormatStuff */ /* ** RCFormatBuffer ** The caller is supplying the buffer, the runtime is doing all ** the conversion. The object contains no state, so is reusable ** and reentrant. */ class PR_IMPLEMENT(RCFormatBuffer): public RCFormatStuff { public: RCFormatBuffer(); virtual ~RCFormatBuffer(); /* ** Format the trailing arguments as indicated by the 'fmt' ** string. Put the result in 'buffer'. Return the number ** of bytes moved into 'buffer'. 'buffer' will always be ** a properly terminated string even if the convresion fails. */ virtual PRSize Sn_printf( char *buffer, PRSize length, const char *fmt, ...); virtual char *Sm_append(char *buffer, const char *fmt, ...); private: /* ** This class overrides the stuff function, does not preserve ** its virtual-ness and no longer allows the clients to call ** it in the clear. In other words, it is now the implementation ** for this class. */ PRSize StuffFunction(void*, const char*, PRSize); }; /* RCFormatBuffer */ /* ** RCFormat ** The runtime is supplying the buffer. The object has state - the ** buffer. Each operation must run to completion before the object ** can be reused. When it is, the buffer is reset (whatever that ** means). The result of a conversion is available via the extractor. ** After extracted, the memory still belongs to the class - if the ** caller wants to retain or modify, it must first be copied. */ class PR_IMPLEMENT(RCFormat): pubic RCFormatBuffer { public: RCFormat(); virtual ~RCFormat(); /* ** Translate the trailing arguments according to the 'fmt' ** string and store the results in the object. */ virtual PRSize Sm_printf(const char *fmt, ...); /* ** Extract the latest translation. ** The object does not surrender the memory occupied by ** the string. If the caller wishes to modify the data, ** it must first be copied. */ const char*(); private: char *buffer; RCFormat(const RCFormat&); RCFormat& operator=(const RCFormat&); }; /* RCFormat */ /* ** RCPrint ** The output is formatted and then written to an associated file ** descriptor. The client can provide a suitable file descriptor ** or can indicate that the output should be directed to one of ** the well-known "console" devices. */ class PR_IMPLEMENT(RCPrint): public RCFormat { virtual ~RCPrint(); RCPrint(RCIO* output); RCPrint(RCFileIO::SpecialFile output); virtual PRSize Printf(const char *fmt, ...); private: RCPrint(); }; /* RCPrint */ #endif /* defined(_RCASCII_H) */ /* RCAscii.h */ nspr-4.11/nspr/pr/src/cplus/rcbase.cpp0000644000000000000000000000136512623070344016040 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** RCBase.cpp - Mixin class for NSPR C++ wrappers */ #include "rcbase.h" RCBase::~RCBase() { } PRSize RCBase::GetErrorTextLength() { return PR_GetErrorTextLength(); } PRSize RCBase::CopyErrorText(char *text) { return PR_GetErrorText(text); } void RCBase::SetError(PRErrorCode error, PRInt32 oserror) { PR_SetError(error, oserror); } void RCBase::SetErrorText(PRSize text_length, const char *text) { PR_SetErrorText(text_length, text); } /* rcbase.cpp */ nspr-4.11/nspr/pr/src/cplus/rcbase.h0000644000000000000000000000262712623070344015507 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** RCBase.h - Mixin class for NSPR C++ wrappers */ #if defined(_RCRUNTIME_H) #else #define _RCRUNTIME_H #include /* ** Class: RCBase (mixin) ** ** Generally mixed into every base class. The functions in this class are all ** static. Therefore this entire class is just syntatic sugar. It gives the ** illusion that errors (in particular) are retrieved via the same object ** that just reported a failure. It also (unfortunately) might lead one to ** believe that the errors are persistent in that object. They're not. */ class PR_IMPLEMENT(RCBase) { public: virtual ~RCBase(); static void AbortSelf(); static PRErrorCode GetError(); static PRInt32 GetOSError(); static PRSize GetErrorTextLength(); static PRSize CopyErrorText(char *text); static void SetError(PRErrorCode error, PRInt32 oserror); static void SetErrorText(PRSize textLength, const char *text); protected: RCBase() { } }; /* RCObject */ inline PRErrorCode RCBase::GetError() { return PR_GetError(); } inline PRInt32 RCBase::GetOSError() { return PR_GetOSError(); } #endif /* defined(_RCRUNTIME_H) */ /* rcbase.h */ nspr-4.11/nspr/pr/src/cplus/rccv.cpp0000644000000000000000000000277412623070344015543 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** RCCondition - C++ wrapper around NSPR's PRCondVar */ #include "rccv.h" #include #include #include RCCondition::RCCondition(class RCLock *lock): RCBase() { cv = PR_NewCondVar(lock->lock); PR_ASSERT(NULL != cv); timeout = PR_INTERVAL_NO_TIMEOUT; } /* RCCondition::RCCondition */ RCCondition::~RCCondition() { if (NULL != cv) PR_DestroyCondVar(cv); } /* RCCondition::~RCCondition */ PRStatus RCCondition::Wait() { PRStatus rv; PR_ASSERT(NULL != cv); if (NULL == cv) { SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = PR_FAILURE; } else rv = PR_WaitCondVar(cv, timeout.interval); return rv; } /* RCCondition::Wait */ PRStatus RCCondition::Notify() { return PR_NotifyCondVar(cv); } /* RCCondition::Notify */ PRStatus RCCondition::Broadcast() { return PR_NotifyAllCondVar(cv); } /* RCCondition::Broadcast */ PRStatus RCCondition::SetTimeout(const RCInterval& tmo) { if (NULL == cv) { SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } timeout = tmo; return PR_SUCCESS; } /* RCCondition::SetTimeout */ RCInterval RCCondition::GetTimeout() const { return timeout; } /* rccv.cpp */ nspr-4.11/nspr/pr/src/cplus/rccv.h0000644000000000000000000000374512623070344015207 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** RCCondition - C++ wrapper around NSPR's PRCondVar ** ** Conditions have a notion of timeouts. A thread that waits on a condition ** will resume execution when the condition is notified OR when a specified ** interval of time has expired. ** ** Most applications don't adjust the timeouts on conditions. The literature ** would argue that all threads waiting on a single condition must have the ** same semantics. But if an application wishes to modify the timeout with ** (perhaps) each wait call, that modification should be done consistantly ** and under protection of the condition's associated lock. ** ** The default timeout is infinity. */ #if defined(_RCCOND_H) #else #define _RCCOND_H #include "rclock.h" #include "rcbase.h" #include "rcinrval.h" struct PRCondVar; class PR_IMPLEMENT(RCCondition): public RCBase { public: RCCondition(RCLock*); /* associates CV with a lock and infinite tmo */ virtual ~RCCondition(); virtual PRStatus Wait(); /* applies object's current timeout */ virtual PRStatus Notify(); /* perhaps ready one thread */ virtual PRStatus Broadcast(); /* perhaps ready many threads */ virtual PRStatus SetTimeout(const RCInterval&); /* set object's current timeout value */ private: PRCondVar *cv; RCInterval timeout; RCCondition(); RCCondition(const RCCondition&); void operator=(const RCCondition&); public: RCInterval GetTimeout() const; }; /* RCCondition */ inline RCCondition::RCCondition(): RCBase() { } inline RCCondition::RCCondition(const RCCondition&): RCBase() { } inline void RCCondition::operator=(const RCCondition&) { } #endif /* defined(_RCCOND_H) */ /* RCCond.h */ nspr-4.11/nspr/pr/src/cplus/rcfileio.cpp0000644000000000000000000001261212623070344016372 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Class implementation for normal and special file I/O (ref: prio.h) */ #include "rcfileio.h" #include RCFileIO::RCFileIO(): RCIO(RCIO::file) { } RCFileIO::~RCFileIO() { if (NULL != fd) (void)Close(); } PRInt64 RCFileIO::Available() { return fd->methods->available(fd); } PRStatus RCFileIO::Close() { PRStatus rv = fd->methods->close(fd); fd = NULL; return rv; } PRStatus RCFileIO::Delete(const char* filename) { return PR_Delete(filename); } PRStatus RCFileIO::FileInfo(RCFileInfo* info) const { return fd->methods->fileInfo64(fd, &info->info); } PRStatus RCFileIO::FileInfo(const char *name, RCFileInfo* info) { return PR_GetFileInfo64(name, &info->info); } PRStatus RCFileIO::Fsync() { return fd->methods->fsync(fd); } PRStatus RCFileIO::Open(const char *filename, PRIntn flags, PRIntn mode) { fd = PR_Open(filename, flags, mode); return (NULL == fd) ? PR_FAILURE : PR_SUCCESS; } /* RCFileIO::Open */ PRInt32 RCFileIO::Read(void *buf, PRSize amount) { return fd->methods->read(fd, buf, amount); } PRInt64 RCFileIO::Seek(PRInt64 offset, RCIO::Whence how) { PRSeekWhence whence; switch (how) { case RCFileIO::set: whence = PR_SEEK_SET; break; case RCFileIO::current: whence = PR_SEEK_CUR; break; case RCFileIO::end: whence = PR_SEEK_END; break; default: whence = (PRSeekWhence)-1; } return fd->methods->seek64(fd, offset, whence); } /* RCFileIO::Seek */ PRInt32 RCFileIO::Write(const void *buf, PRSize amount) { return fd->methods->write(fd, buf, amount); } PRInt32 RCFileIO::Writev( const PRIOVec *iov, PRSize size, const RCInterval& timeout) { return fd->methods->writev(fd, iov, size, timeout); } RCIO *RCFileIO::GetSpecialFile(RCFileIO::SpecialFile special) { PRFileDesc* fd; PRSpecialFD which; RCFileIO* spec = NULL; switch (special) { case RCFileIO::input: which = PR_StandardInput; break; case RCFileIO::output: which = PR_StandardOutput; break; case RCFileIO::error: which = PR_StandardError; break; default: which = (PRSpecialFD)-1; } fd = PR_GetSpecialFD(which); if (NULL != fd) { spec = new RCFileIO(); if (NULL != spec) spec->fd = fd; } return spec; } /* RCFileIO::GetSpecialFile */ /* ** The following methods have been made non-virtual and private. These ** default implementations are intended to NEVER be called. They ** are not valid for this type of I/O class (normal and special file). */ PRStatus RCFileIO::Connect(const RCNetAddr&, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCFileIO::GetLocalName(RCNetAddr*) const { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCFileIO::GetPeerName(RCNetAddr*) const { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCFileIO::GetSocketOption(PRSocketOptionData*) const { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCFileIO::Listen(PRIntn) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRInt16 RCFileIO::Poll(PRInt16, PRInt16*) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return 0; } PRInt32 RCFileIO::Recv(void*, PRSize, PRIntn, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } PRInt32 RCFileIO::Recvfrom(void*, PRSize, PRIntn, RCNetAddr*, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } PRInt32 RCFileIO::Send( const void*, PRSize, PRIntn, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } PRInt32 RCFileIO::Sendto( const void*, PRSize, PRIntn, const RCNetAddr&, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } RCIO* RCFileIO::Accept(RCNetAddr*, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return NULL; } PRStatus RCFileIO::Bind(const RCNetAddr&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRInt32 RCFileIO::AcceptRead( RCIO**, RCNetAddr**, void*, PRSize, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } PRStatus RCFileIO::SetSocketOption(const PRSocketOptionData*) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCFileIO::Shutdown(RCIO::ShutdownHow) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRInt32 RCFileIO::TransmitFile( RCIO*, const void*, PRSize, RCIO::FileDisposition, const RCInterval&) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } /* ** Class implementation for file information object (ref: prio.h) */ RCFileInfo::~RCFileInfo() { } RCFileInfo::RCFileInfo(const RCFileInfo& her): RCBase() { info = her.info; } /* RCFileInfo::RCFileInfo */ RCTime RCFileInfo::CreationTime() const { return RCTime(info.creationTime); } RCTime RCFileInfo::ModifyTime() const { return RCTime(info.modifyTime); } RCFileInfo::FileType RCFileInfo::Type() const { RCFileInfo::FileType type; switch (info.type) { case PR_FILE_FILE: type = RCFileInfo::file; break; case PR_FILE_DIRECTORY: type = RCFileInfo::directory; break; default: type = RCFileInfo::other; } return type; } /* RCFileInfo::Type */ nspr-4.11/nspr/pr/src/cplus/rcfileio.h0000644000000000000000000001026712623070344016043 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Class definitions for normal and special file I/O (ref: prio.h) */ #if defined(_RCFILEIO_H) #else #define _RCFILEIO_H #include "rcio.h" #include "rctime.h" /* ** One would normally create a concrete class, such as RCFileIO, but then ** pass around more generic references, ie., RCIO. ** ** This subclass of RCIO hides (makes private) the methods that are not ** applicable to normal files. */ class RCFileInfo; class PR_IMPLEMENT(RCFileIO): public RCIO { public: RCFileIO(); virtual ~RCFileIO(); virtual PRInt64 Available(); virtual PRStatus Close(); static PRStatus Delete(const char *name); virtual PRStatus FileInfo(RCFileInfo* info) const; static PRStatus FileInfo(const char *name, RCFileInfo* info); virtual PRStatus Fsync(); virtual PRStatus Open(const char *name, PRIntn flags, PRIntn mode); virtual PRInt32 Read(void *buf, PRSize amount); virtual PRInt64 Seek(PRInt64 offset, RCIO::Whence how); virtual PRInt32 Write(const void *buf, PRSize amount); virtual PRInt32 Writev( const PRIOVec *iov, PRSize size, const RCInterval& timeout); private: /* These methods made private are unavailable for this object */ RCFileIO(const RCFileIO&); void operator=(const RCFileIO&); RCIO* Accept(RCNetAddr* addr, const RCInterval& timeout); PRInt32 AcceptRead( RCIO **newfd, RCNetAddr **address, void *buffer, PRSize amount, const RCInterval& timeout); PRStatus Bind(const RCNetAddr& addr); PRStatus Connect(const RCNetAddr& addr, const RCInterval& timeout); PRStatus GetLocalName(RCNetAddr *addr) const; PRStatus GetPeerName(RCNetAddr *addr) const; PRStatus GetSocketOption(PRSocketOptionData *data) const; PRStatus Listen(PRIntn backlog); PRInt16 Poll(PRInt16 in_flags, PRInt16 *out_flags); PRInt32 Recv( void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout); PRInt32 Recvfrom( void *buf, PRSize amount, PRIntn flags, RCNetAddr* addr, const RCInterval& timeout); PRInt32 Send( const void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout); PRInt32 Sendto( const void *buf, PRSize amount, PRIntn flags, const RCNetAddr& addr, const RCInterval& timeout); PRStatus SetSocketOption(const PRSocketOptionData *data); PRStatus Shutdown(RCIO::ShutdownHow how); PRInt32 TransmitFile( RCIO *source, const void *headers, PRSize hlen, RCIO::FileDisposition flags, const RCInterval& timeout); public: /* ** The following function return a valid normal file object, ** Such objects can be used for scanned input and console output. */ typedef enum { input = PR_StandardInput, output = PR_StandardOutput, error = PR_StandardError } SpecialFile; static RCIO *GetSpecialFile(RCFileIO::SpecialFile special); }; /* RCFileIO */ class PR_IMPLEMENT(RCFileInfo): public RCBase { public: typedef enum { file = PR_FILE_FILE, directory = PR_FILE_DIRECTORY, other = PR_FILE_OTHER } FileType; public: RCFileInfo(); RCFileInfo(const RCFileInfo&); virtual ~RCFileInfo(); PRInt64 Size() const; RCTime CreationTime() const; RCTime ModifyTime() const; RCFileInfo::FileType Type() const; friend PRStatus RCFileIO::FileInfo(RCFileInfo*) const; friend PRStatus RCFileIO::FileInfo(const char *name, RCFileInfo*); private: PRFileInfo64 info; }; /* RCFileInfo */ inline RCFileInfo::RCFileInfo(): RCBase() { } inline PRInt64 RCFileInfo::Size() const { return info.size; } #endif /* defined(_RCFILEIO_H) */ nspr-4.11/nspr/pr/src/cplus/rcinrval.cpp0000644000000000000000000000213712623070344016417 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** C++ interval times (ref: prinrval.h) ** ** An interval is a period of time. The start of the interval (epoch) ** must be defined by the application. The unit of time of an interval ** is platform dependent, therefore so is the maximum interval that is ** representable. However, that interval is never less that ~12 hours. */ #include "rcinrval.h" RCInterval::~RCInterval() { } RCInterval::RCInterval(RCInterval::RCReservedInterval special): RCBase() { switch (special) { case RCInterval::now: interval = PR_IntervalNow(); break; case RCInterval::no_timeout: interval = PR_INTERVAL_NO_TIMEOUT; break; case RCInterval::no_wait: interval = PR_INTERVAL_NO_WAIT; break; default: break; } } /* RCInterval::RCInterval */ /* rcinrval.cpp */ nspr-4.11/nspr/pr/src/cplus/rcinrval.h0000644000000000000000000001137412623070344016067 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** C++ interval times (ref: prinrval.h) ** ** An interval is a period of time. The start of the interval (epoch) ** must be defined by the application. The unit of time of an interval ** is platform dependent, therefore so is the maximum interval that is ** representable. However, that interval is never less than ~6 hours. */ #if defined(_RCINTERVAL_H) #else #define _RCINTERVAL_H #include "rcbase.h" #include class PR_IMPLEMENT(RCInterval): public RCBase { public: typedef enum {now, no_timeout, no_wait} RCReservedInterval; virtual ~RCInterval(); RCInterval(); RCInterval(PRIntervalTime interval); RCInterval(const RCInterval& copy); RCInterval(RCReservedInterval special); void SetToNow(); void operator=(const RCInterval&); void operator=(PRIntervalTime interval); PRBool operator<(const RCInterval&); PRBool operator>(const RCInterval&); PRBool operator==(const RCInterval&); PRBool operator>=(const RCInterval&); PRBool operator<=(const RCInterval&); RCInterval operator+(const RCInterval&); RCInterval operator-(const RCInterval&); RCInterval& operator+=(const RCInterval&); RCInterval& operator-=(const RCInterval&); RCInterval operator/(PRUint32); RCInterval operator*(PRUint32); RCInterval& operator/=(PRUint32); RCInterval& operator*=(PRUint32); PRUint32 ToSeconds() const; PRUint32 ToMilliseconds() const; PRUint32 ToMicroseconds() const; operator PRIntervalTime() const; static PRIntervalTime FromSeconds(PRUint32 seconds); static PRIntervalTime FromMilliseconds(PRUint32 milli); static PRIntervalTime FromMicroseconds(PRUint32 micro); friend class RCCondition; private: PRIntervalTime interval; }; /* RCInterval */ inline RCInterval::RCInterval(): RCBase() { } inline RCInterval::RCInterval(const RCInterval& his): RCBase() { interval = his.interval; } inline RCInterval::RCInterval(PRIntervalTime ticks): RCBase() { interval = ticks; } inline void RCInterval::SetToNow() { interval = PR_IntervalNow(); } inline void RCInterval::operator=(const RCInterval& his) { interval = his.interval; } inline void RCInterval::operator=(PRIntervalTime his) { interval = his; } inline PRBool RCInterval::operator==(const RCInterval& his) { return (interval == his.interval) ? PR_TRUE : PR_FALSE; } inline PRBool RCInterval::operator<(const RCInterval& his) { return (interval < his.interval)? PR_TRUE : PR_FALSE; } inline PRBool RCInterval::operator>(const RCInterval& his) { return (interval > his.interval) ? PR_TRUE : PR_FALSE; } inline PRBool RCInterval::operator<=(const RCInterval& his) { return (interval <= his.interval) ? PR_TRUE : PR_FALSE; } inline PRBool RCInterval::operator>=(const RCInterval& his) { return (interval <= his.interval) ? PR_TRUE : PR_FALSE; } inline RCInterval RCInterval::operator+(const RCInterval& his) { return RCInterval((PRIntervalTime)(interval + his.interval)); } inline RCInterval RCInterval::operator-(const RCInterval& his) { return RCInterval((PRIntervalTime)(interval - his.interval)); } inline RCInterval& RCInterval::operator+=(const RCInterval& his) { interval += his.interval; return *this; } inline RCInterval& RCInterval::operator-=(const RCInterval& his) { interval -= his.interval; return *this; } inline RCInterval RCInterval::operator/(PRUint32 him) { return RCInterval((PRIntervalTime)(interval / him)); } inline RCInterval RCInterval::operator*(PRUint32 him) { return RCInterval((PRIntervalTime)(interval * him)); } inline RCInterval& RCInterval::operator/=(PRUint32 him) { interval /= him; return *this; } inline RCInterval& RCInterval::operator*=(PRUint32 him) { interval *= him; return *this; } inline PRUint32 RCInterval::ToSeconds() const { return PR_IntervalToSeconds(interval); } inline PRUint32 RCInterval::ToMilliseconds() const { return PR_IntervalToMilliseconds(interval); } inline PRUint32 RCInterval::ToMicroseconds() const { return PR_IntervalToMicroseconds(interval); } inline RCInterval::operator PRIntervalTime() const { return interval; } inline PRIntervalTime RCInterval::FromSeconds(PRUint32 seconds) { return PR_SecondsToInterval(seconds); } inline PRIntervalTime RCInterval::FromMilliseconds(PRUint32 milli) { return PR_MillisecondsToInterval(milli); } inline PRIntervalTime RCInterval::FromMicroseconds(PRUint32 micro) { return PR_MicrosecondsToInterval(micro); } #endif /* defined(_RCINTERVAL_H) */ /* RCInterval.h */ nspr-4.11/nspr/pr/src/cplus/rcio.cpp0000644000000000000000000000064512623070344015535 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Base class implmenation for I/O (ref: prio.h) */ #include "rcio.h" RCIO::~RCIO() { } RCIO::RCIO(RCIO::RCIOType): RCBase() { } nspr-4.11/nspr/pr/src/cplus/rcio.h0000644000000000000000000001057212623070344015202 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Base class definitions for I/O (ref: prio.h) ** ** This class is a virtual base class. Construction must be done by a ** subclass, but the I/O operations can be done on a RCIO object reference. */ #if defined(_RCIO_H) #else #define _RCIO_H #include "rcbase.h" #include "rcnetdb.h" #include "rcinrval.h" #include "prio.h" class RCFileInfo; class PR_IMPLEMENT(RCIO): public RCBase { public: typedef enum { open = PR_TRANSMITFILE_KEEP_OPEN, /* socket is left open after file * is transmitted. */ close = PR_TRANSMITFILE_CLOSE_SOCKET/* socket is closed after file * is transmitted. */ } FileDisposition; typedef enum { set = PR_SEEK_SET, /* Set to value specified */ current = PR_SEEK_CUR, /* Seek relative to current position */ end = PR_SEEK_END /* seek past end of current eof */ } Whence; typedef enum { recv = PR_SHUTDOWN_RCV, /* receives will be disallowed */ send = PR_SHUTDOWN_SEND, /* sends will be disallowed */ both = PR_SHUTDOWN_BOTH /* sends & receives will be disallowed */ } ShutdownHow; public: virtual ~RCIO(); virtual RCIO* Accept(RCNetAddr* addr, const RCInterval& timeout) = 0; virtual PRInt32 AcceptRead( RCIO **nd, RCNetAddr **raddr, void *buf, PRSize amount, const RCInterval& timeout) = 0; virtual PRInt64 Available() = 0; virtual PRStatus Bind(const RCNetAddr& addr) = 0; virtual PRStatus Close() = 0; virtual PRStatus Connect( const RCNetAddr& addr, const RCInterval& timeout) = 0; virtual PRStatus FileInfo(RCFileInfo *info) const = 0; virtual PRStatus Fsync() = 0; virtual PRStatus GetLocalName(RCNetAddr *addr) const = 0; virtual PRStatus GetPeerName(RCNetAddr *addr) const = 0; virtual PRStatus GetSocketOption(PRSocketOptionData *data) const = 0; virtual PRStatus Listen(PRIntn backlog) = 0; virtual PRStatus Open(const char *name, PRIntn flags, PRIntn mode) = 0; virtual PRInt16 Poll(PRInt16 in_flags, PRInt16 *out_flags) = 0; virtual PRInt32 Read(void *buf, PRSize amount) = 0; virtual PRInt32 Recv( void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout) = 0; virtual PRInt32 Recvfrom( void *buf, PRSize amount, PRIntn flags, RCNetAddr* addr, const RCInterval& timeout) = 0; virtual PRInt64 Seek(PRInt64 offset, Whence how) = 0; virtual PRInt32 Send( const void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout) = 0; virtual PRInt32 Sendto( const void *buf, PRSize amount, PRIntn flags, const RCNetAddr& addr, const RCInterval& timeout) = 0; virtual PRStatus SetSocketOption(const PRSocketOptionData *data) = 0; virtual PRStatus Shutdown(ShutdownHow how) = 0; virtual PRInt32 TransmitFile( RCIO *source, const void *headers, PRSize hlen, RCIO::FileDisposition flags, const RCInterval& timeout) = 0; virtual PRInt32 Write(const void *buf, PRSize amount) = 0; virtual PRInt32 Writev( const PRIOVec *iov, PRSize size, const RCInterval& timeout) = 0; protected: typedef enum { file = PR_DESC_FILE, tcp = PR_DESC_SOCKET_TCP, udp = PR_DESC_SOCKET_UDP, layered = PR_DESC_LAYERED} RCIOType; RCIO(RCIOType); PRFileDesc *fd; /* where the real code hides */ private: /* no default construction and no copies allowed */ RCIO(); RCIO(const RCIO&); }; /* RCIO */ #endif /* defined(_RCIO_H) */ /* RCIO.h */ nspr-4.11/nspr/pr/src/cplus/rclock.cpp0000644000000000000000000000155012623070344016052 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** C++ access to NSPR locks (PRLock) */ #include "rclock.h" #include RCLock::RCLock() { lock = PR_NewLock(); /* it might be NULL */ PR_ASSERT(NULL != lock); } /* RCLock::RCLock */ RCLock::~RCLock() { if (NULL != lock) PR_DestroyLock(lock); lock = NULL; } /* RCLock::~RCLock */ void RCLock::Acquire() { PR_ASSERT(NULL != lock); PR_Lock(lock); } /* RCLock::Acquire */ void RCLock::Release() { PRStatus rv; PR_ASSERT(NULL != lock); rv = PR_Unlock(lock); PR_ASSERT(PR_SUCCESS == rv); } /* RCLock::Release */ /* RCLock.cpp */ nspr-4.11/nspr/pr/src/cplus/rclock.h0000644000000000000000000000307312623070344015521 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** C++ access to NSPR locks (PRLock) */ #if defined(_RCLOCK_H) #else #define _RCLOCK_H #include "rcbase.h" #include class PR_IMPLEMENT(RCLock): public RCBase { public: RCLock(); virtual ~RCLock(); void Acquire(); /* non-reentrant */ void Release(); /* should be by owning thread */ friend class RCCondition; private: RCLock(const RCLock&); /* can't do that */ void operator=(const RCLock&); /* nor that */ PRLock *lock; }; /* RCLock */ /* ** Class: RCEnter ** ** In scope locks. You can only allocate them on the stack. The language ** will insure that they get released (by calling the destructor) when ** the thread leaves scope, even if via an exception. */ class PR_IMPLEMENT(RCEnter) { public: ~RCEnter(); /* releases the lock */ RCEnter(RCLock*); /* acquires the lock */ private: RCLock *lock; RCEnter(); RCEnter(const RCEnter&); void operator=(const RCEnter&); void *operator new(PRSize) { return NULL; } void operator delete(void*) { } }; /* RCEnter */ inline RCEnter::RCEnter(RCLock* ml) { lock = ml; lock->Acquire(); } inline RCEnter::~RCEnter() { lock->Release(); lock = NULL; } #endif /* defined(_RCLOCK_H) */ /* RCLock.h */ nspr-4.11/nspr/pr/src/cplus/rcmon.h0000644000000000000000000000224712623070344015364 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Class: RCMonitor (ref prmonitor.h) ** ** RCMonitor.h - C++ wrapper around NSPR's monitors */ #if defined(_RCMONITOR_H) #else #define _RCMONITOR_H #include "rcbase.h" #include "rcinrval.h" struct PRMonitor; class PR_IMPLEMENT(RCMonitor): public RCBase { public: RCMonitor(); /* timeout is infinity */ virtual ~RCMonitor(); virtual void Enter(); /* reentrant entry */ virtual void Exit(); virtual void Notify(); /* possibly enable one thread */ virtual void NotifyAll(); /* enable all waiters */ virtual void Wait(); /* applies object's timeout */ virtual void SetTimeout(const RCInterval& timeout); private: PRMonitor *monitor; RCInterval timeout; public: RCInterval GetTimeout() const; /* get the current value */ }; /* RCMonitor */ #endif /* defined(_RCMONITOR_H) */ /* RCMonitor.h */ nspr-4.11/nspr/pr/src/cplus/rcnetdb.cpp0000644000000000000000000001310212623070344016212 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Base class implementation for network access functions (ref: prnetdb.h) */ #include "rclock.h" #include "rcnetdb.h" #include #include #include RCNetAddr::RCNetAddr(const RCNetAddr& his): RCBase() { address = his.address; } RCNetAddr::RCNetAddr(const RCNetAddr& his, PRUint16 port): RCBase() { address = his.address; switch (address.raw.family) { case PR_AF_INET: address.inet.port = port; break; case PR_AF_INET6: address.ipv6.port = port; break; default: break; } } /* RCNetAddr::RCNetAddr */ RCNetAddr::RCNetAddr(RCNetAddr::HostValue host, PRUint16 port): RCBase() { PRNetAddrValue how; switch (host) { case RCNetAddr::any: how = PR_IpAddrAny; break; case RCNetAddr::loopback: how = PR_IpAddrLoopback; break; default: PR_NOT_REACHED("This can't happen -- and did!"); } (void)PR_InitializeNetAddr(how, port, &address); } /* RCNetAddr::RCNetAddr */ RCNetAddr::~RCNetAddr() { } void RCNetAddr::operator=(const RCNetAddr& his) { address = his.address; } PRStatus RCNetAddr::FromString(const char* string) { return PR_StringToNetAddr(string, &address); } void RCNetAddr::operator=(const PRNetAddr* addr) { address = *addr; } PRBool RCNetAddr::operator==(const RCNetAddr& his) const { PRBool rv = EqualHost(his); if (rv) { switch (address.raw.family) { case PR_AF_INET: rv = (address.inet.port == his.address.inet.port); break; case PR_AF_INET6: rv = (address.ipv6.port == his.address.ipv6.port); break; case PR_AF_LOCAL: default: break; } } return rv; } /* RCNetAddr::operator== */ PRBool RCNetAddr::EqualHost(const RCNetAddr& his) const { PRBool rv; switch (address.raw.family) { case PR_AF_INET: rv = (address.inet.ip == his.address.inet.ip); break; case PR_AF_INET6: rv = (0 == memcmp( &address.ipv6.ip, &his.address.ipv6.ip, sizeof(address.ipv6.ip))); break; #if defined(XP_UNIX) case PR_AF_LOCAL: rv = (0 == strncmp( address.local.path, his.address.local.path, sizeof(address.local.path))); break; #endif default: break; } return rv; } /* RCNetAddr::operator== */ PRStatus RCNetAddr::ToString(char *string, PRSize size) const { return PR_NetAddrToString(&address, string, size); } /* ** RCHostLookup */ RCHostLookup::~RCHostLookup() { if (NULL != address) delete [] address; } /* RCHostLookup::~RCHostLookup */ RCHostLookup::RCHostLookup(): RCBase() { address = NULL; max_index = 0; } /* RCHostLookup::RCHostLookup */ PRStatus RCHostLookup::ByName(const char* name) { PRStatus rv; PRNetAddr addr; PRHostEnt hostentry; PRIntn index = 0, max; RCNetAddr* vector = NULL; RCNetAddr* old_vector = NULL; void* buffer = PR_Malloc(PR_NETDB_BUF_SIZE); if (NULL == buffer) return PR_FAILURE; rv = PR_GetHostByName(name, (char*)buffer, PR_NETDB_BUF_SIZE, &hostentry); if (PR_SUCCESS == rv) { for (max = 0, index = 0;; ++max) { index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr); if (0 == index) break; } if (max > 0) { vector = new RCNetAddr[max]; while (--max > 0) { index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr); if (0 == index) break; vector[index] = &addr; } { RCEnter entry(&ml); old_vector = address; address = vector; max_index = max; } if (NULL != old_vector) delete [] old_vector; } } if (NULL != buffer) PR_DELETE(buffer); return PR_SUCCESS; } /* RCHostLookup::ByName */ PRStatus RCHostLookup::ByAddress(const RCNetAddr& host_addr) { PRStatus rv; PRNetAddr addr; PRHostEnt hostentry; PRIntn index = 0, max; RCNetAddr* vector = NULL; RCNetAddr* old_vector = NULL; char *buffer = (char*)PR_Malloc(PR_NETDB_BUF_SIZE); if (NULL == buffer) return PR_FAILURE; rv = PR_GetHostByAddr(host_addr, buffer, PR_NETDB_BUF_SIZE, &hostentry); if (PR_SUCCESS == rv) { for (max = 0, index = 0;; ++max) { index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr); if (0 == index) break; } if (max > 0) { vector = new RCNetAddr[max]; while (--max > 0) { index = PR_EnumerateHostEnt(index, &hostentry, 0, &addr); if (0 == index) break; vector[index] = &addr; } { RCEnter entry(&ml); old_vector = address; address = vector; max_index = max; } if (NULL != old_vector) delete [] old_vector; } } if (NULL != buffer) PR_DELETE(buffer); return PR_SUCCESS; } /* RCHostLookup::ByAddress */ const RCNetAddr* RCHostLookup::operator[](PRUintn which) { RCNetAddr* addr = NULL; if (which < max_index) addr = &address[which]; return addr; } /* RCHostLookup::operator[] */ /* RCNetdb.cpp */ nspr-4.11/nspr/pr/src/cplus/rcnetdb.h0000644000000000000000000000532512623070344015667 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Base class definitions for network access functions (ref: prnetdb.h) */ #if defined(_RCNETDB_H) #else #define _RCNETDB_H #include "rclock.h" #include "rcbase.h" #include class PR_IMPLEMENT(RCNetAddr): public RCBase { public: typedef enum { any = PR_IpAddrAny, /* assign logical INADDR_ANY */ loopback = PR_IpAddrLoopback /* assign logical INADDR_LOOPBACK */ } HostValue; RCNetAddr(); /* default constructor is unit'd object */ RCNetAddr(const RCNetAddr&); /* copy constructor */ RCNetAddr(HostValue, PRUint16 port);/* init'd w/ 'special' assignments */ RCNetAddr(const RCNetAddr&, PRUint16 port); /* copy w/ port reassigment */ virtual ~RCNetAddr(); void operator=(const RCNetAddr&); virtual PRBool operator==(const RCNetAddr&) const; /* compare of all relavent fields */ virtual PRBool EqualHost(const RCNetAddr&) const; /* compare of just host field */ public: void operator=(const PRNetAddr*); /* construction from more primitive data */ operator const PRNetAddr*() const; /* extraction of underlying representation */ virtual PRStatus FromString(const char* string); /* initialization from an ASCII string */ virtual PRStatus ToString(char *string, PRSize size) const; /* convert internal fromat to a string */ private: PRNetAddr address; }; /* RCNetAddr */ /* ** Class: RCHostLookup ** ** Abstractions to look up host names and addresses. ** ** This is a stateful class. One looks up the host by name or by ** address, then enumerates over a possibly empty array of network ** addresses. The storage for the addresses is owned by the class. */ class RCHostLookup: public RCBase { public: virtual ~RCHostLookup(); RCHostLookup(); virtual PRStatus ByName(const char* name); virtual PRStatus ByAddress(const RCNetAddr&); virtual const RCNetAddr* operator[](PRUintn); private: RCLock ml; PRIntn max_index; RCNetAddr* address; RCHostLookup(const RCHostLookup&); RCHostLookup& operator=(const RCHostLookup&); }; inline RCNetAddr::RCNetAddr(): RCBase() { } inline RCNetAddr::operator const PRNetAddr*() const { return &address; } #endif /* defined(_RCNETDB_H) */ /* RCNetdb.h */ nspr-4.11/nspr/pr/src/cplus/rcnetio.cpp0000644000000000000000000001222212623070344016236 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Subclass implementation for streamed network I/O (ref: prio.h) */ #include "rcnetio.h" #include RCNetStreamIO::~RCNetStreamIO() { PRStatus rv = (fd->methods->close)(fd); fd = NULL; } RCNetStreamIO::RCNetStreamIO(): RCIO(RCIO::tcp) { fd = PR_NewTCPSocket(); } RCNetStreamIO::RCNetStreamIO(PRIntn protocol): RCIO(RCIO::tcp) { fd = PR_Socket(PR_AF_INET, PR_SOCK_STREAM, protocol); } RCIO* RCNetStreamIO::Accept(RCNetAddr* addr, const RCInterval& timeout) { PRNetAddr peer; RCNetStreamIO* rcio = NULL; PRFileDesc* newfd = fd->methods->accept(fd, &peer, timeout); if (NULL != newfd) { rcio = new RCNetStreamIO(); if (NULL != rcio) { *addr = &peer; rcio->fd = newfd; } else (void)(newfd->methods->close)(newfd); } return rcio; } /* RCNetStreamIO::Accept */ PRInt32 RCNetStreamIO::AcceptRead( RCIO **nd, RCNetAddr **raddr, void *buf, PRSize amount, const RCInterval& timeout) { PRNetAddr *from; PRFileDesc *accepted; PRInt32 rv = (fd->methods->acceptread)( fd, &accepted, &from, buf, amount, timeout); if (rv >= 0) { RCNetStreamIO *ns = new RCNetStreamIO(); if (NULL != *nd) ns->fd = accepted; else {PR_Close(accepted); rv = -1; } *nd = ns; } return rv; } /* RCNetStreamIO::AcceptRead */ PRInt64 RCNetStreamIO::Available() { return (fd->methods->available64)(fd); } PRStatus RCNetStreamIO::Bind(const RCNetAddr& addr) { return (fd->methods->bind)(fd, addr); } PRStatus RCNetStreamIO::Connect(const RCNetAddr& addr, const RCInterval& timeout) { return (fd->methods->connect)(fd, addr, timeout); } PRStatus RCNetStreamIO::GetLocalName(RCNetAddr *addr) const { PRNetAddr local; PRStatus rv = (fd->methods->getsockname)(fd, &local); if (PR_SUCCESS == rv) *addr = &local; return rv; } /* RCNetStreamIO::GetLocalName */ PRStatus RCNetStreamIO::GetPeerName(RCNetAddr *addr) const { PRNetAddr peer; PRStatus rv = (fd->methods->getpeername)(fd, &peer); if (PR_SUCCESS == rv) *addr = &peer; return rv; } /* RCNetStreamIO::GetPeerName */ PRStatus RCNetStreamIO::GetSocketOption(PRSocketOptionData *data) const { return (fd->methods->getsocketoption)(fd, data); } PRStatus RCNetStreamIO::Listen(PRIntn backlog) { return (fd->methods->listen)(fd, backlog); } PRInt16 RCNetStreamIO::Poll(PRInt16 in_flags, PRInt16 *out_flags) { return (fd->methods->poll)(fd, in_flags, out_flags); } PRInt32 RCNetStreamIO::Read(void *buf, PRSize amount) { return (fd->methods->read)(fd, buf, amount); } PRInt32 RCNetStreamIO::Recv( void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout) { return (fd->methods->recv)(fd, buf, amount, flags, timeout); } PRInt32 RCNetStreamIO::Recvfrom( void *buf, PRSize amount, PRIntn flags, RCNetAddr* addr, const RCInterval& timeout) { PRNetAddr peer; PRInt32 rv = (fd->methods->recvfrom)( fd, buf, amount, flags, &peer, timeout); if (-1 != rv) *addr = &peer; return rv; } /* RCNetStreamIO::Recvfrom */ PRInt32 RCNetStreamIO::Send( const void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout) { return (fd->methods->send)(fd, buf, amount, flags, timeout); } PRInt32 RCNetStreamIO::Sendto( const void *buf, PRSize amount, PRIntn flags, const RCNetAddr& addr, const RCInterval& timeout) { return (fd->methods->sendto)(fd, buf, amount, flags, addr, timeout); } PRStatus RCNetStreamIO::SetSocketOption(const PRSocketOptionData *data) { return (fd->methods->setsocketoption)(fd, data); } PRStatus RCNetStreamIO::Shutdown(RCIO::ShutdownHow how) { return (fd->methods->shutdown)(fd, (PRIntn)how); } PRInt32 RCNetStreamIO::TransmitFile( RCIO *source, const void *headers, PRSize hlen, RCIO::FileDisposition flags, const RCInterval& timeout) { RCNetStreamIO *src = (RCNetStreamIO*)source; return (fd->methods->transmitfile)( fd, src->fd, headers, hlen, (PRTransmitFileFlags)flags, timeout); } PRInt32 RCNetStreamIO::Write(const void *buf, PRSize amount) { return (fd->methods->write)(fd, buf, amount); } PRInt32 RCNetStreamIO::Writev( const PRIOVec *iov, PRSize size, const RCInterval& timeout) { return (fd->methods->writev)(fd, iov, size, timeout); } /* ** Invalid functions */ PRStatus RCNetStreamIO::Close() { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCNetStreamIO::FileInfo(RCFileInfo*) const { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRStatus RCNetStreamIO::Fsync() { return (fd->methods->fsync)(fd); } PRStatus RCNetStreamIO::Open(const char*, PRIntn, PRIntn) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } PRInt64 RCNetStreamIO::Seek(PRInt64, RCIO::Whence) { PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } /* RCNetStreamIO.cpp */ nspr-4.11/nspr/pr/src/cplus/rcnetio.h0000644000000000000000000000647212623070344015715 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Subclass definitions for network I/O (ref: prio.h) */ #if defined(_RCNETIO_H) #else #define _RCNETIO_H #include "rcbase.h" #include "rcinrval.h" #include "rcio.h" #include "rcnetdb.h" #include "prio.h" class RCFileInfo; /* ** Class: RCNetStreamIO (ref prio.h) ** ** Streamed (reliable) network I/O (e.g., TCP). ** This class hides (makes private) the functions that are not applicable ** to network I/O (i.e., those for file I/O). */ class PR_IMPLEMENT(RCNetStreamIO): public RCIO { public: RCNetStreamIO(); virtual ~RCNetStreamIO(); virtual RCIO* Accept(RCNetAddr* addr, const RCInterval& timeout); virtual PRInt32 AcceptRead( RCIO **nd, RCNetAddr **raddr, void *buf, PRSize amount, const RCInterval& timeout); virtual PRInt64 Available(); virtual PRStatus Bind(const RCNetAddr& addr); virtual PRStatus Connect( const RCNetAddr& addr, const RCInterval& timeout); virtual PRStatus GetLocalName(RCNetAddr *addr) const; virtual PRStatus GetPeerName(RCNetAddr *addr) const; virtual PRStatus GetSocketOption(PRSocketOptionData *data) const; virtual PRStatus Listen(PRIntn backlog); virtual PRInt16 Poll(PRInt16 in_flags, PRInt16 *out_flags); virtual PRInt32 Read(void *buf, PRSize amount); virtual PRInt32 Recv( void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout); virtual PRInt32 Recvfrom( void *buf, PRSize amount, PRIntn flags, RCNetAddr* addr, const RCInterval& timeout); virtual PRInt32 Send( const void *buf, PRSize amount, PRIntn flags, const RCInterval& timeout); virtual PRInt32 Sendto( const void *buf, PRSize amount, PRIntn flags, const RCNetAddr& addr, const RCInterval& timeout); virtual PRStatus SetSocketOption(const PRSocketOptionData *data); virtual PRStatus Shutdown(ShutdownHow how); virtual PRInt32 TransmitFile( RCIO *source, const void *headers, PRSize hlen, RCIO::FileDisposition flags, const RCInterval& timeout); virtual PRInt32 Write(const void *buf, PRSize amount); virtual PRInt32 Writev( const PRIOVec *iov, PRSize size, const RCInterval& timeout); private: /* functions unavailable to this clients of this class */ RCNetStreamIO(const RCNetStreamIO&); PRStatus Close(); PRStatus Open(const char *name, PRIntn flags, PRIntn mode); PRStatus FileInfo(RCFileInfo *info) const; PRStatus Fsync(); PRInt64 Seek(PRInt64 offset, RCIO::Whence how); public: RCNetStreamIO(PRIntn protocol); }; /* RCNetIO */ #endif /* defined(_RCNETIO_H) */ /* RCNetStreamIO.h */ nspr-4.11/nspr/pr/src/cplus/rcthread.cpp0000755000000000000000000001230312623070344016372 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* RCThread.cpp - C++ wrapper on NSPR */ #include "rcthread.h" #include "rcinrval.h" #include #include #include #include static RCPrimordialThread *primordial = NULL; void nas_Root(void *arg) { RCThread *him = (RCThread*)arg; while (RCThread::ex_unstarted == him->execution) (void)PR_Sleep(PR_INTERVAL_NO_TIMEOUT); /* wait for Start() */ him->RootFunction(); /* he gets a self reference */ if (PR_UNJOINABLE_THREAD == PR_GetThreadState(him->identity)) delete him; } /* nas_Root */ RCThread::~RCThread() { } RCThread::RCThread(): RCBase() { } RCThread::RCThread(const RCThread&): RCBase() { PR_NOT_REACHED("Cannot call thread copy constructor"); } /* RCThread::RCThread */ RCThread::RCThread( RCThread::Scope scope, RCThread::State join, PRUint32 stackSize): RCBase() { execution = ex_unstarted; identity = PR_CreateThread( PR_USER_THREAD, nas_Root, this, PR_GetThreadPriority(PR_GetCurrentThread()), (PRThreadScope)scope, (PRThreadState)join, stackSize); } /* RCThread::RCThread */ void RCThread::operator=(const RCThread&) { PR_NOT_REACHED("Cannot call thread assignment operator"); } /* RCThread::operator= */ PRStatus RCThread::Start() { PRStatus rv; /* This is an unsafe check, but not too critical */ if (RCThread::ex_unstarted == execution) { execution = RCThread::ex_started; rv = PR_Interrupt(identity); PR_ASSERT(PR_SUCCESS == rv); } else { rv = PR_FAILURE; PR_SetError(PR_INVALID_STATE_ERROR, 0); } return rv; } /* RCThread::Start */ PRStatus RCThread::Join() { PRStatus rv; if (RCThread::ex_unstarted == execution) { rv = PR_FAILURE; PR_SetError(PR_INVALID_STATE_ERROR, 0); } else rv = PR_JoinThread(identity); if (PR_SUCCESS == rv) delete this; return rv; } /* RCThread::Join */ PRStatus RCThread::Interrupt() { PRStatus rv; if (RCThread::ex_unstarted == execution) { rv = PR_FAILURE; PR_SetError(PR_INVALID_STATE_ERROR, 0); } else rv = PR_Interrupt(identity); return rv; } /* RCThread::Interrupt */ void RCThread::ClearInterrupt() { PR_ClearInterrupt(); } void RCThread::SetPriority(RCThread::Priority new_priority) { PR_SetThreadPriority(identity, (PRThreadPriority)new_priority); } PRThread *RCThread::Self() { return PR_GetCurrentThread(); } RCThread::Scope RCThread::GetScope() const { return (RCThread::Scope)PR_GetThreadScope(identity); } RCThread::State RCThread::GetState() const { return (RCThread::State)PR_GetThreadState(identity); } RCThread::Priority RCThread::GetPriority() const { return (RCThread::Priority)PR_GetThreadPriority(identity); } static void _rc_PDDestructor(RCThreadPrivateData* privateData) { PR_ASSERT(NULL != privateData); privateData->Release(); } static PRThreadPrivateDTOR _tpd_dtor = (PRThreadPrivateDTOR)_rc_PDDestructor; PRStatus RCThread::NewPrivateIndex(PRUintn* index) { return PR_NewThreadPrivateIndex(index, _tpd_dtor); } PRStatus RCThread::SetPrivateData(PRUintn index) { return PR_SetThreadPrivate(index, NULL); } PRStatus RCThread::SetPrivateData(PRUintn index, RCThreadPrivateData* data) { return PR_SetThreadPrivate(index, data); } RCThreadPrivateData* RCThread::GetPrivateData(PRUintn index) { return (RCThreadPrivateData*)PR_GetThreadPrivate(index); } PRStatus RCThread::Sleep(const RCInterval& ticks) { PRIntervalTime tmo = ticks; return PR_Sleep(tmo); } RCPrimordialThread *RCThread::WrapPrimordialThread() { /* ** This needs to take more care in insuring that the thread ** being wrapped is really the primordial thread. This code ** is assuming that the caller is the primordial thread, and ** there's nothing to insure that. */ if (NULL == primordial) { /* it doesn't have to be perfect */ RCPrimordialThread *me = new RCPrimordialThread(); PR_ASSERT(NULL != me); if (NULL == primordial) { primordial = me; me->execution = RCThread::ex_started; me->identity = PR_GetCurrentThread(); } else delete me; /* somebody beat us to it */ } return primordial; } /* RCThread::WrapPrimordialThread */ RCPrimordialThread::RCPrimordialThread(): RCThread() { } RCPrimordialThread::~RCPrimordialThread() { } void RCPrimordialThread::RootFunction() { PR_NOT_REACHED("Primordial thread calling root function"); } /* RCPrimordialThread::RootFunction */ PRStatus RCPrimordialThread::Cleanup() { return PR_Cleanup(); } PRStatus RCPrimordialThread::SetVirtualProcessors(PRIntn count) { PR_SetConcurrency(count); return PR_SUCCESS; } /* SetVirutalProcessors */ RCThreadPrivateData::RCThreadPrivateData() { } RCThreadPrivateData::RCThreadPrivateData( const RCThreadPrivateData& him) { } RCThreadPrivateData::~RCThreadPrivateData() { } /* RCThread.c */ nspr-4.11/nspr/pr/src/cplus/rcthread.h0000644000000000000000000001211212623070344016032 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* RCThread.h */ #if defined(_RCTHREAD_H) #else #define _RCTHREAD_H #include "rcbase.h" #include class RCInterval; class PR_IMPLEMENT(RCThreadPrivateData) { public: RCThreadPrivateData(); RCThreadPrivateData(const RCThreadPrivateData&); virtual ~RCThreadPrivateData(); virtual void Release() = 0; }; /* RCThreadPrivateData */ class PR_IMPLEMENT(RCThread): public RCBase { public: typedef enum { local = PR_LOCAL_THREAD, global = PR_GLOBAL_THREAD } Scope; typedef enum { joinable = PR_JOINABLE_THREAD, unjoinable = PR_UNJOINABLE_THREAD } State; typedef enum { first = PR_PRIORITY_FIRST, low = PR_PRIORITY_LOW, normal = PR_PRIORITY_NORMAL, high = PR_PRIORITY_HIGH, urgent = PR_PRIORITY_URGENT, last = PR_PRIORITY_LAST } Priority; /* * Create a new thread, providing scope and joinability state. */ RCThread(Scope scope, State state, PRUint32 stackSize=0); /* * New threads are created in a suspended state. It must be 'started" * before it begins execution in the class' defined 'RootFunction()'. */ virtual PRStatus Start(); /* * If a thread is created joinable, then the thread's object exists * until join is called. The thread that calls join will block until * the target thread returns from it's root function. */ virtual PRStatus Join(); /* * The priority of a newly created thread is the same as the creator. * The priority may be changed either by the new thread itself, by * the creator or any other arbitrary thread. */ virtual void SetPriority(Priority newPriority); /* * Interrupt another thread, causing it to stop what it * is doing and return with a well known error code. */ virtual PRStatus Interrupt(); /* * And in case a thread was interrupted and didn't get a chance * to have the notification delivered, a way to cancel the pending * status. */ static void ClearInterrupt(); /* * Methods to discover the attributes of an existing thread. */ static PRThread *Self(); Scope GetScope() const; State GetState() const; Priority GetPriority() const; /* * Thread private data */ static PRStatus NewPrivateIndex(PRUintn* index); /* * Getting it - if you want to modify, make a copy */ static RCThreadPrivateData* GetPrivateData(PRUintn index); /* * Setting it to - deletes existing data */ static PRStatus SetPrivateData(PRUintn index); /* * Setting it - runtime will make a copy, freeing old iff necessary */ static PRStatus SetPrivateData(PRUintn index, RCThreadPrivateData* data); /* * Scheduling control */ static PRStatus Sleep(const RCInterval& ticks); friend void nas_Root(void*); friend class RCPrimordialThread; protected: /* * The instantiator of a class must not call the destructor. The base * implementation of Join will, and if the thread is created unjoinable, * then the code that called the RootFunction will call the desctructor. */ virtual ~RCThread(); private: /* * This is where a newly created thread begins execution. Returning * from this function is equivalent to terminating the thread. */ virtual void RootFunction() = 0; PRThread *identity; /* Threads are unstarted until started - pretty startling */ enum {ex_unstarted, ex_started} execution; /* There is no public default constructor or copy constructor */ RCThread(); RCThread(const RCThread&); /* And there is no assignment operator */ void operator=(const RCThread&); public: static RCPrimordialThread *WrapPrimordialThread(); }; /* ** class RCPrimordialThread */ class PR_IMPLEMENT(RCPrimordialThread): public RCThread { public: /* ** The primordial thread can (optionally) wait for all created ** threads to terminate before allowing the process to exit. ** Not calling Cleanup() before returning from main() will cause ** the immediate termination of the entire process, including ** any running threads. */ static PRStatus Cleanup(); /* ** Only the primordial thread is allowed to adjust the number of ** virtual processors of the runtime. It's a lame security thing. */ static PRStatus SetVirtualProcessors(PRIntn count=10); friend class RCThread; private: /* ** None other than the runtime can create of destruct ** a primordial thread. It is fabricated by the runtime ** to wrap the thread that initiated the application. */ RCPrimordialThread(); ~RCPrimordialThread(); void RootFunction(); }; /* RCPrimordialThread */ #endif /* defined(_RCTHREAD_H) */ nspr-4.11/nspr/pr/src/cplus/rctime.cpp0000644000000000000000000000214112623070344016055 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Class implementation for calendar time routines (ref: prtime.h) */ #include "rctime.h" RCTime::~RCTime() { } RCTime::RCTime(PRTime time): RCBase() { gmt = time; } RCTime::RCTime(const RCTime& his): RCBase() { gmt = his.gmt; } RCTime::RCTime(RCTime::Current): RCBase() { gmt = PR_Now(); } RCTime::RCTime(const PRExplodedTime& time): RCBase() { gmt = PR_ImplodeTime(&time); } void RCTime::operator=(const PRExplodedTime& time) { gmt = PR_ImplodeTime(&time); } RCTime RCTime::operator+(const RCTime& his) { RCTime sum(gmt + his.gmt); return sum; } RCTime RCTime::operator-(const RCTime& his) { RCTime difference(gmt - his.gmt); return difference; } RCTime RCTime::operator/(PRUint64 his) { RCTime quotient(gmt / gmt); return quotient; } RCTime RCTime::operator*(PRUint64 his) { RCTime product(gmt * his); return product; } nspr-4.11/nspr/pr/src/cplus/rctime.h0000644000000000000000000000655612623070344015540 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Class definitions for calendar time routines (ref: prtime.h) */ #if defined(_RCTIME_H) #else #define _RCTIME_H #include "rcbase.h" #include /* ** Class: RCTime (ref: prtime.h) ** ** RCTimes are objects that are intended to be used to represent calendar ** times. They maintain units internally as microseconds since the defined ** epoch (midnight, January 1, 1970, GMT). Conversions to and from external ** formats (PRExplodedTime) are available. ** ** In general, NCTimes possess normal algebretic capabilities. */ class PR_IMPLEMENT(RCTime): public RCBase { public: typedef enum {now} Current; RCTime(); /* leaves the object unitialized */ RCTime(Current); /* initializes to current system time */ RCTime(const RCTime&); /* copy constructor */ RCTime(const PRExplodedTime&); /* construction from exploded representation */ virtual ~RCTime(); /* assignment operators */ void operator=(const RCTime&); void operator=(const PRExplodedTime&); /* comparitive operators */ PRBool operator<(const RCTime&); PRBool operator>(const RCTime&); PRBool operator<=(const RCTime&); PRBool operator>=(const RCTime&); PRBool operator==(const RCTime&); /* associative operators */ RCTime operator+(const RCTime&); RCTime operator-(const RCTime&); RCTime& operator+=(const RCTime&); RCTime& operator-=(const RCTime&); /* multiply and divide operators */ RCTime operator/(PRUint64); RCTime operator*(PRUint64); RCTime& operator/=(PRUint64); RCTime& operator*=(PRUint64); void Now(); /* assign current time to object */ private: PRTime gmt; public: RCTime(PRTime); /* construct from raw PRTime */ void operator=(PRTime); /* assign from raw PRTime */ operator PRTime() const; /* extract internal representation */ }; /* RCTime */ inline RCTime::RCTime(): RCBase() { } inline void RCTime::Now() { gmt = PR_Now(); } inline RCTime::operator PRTime() const { return gmt; } inline void RCTime::operator=(PRTime his) { gmt = his; } inline void RCTime::operator=(const RCTime& his) { gmt = his.gmt; } inline PRBool RCTime::operator<(const RCTime& his) { return (gmt < his.gmt) ? PR_TRUE : PR_FALSE; } inline PRBool RCTime::operator>(const RCTime& his) { return (gmt > his.gmt) ? PR_TRUE : PR_FALSE; } inline PRBool RCTime::operator<=(const RCTime& his) { return (gmt <= his.gmt) ? PR_TRUE : PR_FALSE; } inline PRBool RCTime::operator>=(const RCTime& his) { return (gmt >= his.gmt) ? PR_TRUE : PR_FALSE; } inline PRBool RCTime::operator==(const RCTime& his) { return (gmt == his.gmt) ? PR_TRUE : PR_FALSE; } inline RCTime& RCTime::operator+=(const RCTime& his) { gmt += his.gmt; return *this; } inline RCTime& RCTime::operator-=(const RCTime& his) { gmt -= his.gmt; return *this; } inline RCTime& RCTime::operator/=(PRUint64 his) { gmt /= his; return *this; } inline RCTime& RCTime::operator*=(PRUint64 his) { gmt *= his; return *this; } #endif /* defined(_RCTIME_H) */ /* RCTime.h */ nspr-4.11/nspr/pr/src/cplus/tests/.cvsignore0000644000000000000000000000001112623070344017222 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/cplus/tests/Makefile.in0000644000000000000000000001253112623070344017301 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifeq ($(OS_TARGET), WIN16) OS_CFLAGS = $(OS_EXE_CFLAGS) endif CXXSRCS = \ ranfile.cpp \ thread.cpp \ interval.cpp \ time.cpp \ fileio.cpp \ switch.cpp \ tpd.cpp \ $(NULL) OBJS = $(addprefix $(OBJDIR)/,$(CXXSRCS:.cpp=.$(OBJ_SUFFIX))) ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) PROG_SUFFIX = .exe else PROG_SUFFIX = endif PROGS = $(addprefix $(OBJDIR)/, $(CXXSRCS:.cpp=$(PROG_SUFFIX))) TARGETS = $(PROGS) $(OBJS) INCLUDES = -I.. -I$(dist_includedir) # Setting the variables LDOPTS and LIBPR. We first initialize # them to the default values, then adjust them for some platforms. LDOPTS = -L$(dist_libdir) LIBPR = -lnspr$(MOD_MAJOR_VERSION) LIBPL = -lplc$(MOD_MAJOR_VERSION) ifeq ($(OS_ARCH), IRIX) LDOPTS += -rpath $(PWD)/$(dist_libdir) -rdata_shared # For 6.x machines, include this flag ifeq ($(basename $(OS_RELEASE)),6) ifeq ($(USE_N32),1) LDOPTS += -n32 else LDOPTS += -32 endif ifeq ($(USE_PTHREADS), 1) ifeq ($(OS_RELEASE), 6.2) LDOPTS += -Wl,-woff,85 endif endif endif endif # Solaris ifeq ($(OS_ARCH), SunOS) ifdef NS_USE_GCC LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir) else LDOPTS += -R $(PWD)/$(dist_libdir) endif # SunOS 5.5 needs to link with -lpthread, even though we already # linked with this system library when we built libnspr.so. ifeq ($(OS_RELEASE), 5.5) ifdef USE_PTHREADS EXTRA_LIBS = -lpthread endif endif endif # SunOS ifeq ($(OS_ARCH), WINNT) ifeq ($(OS_TARGET), WIN16) LIBPR = $(dist_libdir)/nspr$(MOD_MAJOR_VERSION).lib LIBPL = $(dist_libdir)/plc$(MOD_MAJOR_VERSION).lib else LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO LIBPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) LIBPL = $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).$(LIB_SUFFIX) endif endif ifeq ($(OS_ARCH),OS2) LDOPTS += -Zomf -Zlinker /PM:VIO -lstdcpp endif ifneq ($(OS_ARCH), WINNT) PWD = $(shell pwd) endif ifeq ($(OS_ARCH), OSF1) LDOPTS += -rpath $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), HP-UX) LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir) endif # AIX ifeq ($(OS_ARCH),AIX) LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib ifeq ($(OS_ARCH)$(OS_RELEASE),AIX4.1) LIBPR = -lnspr$(MOD_MAJOR_VERSION)_shr LIBPLC = -lplc$(MOD_MAJOR_VERSION)_shr else LDOPTS += -brtl EXTRA_LIBS = -ldl endif endif ifeq ($(OS_ARCH), Linux) ifeq ($(OS_RELEASE), 1.2) EXTRA_LIBS = -ldl else LDOPTS += -Xlinker -rpath $(PWD)/$(dist_libdir) ifeq ($(USE_PTHREADS),1) EXTRA_LIBS = -lpthread endif endif endif ifeq ($(OS_ARCH), SCO_SV) # SCO Unix needs to link against -lsocket again even though we # already linked with these system libraries when we built libnspr.so. EXTRA_LIBS = -lsocket # This hardcodes in the executable programs the directory to find # libnspr.so etc. at program startup. Equivalent to the -R or -rpath # option for ld on other platforms. export LD_RUN_PATH = $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), UNIXWARE) export LD_RUN_PATH = $(PWD)/$(dist_libdir) endif ##################################################### # # The rules # ##################################################### include $(topsrcdir)/config/rules.mk AIX_PRE_4_2 = 0 ifeq ($(OS_ARCH),AIX) ifneq ($(OS_RELEASE),4.2) ifneq ($(USE_PTHREADS), 1) #AIX_PRE_4_2 = 1 endif endif endif ifeq ($(AIX_PRE_4_2),1) # AIX releases prior to 4.2 need a special two-step linking hack # in order to both override the system select() and be able to # get at the original system select(). # # We use a pattern rule in ns/nspr20/config/rules.mk to generate # the .$(OBJ_SUFFIX) file from the .c source file, then do the # two-step linking hack below. $(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) rm -f $@ $(AIX_TMP) $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) rm -f $(AIX_TMP) else # All platforms that are not AIX pre-4.2. $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) ifeq ($(OS_ARCH), WINNT) ifeq ($(OS_TARGET),WIN16) echo system windows >w16link echo option map >>w16link echo option stack=10K >>w16link echo option heapsize=32K >>w16link echo debug $(DEBUGTYPE) all >>w16link echo name $@ >>w16link echo file >>w16link echo $< >>w16link echo library >>w16link echo $(LIBPR), >>w16link echo $(LIBPL), >>w16link echo winsock.lib >>w16link wlink @w16link. else link $(LDOPTS) $< $(LIBPR) $(LIBPL) ws2_32.lib -out:$@ endif else ifeq ($(OS_ARCH),OS2) $(LINK) $(LDOPTS) $< $(LIBGC) $(LIBPLC) $(LIBPR) $(OS_LIBS) $(EXTRA_LIBS) -o $@ else $(CCC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPL) $(EXTRA_LIBS) -o $@ endif endif endif export:: $(TARGETS) clean:: rm -f $(TARGETS) nspr-4.11/nspr/pr/src/cplus/tests/fileio.cpp0000644000000000000000000000146712623070344017215 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* fileio.cpp - a test program */ #include "rcfileio.h" #include #include #define DEFAULT_ITERATIONS 100 PRIntn main(PRIntn argc, char **argv) { PRStatus rv; RCFileIO fd; RCFileInfo info; rv = fd.Open("filio.dat", PR_CREATE_FILE, 0666); PR_ASSERT(PR_SUCCESS == rv); rv = fd.FileInfo(&info); PR_ASSERT(PR_SUCCESS == rv); rv = fd.Delete("filio.dat"); PR_ASSERT(PR_SUCCESS == rv); fd.Close(); PR_ASSERT(PR_SUCCESS == rv); return 0; } /* main */ /* interval.cpp */ nspr-4.11/nspr/pr/src/cplus/tests/interval.cpp0000644000000000000000000000516612623070344017572 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* interval.cpp - a test program */ #include "rclock.h" #include "rcthread.h" #include "rcinrval.h" #include "rccv.h" #include #include #include #define DEFAULT_ITERATIONS 100 PRIntn main(PRIntn argc, char **argv) { RCLock ml; PRStatus rv; RCCondition cv(&ml); RCInterval now, timeout, epoch, elapsed; PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput); PRIntn msecs, seconds, loops, iterations = DEFAULT_ITERATIONS; /* slow, agonizing waits */ for (seconds = 0; seconds < 10; ++seconds) { timeout = RCInterval::FromSeconds(seconds); cv.SetTimeout(timeout); { RCEnter lock(&ml); epoch.SetToNow(); rv = cv.Wait(); PR_ASSERT(PR_SUCCESS == rv); now = RCInterval(RCInterval::now); elapsed = now - epoch; } PR_fprintf( output, "Waiting %u seconds took %s%u milliseconds\n", seconds, ((elapsed < timeout)? "**" : ""), elapsed.ToMilliseconds()); } /* more slow, agonizing sleeps */ for (seconds = 0; seconds < 10; ++seconds) { timeout = RCInterval::FromSeconds(seconds); { epoch.SetToNow(); rv = RCThread::Sleep(timeout); PR_ASSERT(PR_SUCCESS == rv); now = RCInterval(RCInterval::now); elapsed = now - epoch; } PR_fprintf( output, "Sleeping %u seconds took %s%u milliseconds\n", seconds, ((elapsed < timeout)? "**" : ""), elapsed.ToMilliseconds()); } /* fast, spritely little devils */ for (msecs = 10; msecs < 100; msecs += 10) { timeout = RCInterval::FromMilliseconds(msecs); cv.SetTimeout(timeout); { RCEnter lock(&ml); epoch.SetToNow(); for (loops = 0; loops < iterations; ++loops) { rv = cv.Wait(); PR_ASSERT(PR_SUCCESS == rv); } now = RCInterval(RCInterval::now); elapsed = now - epoch; } elapsed /= iterations; PR_fprintf( output, "Waiting %u msecs took %s%u milliseconds average\n", msecs, ((elapsed < timeout)? "**" : ""), elapsed.ToMilliseconds()); } return 0; } /* main */ /* interval.cpp */ nspr-4.11/nspr/pr/src/cplus/tests/ranfile.cpp0000644000000000000000000003214212623070344017360 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Contact: AOF ** ** Name: ranfile.c ** ** Description: Test to hammer on various components of NSPR ** Modification History: ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include #include #include #include "rccv.h" #include "rcthread.h" #include "rcfileio.h" #include "rclock.h" #include #include #include static PRFileDesc *output; static PRIntn debug_mode = 0; static PRIntn failed_already = 0; class HammerData { public: typedef enum { sg_go, sg_stop, sg_done} Action; typedef enum { sg_okay, sg_open, sg_close, sg_delete, sg_write, sg_seek} Problem; virtual ~HammerData(); HammerData(RCLock* lock, RCCondition *cond, PRUint32 clip); virtual PRUint32 Random(); Action action; Problem problem; PRUint32 writes; RCInterval timein; friend class Hammer; private: RCLock *ml; RCCondition *cv; PRUint32 limit; PRFloat64 seed; }; /* HammerData */ class Hammer: public HammerData, public RCThread { public: virtual ~Hammer(); Hammer(RCThread::Scope scope, RCLock* lock, RCCondition *cond, PRUint32 clip); private: void RootFunction(); }; static PRInt32 pageSize = 1024; static const char* baseName = "./"; static const char *programName = "Random File"; /*********************************************************************** ** PRIVATE FUNCTION: Random ** DESCRIPTION: ** Generate a pseudo-random number ** INPUTS: None ** OUTPUTS: None ** RETURN: A pseudo-random unsigned number, 32-bits wide ** SIDE EFFECTS: ** Updates random seed (a static) ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: ** Uses the current interval timer value, promoted to a 64 bit ** float as a multiplier for a static residue (which begins ** as an uninitialized variable). The result is bits [16..48) ** of the product. Seed is then updated with the return value ** promoted to a float-64. ***********************************************************************/ PRUint32 HammerData::Random() { PRUint32 rv; PRUint64 shift; RCInterval now = RCInterval(RCInterval::now); PRFloat64 random = seed * (PRFloat64)((PRIntervalTime)now); LL_USHR(shift, *((PRUint64*)&random), 16); LL_L2UI(rv, shift); seed = (PRFloat64)rv; return rv; } /* HammerData::Random */ Hammer::~Hammer() { } Hammer::Hammer( RCThread::Scope scope, RCLock* lock, RCCondition *cond, PRUint32 clip): HammerData(lock, cond, clip), RCThread(scope, RCThread::joinable, 0) { } HammerData::~HammerData() { } HammerData::HammerData(RCLock* lock, RCCondition *cond, PRUint32 clip) { ml = lock; cv = cond; writes = 0; limit = clip; seed = 0x58a9382; action = HammerData::sg_go; problem = HammerData::sg_okay; timein = RCInterval(RCInterval::now); } /* HammerData::HammerData */ /*********************************************************************** ** PRIVATE FUNCTION: Hammer::RootFunction ** DESCRIPTION: ** Hammer on the file I/O system ** INPUTS: A pointer to the thread's private data ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** Creates, accesses and deletes a file ** RESTRICTIONS: ** (Currently) must have file create permission in "/usr/tmp". ** MEMORY: NA ** ALGORITHM: ** This function is a root of a thread ** 1) Creates a (hopefully) unique file in /usr/tmp/ ** 2) Writes a zero to a random number of sequential pages ** 3) Closes the file ** 4) Reopens the file ** 5) Seeks to a random page within the file ** 6) Writes a one byte on that page ** 7) Repeat steps [5..6] for each page in the file ** 8) Close and delete the file ** 9) Repeat steps [1..8] until told to stop ** 10) Notify complete and return ***********************************************************************/ void Hammer::RootFunction() { PRUint32 index; RCFileIO file; char filename[30]; const char zero = 0; PRStatus rv = PR_SUCCESS; limit = (Random() % limit) + 1; (void)sprintf(filename, "%ssg%04p.dat", baseName, this); if (debug_mode) PR_fprintf(output, "Starting work on %s\n", filename); while (PR_TRUE) { PRUint64 bytes; PRUint32 minor = (Random() % limit) + 1; PRUint32 random = (Random() % limit) + 1; PRUint32 pages = (Random() % limit) + 10; while (minor-- > 0) { problem = sg_okay; if (action != sg_go) goto finished; problem = sg_open; rv = file.Open(filename, PR_RDWR|PR_CREATE_FILE, 0666); if (PR_FAILURE == rv) goto finished; for (index = 0; index < pages; index++) { problem = sg_okay; if (action != sg_go) goto close; problem = sg_seek; bytes = file.Seek(pageSize * index, RCFileIO::set); if (bytes != pageSize * index) goto close; problem = sg_write; bytes = file.Write(&zero, sizeof(zero)); if (bytes <= 0) goto close; writes += 1; } problem = sg_close; rv = file.Close(); if (rv != PR_SUCCESS) goto purge; problem = sg_okay; if (action != sg_go) goto purge; problem = sg_open; rv = file.Open(filename, PR_RDWR, 0666); if (PR_FAILURE == rv) goto finished; for (index = 0; index < pages; index++) { problem = sg_okay; if (action != sg_go) goto close; problem = sg_seek; bytes = file.Seek(pageSize * index, RCFileIO::set); if (bytes != pageSize * index) goto close; problem = sg_write; bytes = file.Write(&zero, sizeof(zero)); if (bytes <= 0) goto close; writes += 1; random = (random + 511) % pages; } problem = sg_close; rv = file.Close(); if (rv != PR_SUCCESS) goto purge; problem = sg_delete; rv = file.Delete(filename); if (rv != PR_SUCCESS) goto finished; } } close: (void)file.Close(); purge: (void)file.Delete(filename); finished: RCEnter scope(ml); action = HammerData::sg_done; cv->Notify(); if (debug_mode) PR_fprintf(output, "Ending work on %s\n", filename); return; } /* Hammer::RootFunction */ static Hammer* hammer[100]; /*********************************************************************** ** PRIVATE FUNCTION: main ** DESCRIPTION: ** Hammer on the file I/O system ** INPUTS: The usual argc and argv ** argv[0] - program name (not used) ** argv[1] - the number of virtual_procs to execute the major loop ** argv[2] - the number of threads to toss into the batch ** argv[3] - the clipping number applied to randoms ** default values: max_virtual_procs = 2, threads = 10, limit = 57 ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** Creates, accesses and deletes lots of files ** RESTRICTIONS: ** (Currently) must have file create permission in "/usr/tmp". ** MEMORY: NA ** ALGORITHM: ** 1) Fork a "Thread()" ** 2) Wait for 'interleave' seconds ** 3) For [0..'threads') repeat [1..2] ** 4) Mark all objects to stop ** 5) Collect the threads, accumulating the results ** 6) For [0..'max_virtual_procs') repeat [1..5] ** 7) Print accumulated results and exit ** ** Characteristic output (from IRIX) ** Random File: Using max_virtual_procs = 2, threads = 10, limit = 57 ** Random File: [min [avg] max] writes/sec average ***********************************************************************/ PRIntn main (PRIntn argc, char *argv[]) { RCLock ml; PLOptStatus os; RCCondition cv(&ml); PRUint32 writesMax = 0, durationTot = 0; RCThread::Scope thread_scope = RCThread::local; PRUint32 writes, writesMin = 0x7fffffff, writesTot = 0; PRIntn active, poll, limit = 0, max_virtual_procs = 0, threads = 0, virtual_procs; RCInterval interleave(RCInterval::FromMilliseconds(10000)), duration(0); const char *where[] = {"okay", "open", "close", "delete", "write", "seek"}; PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:t:i:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: baseName = opt->value; break; case 'G': /* global threads */ thread_scope = RCThread::global; break; case 'd': /* debug mode */ debug_mode = 1; break; case 'l': /* limiting number */ limit = atoi(opt->value); break; case 't': /* number of threads */ threads = atoi(opt->value); break; case 'i': /* iteration counter */ max_virtual_procs = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); output = PR_GetSpecialFD(PR_StandardOutput); /* main test */ cv.SetTimeout(interleave); if (max_virtual_procs == 0) max_virtual_procs = 2; if (limit == 0) limit = 57; if (threads == 0) threads = 10; if (debug_mode) PR_fprintf(output, "%s: Using %d virtual processors, %d threads, limit = %d and %s threads\n", programName, max_virtual_procs, threads, limit, (thread_scope == RCThread::local) ? "LOCAL" : "GLOBAL"); for (virtual_procs = 0; virtual_procs < max_virtual_procs; ++virtual_procs) { if (debug_mode) PR_fprintf(output, "%s: Setting number of virtual processors to %d\n", programName, virtual_procs + 1); RCPrimordialThread::SetVirtualProcessors(virtual_procs + 1); for (active = 0; active < threads; active++) { hammer[active] = new Hammer(thread_scope, &ml, &cv, limit); hammer[active]->Start(); /* then make it roll */ RCThread::Sleep(interleave); /* start them slowly */ } /* * The last thread started has had the opportunity to run for * 'interleave' seconds. Now gather them all back in. */ { RCEnter scope(&ml); for (poll = 0; poll < threads; poll++) { if (hammer[poll]->action == HammerData::sg_go) /* don't overwrite done */ hammer[poll]->action = HammerData::sg_stop; /* ask him to stop */ } } while (active > 0) { for (poll = 0; poll < threads; poll++) { ml.Acquire(); while (hammer[poll]->action < HammerData::sg_done) cv.Wait(); ml.Release(); if (hammer[poll]->problem == HammerData::sg_okay) { duration = RCInterval(RCInterval::now) - hammer[poll]->timein; writes = hammer[poll]->writes * 1000 / duration; if (writes < writesMin) writesMin = writes; if (writes > writesMax) writesMax = writes; writesTot += hammer[poll]->writes; durationTot += duration; } else { if (debug_mode) PR_fprintf(output, "%s: test failed %s after %ld seconds\n", programName, where[hammer[poll]->problem], duration); else failed_already=1; } active -= 1; /* this is another one down */ (void)hammer[poll]->Join(); hammer[poll] = NULL; } } if (debug_mode) PR_fprintf(output, "%s: [%ld [%ld] %ld] writes/sec average\n", programName, writesMin, writesTot * 1000 / durationTot, writesMax); } failed_already |= (PR_FAILURE == RCPrimordialThread::Cleanup()); PR_fprintf(output, "%s\n", (failed_already) ? "FAIL\n" : "PASS\n"); return failed_already; } /* main */ nspr-4.11/nspr/pr/src/cplus/tests/switch.cpp0000644000000000000000000001411312623070344017237 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: switch.cpp ** Description: trying to time context switches */ #include "rccv.h" #include "rcinrval.h" #include "rclock.h" #include "rcthread.h" #include #include #include #include #include #include #define INNER_LOOPS 100 #define DEFAULT_LOOPS 100 #define DEFAULT_THREADS 10 static PRFileDesc *debug_out = NULL; static PRBool debug_mode = PR_FALSE, verbosity = PR_FALSE, failed = PR_FALSE; class Home: public RCCondition { public: virtual ~Home(); Home(Home *link, RCLock* ml); public: Home *next; RCLock* ml; PRBool twiddle; }; /* Home */ Home::~Home() { } Home::Home(Home *link, RCLock* lock): RCCondition(lock) { ml = lock; next = link; twiddle = PR_FALSE; } /* Home::Home */ class Shared: public Home, public RCThread { public: Shared(RCThread::Scope scope, Home* link, RCLock* ml); private: ~Shared(); void RootFunction(); }; /* Shared */ Shared::Shared(RCThread::Scope scope, Home* link, RCLock* lock): Home(link, lock), RCThread(scope, RCThread::joinable) { } Shared::~Shared() { } void Shared::RootFunction() { PRStatus status = PR_SUCCESS; while (PR_SUCCESS == status) { RCEnter entry(ml); while (twiddle && (PR_SUCCESS == status)) status = Wait(); if (verbosity) PR_fprintf(debug_out, "+"); twiddle = PR_TRUE; next->twiddle = PR_FALSE; next->Notify(); } } /* Shared::RootFunction */ static void Help(void) { debug_out = PR_STDOUT; PR_fprintf( debug_out, "Usage: >./switch [-d] [-c n] [-t n] [-T n] [-G]\n"); PR_fprintf( debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS); PR_fprintf( debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS); PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n"); PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n"); PR_fprintf(debug_out, "-G n\tglobal threads only (default: FALSE)\n"); PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n"); } /* Help */ PRIntn main(PRIntn argc, char **argv) { PLOptStatus os; PRStatus status; PRBool help = PR_FALSE; PRUintn concurrency = 1; RCThread::Scope thread_scope = RCThread::local; PRUintn thread_count, inner_count, loop_count, average; PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS; PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'v': /* verbose mode */ verbosity = PR_TRUE; case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop counter */ loop_limit = atoi(opt->value); break; case 't': /* thread limit */ thread_limit = atoi(opt->value); break; case 'C': /* Concurrency limit */ concurrency = atoi(opt->value); break; case 'G': /* global threads only */ thread_scope = RCThread::global; break; case 'h': /* help message */ Help(); help = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); if (help) return -1; if (PR_TRUE == debug_mode) { debug_out = PR_STDOUT; PR_fprintf(debug_out, "Test parameters\n"); PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit); PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit); PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency); PR_fprintf( debug_out, "\tThread type: %s\n", (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL"); } /* ** The interesting part starts here */ RCLock lock; Shared* shared; Home home(NULL, &lock); Home* link = &home; RCInterval timein, timeout = 0; /* Build up the string of objects */ for (thread_count = 1; thread_count <= thread_limit; ++thread_count) { shared = new Shared(thread_scope, link, &lock); shared->Start(); /* make it run */ link = (Home*)shared; } /* Pass the message around the horn a few times */ for (loop_count = 1; loop_count <= loop_limit; ++loop_count) { timein.SetToNow(); for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count) { RCEnter entry(&lock); home.twiddle = PR_TRUE; shared->twiddle = PR_FALSE; shared->Notify(); while (home.twiddle) { failed = (PR_FAILURE == home.Wait()) ? PR_TRUE : PR_FALSE; } } timeout += (RCInterval(RCInterval::now) - timein); } /* Figure out how well we did */ if (debug_mode) { average = timeout.ToMicroseconds() / (INNER_LOOPS * loop_limit * thread_count); PR_fprintf( debug_out, "Average switch times %d usecs for %d threads\n", average, thread_limit); } /* Start reclamation process */ link = shared; for (thread_count = 1; thread_count <= thread_limit; ++thread_count) { if (&home == link) break; status = ((Shared*)link)->Interrupt(); if (PR_SUCCESS != status) { failed = PR_TRUE; if (debug_mode) PL_FPrintError(debug_out, "Failed to interrupt"); } link = link->next; } for (thread_count = 1; thread_count <= thread_limit; ++thread_count) { link = shared->next; status = shared->Join(); if (PR_SUCCESS != status) { failed = PR_TRUE; if (debug_mode) PL_FPrintError(debug_out, "Failed to join"); } if (&home == link) break; shared = (Shared*)link; } PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n")); failed |= (PR_SUCCESS == RCPrimordialThread::Cleanup()); return ((failed) ? 1 : 0); } /* main */ /* switch.c */ nspr-4.11/nspr/pr/src/cplus/tests/thread.cpp0000644000000000000000000000470212623070344017210 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* thread.cpp - a test program */ #include "rcthread.h" #include #include class TestThread: public RCThread { public: TestThread(RCThread::State state, PRIntn count); virtual void RootFunction(); protected: virtual ~TestThread(); private: PRUint32 mydata; }; TestThread::~TestThread() { } TestThread::TestThread(RCThread::State state, PRIntn count): RCThread(RCThread::global, state, 0) { mydata = count; } void TestThread::RootFunction() { SetPriority(RCThread::high); printf("TestThread::RootFunction %d did it\n", mydata); } /* TestThread::RootFunction */ class Foo1 { public: Foo1(); virtual ~Foo1(); TestThread *thread; PRIntn data; }; Foo1::Foo1() { data = 0xafaf; thread = new TestThread(RCThread::joinable, 0xafaf); thread->Start(); } Foo1::~Foo1() { PRStatus rv = thread->Join(); PR_ASSERT(PR_SUCCESS == rv); } /* Foo1::~Foo1 */ PRIntn main(PRIntn argc, char **agrv) { PRStatus status; PRIntn count = 100; RCThread *thread[10]; while (--count > 0) { TestThread *thread = new TestThread(RCThread::joinable, count); status = thread->Start(); /* have to remember to start it */ PR_ASSERT(PR_SUCCESS == status); status = thread->Join(); /* this should work */ PR_ASSERT(PR_SUCCESS == status); } while (++count < 100) { TestThread *thread = new TestThread(RCThread::unjoinable, count); status = thread->Start(); /* have to remember to start it */ PR_ASSERT(PR_SUCCESS == status); } { Foo1 *foo1 = new Foo1(); PR_ASSERT(NULL != foo1); delete foo1; } { for (count = 0; count < 10; ++count) { thread[count] = new TestThread( RCThread::joinable, count); status = thread[count]->Start(); /* have to remember to start it */ PR_ASSERT(PR_SUCCESS == status); } for (count = 0; count < 10; ++count) { PRStatus rv = thread[count]->Join(); PR_ASSERT(PR_SUCCESS == rv); } } (void)RCPrimordialThread::Cleanup(); return 0; } /* main */ /* thread.cpp */ nspr-4.11/nspr/pr/src/cplus/tests/time.cpp0000644000000000000000000000120612623070344016673 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* time.cpp - a test program */ #include "rctime.h" #include #include #define DEFAULT_ITERATIONS 100 PRIntn main(PRIntn argc, char **argv) { RCTime unitialized; RCTime now(PR_Now()); RCTime current(RCTime::now); PRTime time = current; unitialized = now; now.Now(); return 0; } /* main */ /* time.cpp */ nspr-4.11/nspr/pr/src/cplus/tests/tpd.cpp0000644000000000000000000002064412623070344016533 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: tpd.cpp ** Description: Exercising the thread private data bailywick. */ #include "prlog.h" #include "prprf.h" #include "rcthread.h" #include #include "plgetopt.h" /* ** class MyThread */ class MyThread: public RCThread { public: MyThread(); private: ~MyThread(); void RootFunction(); }; /* MyThread */ /* ** class MyPrivateData */ class MyPrivateData: public RCThreadPrivateData { public: virtual ~MyPrivateData(); MyPrivateData(); MyPrivateData(char*); MyPrivateData(const MyPrivateData&); void Release(); private: char *string; }; /* MyPrivateData */ static PRUintn key[128]; static PRIntn debug = 0; static PRBool failed = PR_FALSE; static PRBool should = PR_TRUE; static PRBool did = PR_TRUE; static PRFileDesc *fout = NULL; static void PrintProgress(PRIntn line) { failed = failed || (should && !did); failed = failed || (!should && did); if (debug > 0) { PR_fprintf( fout, "@ line %d destructor should %shave been called and was%s\n", line, ((should) ? "" : "NOT "), ((did) ? "" : " NOT")); } } /* PrintProgress */ static void MyAssert(const char *expr, const char *file, PRIntn line) { if (debug > 0) (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line); } /* MyAssert */ #define MY_ASSERT(_expr) \ ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__)) int main(PRIntn argc, char *argv[]) { PRStatus rv; PRUintn keys; MyThread *thread; const RCThreadPrivateData *pd; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); RCThread *primordial = RCThread::WrapPrimordialThread(); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); fout = PR_STDOUT; MyPrivateData extension = MyPrivateData("EXTENSION"); MyPrivateData key_string[] = { "Key #0", "Key #1", "Key #2", "Key #3", "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"}; did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = RCThread::NewPrivateIndex(&key[keys]); key[keys + 4] = key[keys] + 4; MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); /* the first four should be bu null, the last four undefined and null */ did = should = PR_FALSE; for (keys = 0; keys < 8; ++keys) { pd = RCThread::GetPrivateData(key[keys]); MY_ASSERT(NULL == pd); } PrintProgress(__LINE__); /* initially set private data for new keys */ did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = RCThread::SetPrivateData(key[keys], &key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); /* re-assign the private data, albeit the same content */ did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { pd = RCThread::GetPrivateData(key[keys]); PR_ASSERT(NULL != pd); rv = RCThread::SetPrivateData(key[keys], &key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); /* set private to */ did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = RCThread::SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); /* should all be null now */ did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { pd = RCThread::GetPrivateData(key[keys]); PR_ASSERT(NULL == pd); } PrintProgress(__LINE__); /* allocate another batch of keys and assign data to them */ did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = RCThread::NewPrivateIndex(&key[keys]); MY_ASSERT(PR_SUCCESS == rv); rv = RCThread::SetPrivateData(key[keys], &extension); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); /* set all the extended slots to */ did = PR_FALSE; should = PR_TRUE; for (keys = 8; keys < 127; ++keys) { rv = RCThread::SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); /* set all the extended slots to again (noop) */ did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = RCThread::SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } if (debug) PR_fprintf(fout, "Creating thread\n"); thread = new MyThread(); if (debug) PR_fprintf(fout, "Starting thread\n"); thread->Start(); if (debug) PR_fprintf(fout, "Joining thread\n"); (void)thread->Join(); if (debug) PR_fprintf(fout, "Joined thread\n"); failed |= (PR_FAILURE == RCPrimordialThread::Cleanup()); (void)PR_fprintf( fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED")); return (failed) ? 1 : 0; } /* main */ /* ** class MyPrivateData */ MyPrivateData::~MyPrivateData() { PR_fprintf( fout, "MyPrivateData::~MyPrivateData[%s]\n", (NULL != string) ? string : "NULL"); } /* MyPrivateData::~MyPrivateData */ MyPrivateData::MyPrivateData(): RCThreadPrivateData() { PR_fprintf(fout, "MyPrivateData::MyPrivateData()\n"); string = NULL; } /* MyPrivateData::MyPrivateData */ MyPrivateData::MyPrivateData(char* data): RCThreadPrivateData() { PR_fprintf(fout, "MyPrivateData::MyPrivateData(char* data)\n"); string = data; } /* MyPrivateData:: MyPrivateData */ MyPrivateData::MyPrivateData(const MyPrivateData& him): RCThreadPrivateData(him) { PR_fprintf(fout, "MyPrivateData::MyPrivateData(const MyPrivateData& him)\n"); string = him.string; } /* MyPrivateData:: MyPrivateData */ void MyPrivateData::Release() { if (should) did = PR_TRUE; else failed = PR_TRUE; } /* MyPrivateData::operator= */ /* ** class MyThread */ MyThread::~MyThread() { } MyThread::MyThread(): RCThread(RCThread::global, RCThread::joinable) { } void MyThread::RootFunction() { PRStatus rv; PRUintn keys; const RCThreadPrivateData *pd; MyPrivateData extension = MyPrivateData("EXTENSION"); MyPrivateData key_string[] = { "Key #0", "Key #1", "Key #2", "Key #3", "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"}; did = should = PR_FALSE; for (keys = 0; keys < 8; ++keys) { pd = GetPrivateData(key[keys]); MY_ASSERT(NULL == pd); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = SetPrivateData(keys, &key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); #if !defined(DEBUG) did = should = PR_FALSE; for (keys = 4; keys < 8; ++keys) { rv = SetPrivateData(keys, &key_string[keys]); MY_ASSERT(PR_FAILURE == rv); } PrintProgress(__LINE__); #endif did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = SetPrivateData(key[keys], &key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = SetPrivateData(key[keys], &extension); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 8; keys < 127; ++keys) { rv = SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = SetPrivateData(key[keys]); MY_ASSERT(PR_SUCCESS == rv); } } /* MyThread::RootFunction */ /* tpd.c */ nspr-4.11/nspr/pr/src/io/.cvsignore0000644000000000000000000000001112623070344015341 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/io/Makefile.in0000644000000000000000000000157112623070344015422 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = \ prfdcach.c \ prmwait.c \ priometh.c \ pripv6.c \ prmapopt.c \ prlayer.c \ prlog.c \ prmmap.c \ prpolevt.c \ prprf.c \ prscanf.c \ prstdio.c \ $(NULL) ifndef USE_PTHREADS CSRCS += \ prdir.c \ prfile.c \ prio.c \ prsocket.c \ $(NULL) endif TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/io/prdir.c0000644000000000000000000000535412623070344014644 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" PR_IMPLEMENT(PRDir*) PR_OpenDir(const char *name) { PRDir *dir; PRStatus sts; dir = PR_NEW(PRDir); if (dir) { sts = _PR_MD_OPEN_DIR(&dir->md,name); if (sts != PR_SUCCESS) { PR_DELETE(dir); return NULL; } } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return dir; } PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags) { /* _MD_READ_DIR return a char* to the name; allocation in machine-dependent code */ char* name = _PR_MD_READ_DIR(&dir->md, flags); dir->d.name = name; return name ? &dir->d : NULL; } PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir) { PRInt32 rv; if (dir) { rv = _PR_MD_CLOSE_DIR(&dir->md); PR_DELETE(dir); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode) { PRInt32 rv; rv = _PR_MD_MKDIR(name, mode); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode) { PRInt32 rv; if (!_pr_initialized) _PR_ImplicitInitialization(); rv = _PR_MD_MAKE_DIR(name, mode); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name) { PRInt32 rv; rv = _PR_MD_RMDIR(name); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } #ifdef MOZ_UNICODE /* * UTF16 Interface */ PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name) { PRDirUTF16 *dir; PRStatus sts; dir = PR_NEW(PRDirUTF16); if (dir) { sts = _PR_MD_OPEN_DIR_UTF16(&dir->md,name); if (sts != PR_SUCCESS) { PR_DELETE(dir); return NULL; } } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return dir; } PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags) { /* * _MD_READ_DIR_UTF16 return a PRUnichar* to the name; allocation in * machine-dependent code */ PRUnichar* name = _PR_MD_READ_DIR_UTF16(&dir->md, flags); dir->d.name = name; return name ? &dir->d : NULL; } PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDirUTF16 *dir) { PRInt32 rv; if (dir) { rv = _PR_MD_CLOSE_DIR_UTF16(&dir->md); PR_DELETE(dir); if (rv < 0) return PR_FAILURE; else return PR_SUCCESS; } return PR_SUCCESS; } #endif /* MOZ_UNICODE */ nspr-4.11/nspr/pr/src/io/prfdcach.c0000644000000000000000000001634712623070344015302 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /*****************************************************************************/ /*****************************************************************************/ /************************** File descriptor caching **************************/ /*****************************************************************************/ /*****************************************************************************/ /* ** This code is built into debuggable versions of NSPR to assist in ** finding misused file descriptors. Since file descritors (PRFileDesc) ** are identified by a pointer to their structure, they can be the ** target of dangling references. Furthermore, NSPR caches and tries ** to aggressively reuse file descriptors, leading to more ambiguity. ** The following code will allow a debugging client to set environment ** variables and control the number of file descriptors that will be ** preserved before they are recycled. The environment variables are ** NSPR_FD_CACHE_SIZE_LOW and NSPR_FD_CACHE_SIZE_HIGH. The former sets ** the number of descriptors NSPR will allocate before beginning to ** recycle. The latter is the maximum number permitted in the cache ** (exclusive of those in use) at a time. */ typedef struct _PR_Fd_Cache { PRLock *ml; PRIntn count; PRFileDesc *head, *tail; PRIntn limit_low, limit_high; } _PR_Fd_Cache; static _PR_Fd_Cache _pr_fd_cache; /* ** Get a FileDescriptor from the cache if one exists. If not allocate ** a new one from the heap. */ PRFileDesc *_PR_Getfd(void) { PRFileDesc *fd; /* ** $$$ ** This may look a little wasteful. We'll see. Right now I want to ** be able to toggle between caching and not at runtime to measure ** the differences. If it isn't too annoying, I'll leave it in. ** $$$$ ** ** The test is against _pr_fd_cache.limit_high. If that's zero, ** we're not doing the extended cache but going for performance. */ if (0 == _pr_fd_cache.limit_high) { goto allocate; } else { do { if (NULL == _pr_fd_cache.head) goto allocate; /* nothing there */ if (_pr_fd_cache.count < _pr_fd_cache.limit_low) goto allocate; /* we "should" be able to extract an fd from the cache */ PR_Lock(_pr_fd_cache.ml); /* need the lock to do this safely */ fd = _pr_fd_cache.head; /* protected extraction */ if (NULL == fd) /* unexpected, but not fatal */ { PR_ASSERT(0 == _pr_fd_cache.count); PR_ASSERT(NULL == _pr_fd_cache.tail); } else { _pr_fd_cache.count -= 1; _pr_fd_cache.head = fd->higher; if (NULL == _pr_fd_cache.head) { PR_ASSERT(0 == _pr_fd_cache.count); _pr_fd_cache.tail = NULL; } PR_ASSERT(&_pr_faulty_methods == fd->methods); PR_ASSERT(PR_INVALID_IO_LAYER == fd->identity); PR_ASSERT(_PR_FILEDESC_FREED == fd->secret->state); } PR_Unlock(_pr_fd_cache.ml); } while (NULL == fd); /* then go around and allocate a new one */ } finished: fd->dtor = NULL; fd->lower = fd->higher = NULL; fd->identity = PR_NSPR_IO_LAYER; memset(fd->secret, 0, sizeof(PRFilePrivate)); return fd; allocate: fd = PR_NEW(PRFileDesc); if (NULL != fd) { fd->secret = PR_NEW(PRFilePrivate); if (NULL == fd->secret) PR_DELETE(fd); } if (NULL != fd) goto finished; else return NULL; } /* _PR_Getfd */ /* ** Return a file descriptor to the cache unless there are too many in ** there already. If put in cache, clear the fields first. */ void _PR_Putfd(PRFileDesc *fd) { PR_ASSERT(PR_NSPR_IO_LAYER == fd->identity); fd->methods = &_pr_faulty_methods; fd->identity = PR_INVALID_IO_LAYER; fd->secret->state = _PR_FILEDESC_FREED; if (0 != _pr_fd_cache.limit_high) { if (_pr_fd_cache.count < _pr_fd_cache.limit_high) { PR_Lock(_pr_fd_cache.ml); if (NULL == _pr_fd_cache.tail) { PR_ASSERT(0 == _pr_fd_cache.count); PR_ASSERT(NULL == _pr_fd_cache.head); _pr_fd_cache.head = _pr_fd_cache.tail = fd; } else { PR_ASSERT(NULL == _pr_fd_cache.tail->higher); _pr_fd_cache.tail->higher = fd; _pr_fd_cache.tail = fd; /* new value */ } fd->higher = NULL; /* always so */ _pr_fd_cache.count += 1; /* count the new entry */ PR_Unlock(_pr_fd_cache.ml); return; } } PR_Free(fd->secret); PR_Free(fd); } /* _PR_Putfd */ PR_IMPLEMENT(PRStatus) PR_SetFDCacheSize(PRIntn low, PRIntn high) { /* ** This can be called at any time, may adjust the cache sizes, ** turn the caches off, or turn them on. It is not dependent ** on the compilation setting of DEBUG. */ if (!_pr_initialized) _PR_ImplicitInitialization(); if (low > high) low = high; /* sanity check the params */ PR_Lock(_pr_fd_cache.ml); _pr_fd_cache.limit_high = high; _pr_fd_cache.limit_low = low; PR_Unlock(_pr_fd_cache.ml); return PR_SUCCESS; } /* PR_SetFDCacheSize */ void _PR_InitFdCache(void) { /* ** The fd caching is enabled by default for DEBUG builds, ** disabled by default for OPT builds. That default can ** be overridden at runtime using environment variables ** or a super-wiz-bang API. */ const char *low = PR_GetEnv("NSPR_FD_CACHE_SIZE_LOW"); const char *high = PR_GetEnv("NSPR_FD_CACHE_SIZE_HIGH"); /* ** _low is allowed to be zero, _high is not. ** If _high is zero, we're not doing the caching. */ _pr_fd_cache.limit_low = 0; #if defined(DEBUG) _pr_fd_cache.limit_high = FD_SETSIZE; #else _pr_fd_cache.limit_high = 0; #endif /* defined(DEBUG) */ if (NULL != low) _pr_fd_cache.limit_low = atoi(low); if (NULL != high) _pr_fd_cache.limit_high = atoi(high); if (_pr_fd_cache.limit_low < 0) _pr_fd_cache.limit_low = 0; if (_pr_fd_cache.limit_low > FD_SETSIZE) _pr_fd_cache.limit_low = FD_SETSIZE; if (_pr_fd_cache.limit_high > FD_SETSIZE) _pr_fd_cache.limit_high = FD_SETSIZE; if (_pr_fd_cache.limit_high < _pr_fd_cache.limit_low) _pr_fd_cache.limit_high = _pr_fd_cache.limit_low; _pr_fd_cache.ml = PR_NewLock(); PR_ASSERT(NULL != _pr_fd_cache.ml); } /* _PR_InitFdCache */ void _PR_CleanupFdCache(void) { PRFileDesc *fd, *next; for (fd = _pr_fd_cache.head; fd != NULL; fd = next) { next = fd->higher; PR_DELETE(fd->secret); PR_DELETE(fd); } _pr_fd_cache.head = NULL; _pr_fd_cache.tail = NULL; _pr_fd_cache.count = 0; PR_DestroyLock(_pr_fd_cache.ml); _pr_fd_cache.ml = NULL; } /* _PR_CleanupFdCache */ /* prfdcach.c */ nspr-4.11/nspr/pr/src/io/prfile.c0000644000000000000000000004550712623070344015011 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #ifdef XP_UNIX #if defined(AIX) || defined(QNX) /* To pick up sysconf */ #include #else /* To pick up getrlimit, setrlimit */ #include #include #endif #endif /* XP_UNIX */ extern PRLock *_pr_flock_lock; extern PRCondVar *_pr_flock_cv; static PRInt32 PR_CALLBACK FileRead(PRFileDesc *fd, void *buf, PRInt32 amount) { PRInt32 rv = 0; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); rv = -1; } if (rv == -1) return rv; rv = _PR_MD_READ(fd, buf, amount); if (rv < 0) { PR_ASSERT(rv == -1); } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("read -> %d", rv)); return rv; } static PRInt32 PR_CALLBACK FileWrite(PRFileDesc *fd, const void *buf, PRInt32 amount) { PRInt32 rv = 0; PRInt32 temp, count; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); rv = -1; } if (rv != 0) return rv; count = 0; #if !defined(_PR_HAVE_O_APPEND) /* Bugzilla: 4090, 276330 */ if (fd->secret->appendMode) { if (PR_Seek64(fd, 0, PR_SEEK_END) == -1) { return -1; } } /* if (fd->secret->appendMode...) */ #endif /* _PR_HAVE_O_APPEND */ while (amount > 0) { temp = _PR_MD_WRITE(fd, buf, amount); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("write -> %d", count)); return count; } static PROffset32 PR_CALLBACK FileSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence) { PROffset32 result; result = _PR_MD_LSEEK(fd, offset, whence); return result; } static PROffset64 PR_CALLBACK FileSeek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence) { PROffset64 result; result = _PR_MD_LSEEK64(fd, offset, whence); return result; } static PRInt32 PR_CALLBACK FileAvailable(PRFileDesc *fd) { PRInt32 result, cur, end; cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR); if (cur >= 0) end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END); if ((cur < 0) || (end < 0)) { return -1; } result = end - cur; _PR_MD_LSEEK(fd, cur, PR_SEEK_SET); return result; } static PRInt64 PR_CALLBACK FileAvailable64(PRFileDesc *fd) { PRInt64 result, cur, end; PRInt64 minus_one; LL_I2L(minus_one, -1); cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR); if (LL_GE_ZERO(cur)) end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END); if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one; LL_SUB(result, end, cur); (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET); return result; } static PRInt32 PR_CALLBACK PipeAvailable(PRFileDesc *fd) { PRInt32 rv; rv = _PR_MD_PIPEAVAILABLE(fd); return rv; } static PRInt64 PR_CALLBACK PipeAvailable64(PRFileDesc *fd) { PRInt64 rv; LL_I2L(rv, _PR_MD_PIPEAVAILABLE(fd)); return rv; } static PRStatus PR_CALLBACK PipeSync(PRFileDesc *fd) { return PR_SUCCESS; } static PRStatus PR_CALLBACK FileGetInfo(PRFileDesc *fd, PRFileInfo *info) { PRInt32 rv; rv = _PR_MD_GETOPENFILEINFO(fd, info); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } static PRStatus PR_CALLBACK FileGetInfo64(PRFileDesc *fd, PRFileInfo64 *info) { /* $$$$ NOT YET IMPLEMENTED */ PRInt32 rv; rv = _PR_MD_GETOPENFILEINFO64(fd, info); if (rv < 0) return PR_FAILURE; else return PR_SUCCESS; } static PRStatus PR_CALLBACK FileSync(PRFileDesc *fd) { PRInt32 result; result = _PR_MD_FSYNC(fd); if (result < 0) { return PR_FAILURE; } return PR_SUCCESS; } static PRStatus PR_CALLBACK FileClose(PRFileDesc *fd) { if (!fd || !fd->secret || (fd->secret->state != _PR_FILEDESC_OPEN && fd->secret->state != _PR_FILEDESC_CLOSED)) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if (fd->secret->state == _PR_FILEDESC_OPEN) { if (_PR_MD_CLOSE_FILE(fd->secret->md.osfd) < 0) { return PR_FAILURE; } fd->secret->state = _PR_FILEDESC_CLOSED; } PR_FreeFileDesc(fd); return PR_SUCCESS; } static PRInt16 PR_CALLBACK FilePoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { *out_flags = 0; return in_flags; } /* FilePoll */ static PRIOMethods _pr_fileMethods = { PR_DESC_FILE, FileClose, FileRead, FileWrite, FileAvailable, FileAvailable64, FileSync, FileSeek, FileSeek64, FileGetInfo, FileGetInfo64, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, FilePoll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void) { return &_pr_fileMethods; } static PRIOMethods _pr_pipeMethods = { PR_DESC_PIPE, FileClose, FileRead, FileWrite, PipeAvailable, PipeAvailable64, PipeSync, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, FilePoll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void) { return &_pr_pipeMethods; } PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) { PROsfd osfd; PRFileDesc *fd = 0; #if !defined(_PR_HAVE_O_APPEND) PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); /* Map pr open flags and mode to os specific flags */ osfd = _PR_MD_OPEN(name, flags, mode); if (osfd != -1) { fd = PR_AllocFileDesc(osfd, &_pr_fileMethods); if (!fd) { (void) _PR_MD_CLOSE_FILE(osfd); } else { #if !defined(_PR_HAVE_O_APPEND) fd->secret->appendMode = appendMode; #endif _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE); } } return fd; } PR_IMPLEMENT(PRFileDesc*) PR_OpenFile( const char *name, PRIntn flags, PRIntn mode) { PROsfd osfd; PRFileDesc *fd = 0; #if !defined(_PR_HAVE_O_APPEND) PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); /* Map pr open flags and mode to os specific flags */ osfd = _PR_MD_OPEN_FILE(name, flags, mode); if (osfd != -1) { fd = PR_AllocFileDesc(osfd, &_pr_fileMethods); if (!fd) { (void) _PR_MD_CLOSE_FILE(osfd); } else { #if !defined(_PR_HAVE_O_APPEND) fd->secret->appendMode = appendMode; #endif _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE); } } return fd; } PR_IMPLEMENT(PRInt32) PR_GetSysfdTableMax(void) { #if defined(XP_UNIX) && !defined(AIX) && !defined(QNX) struct rlimit rlim; if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) { /* XXX need to call PR_SetError() */ return -1; } return rlim.rlim_max; #elif defined(AIX) || defined(QNX) return sysconf(_SC_OPEN_MAX); #elif defined(WIN32) /* * There is a systemwide limit of 65536 user handles. */ return 16384; #elif defined (WIN16) return FOPEN_MAX; #elif defined(XP_OS2) ULONG ulReqCount = 0; ULONG ulCurMaxFH = 0; DosSetRelMaxFH(&ulReqCount, &ulCurMaxFH); return ulCurMaxFH; #elif defined(XP_BEOS) PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; #else write me; #endif } PR_IMPLEMENT(PRInt32) PR_SetSysfdTableSize(int table_size) { #if defined(XP_UNIX) && !defined(AIX) && !defined(QNX) struct rlimit rlim; PRInt32 tableMax = PR_GetSysfdTableMax(); if (tableMax < 0) return -1; if (tableMax > FD_SETSIZE) tableMax = FD_SETSIZE; rlim.rlim_max = tableMax; /* Grow as much as we can; even if too big */ if ( rlim.rlim_max < table_size ) rlim.rlim_cur = rlim.rlim_max; else rlim.rlim_cur = table_size; if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) { /* XXX need to call PR_SetError() */ return -1; } return rlim.rlim_cur; #elif defined(XP_OS2) PRInt32 tableMax = PR_GetSysfdTableMax(); if (table_size > tableMax) { APIRET rc = NO_ERROR; rc = DosSetMaxFH(table_size); if (rc == NO_ERROR) return table_size; else return -1; } return tableMax; #elif defined(AIX) || defined(QNX) \ || defined(WIN32) || defined(WIN16) || defined(XP_BEOS) PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; #else write me; #endif } PR_IMPLEMENT(PRStatus) PR_Delete(const char *name) { PRInt32 rv; rv = _PR_MD_DELETE(name); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info) { PRInt32 rv; rv = _PR_MD_GETFILEINFO(fn, info); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info) { PRInt32 rv; if (!_pr_initialized) _PR_ImplicitInitialization(); rv = _PR_MD_GETFILEINFO64(fn, info); if (rv < 0) { return PR_FAILURE; } else { return PR_SUCCESS; } } PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to) { PRInt32 rv; rv = _PR_MD_RENAME(from, to); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how) { PRInt32 rv; rv = _PR_MD_ACCESS(name, how); if (rv < 0) { return PR_FAILURE; } else return PR_SUCCESS; } /* ** Import an existing OS file to NSPR */ PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PROsfd osfd) { PRFileDesc *fd = NULL; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = PR_AllocFileDesc(osfd, &_pr_fileMethods); if( !fd ) { (void) _PR_MD_CLOSE_FILE(osfd); } else { _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE); } return fd; } /* ** Import an existing OS pipe to NSPR */ PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PROsfd osfd) { PRFileDesc *fd = NULL; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = PR_AllocFileDesc(osfd, &_pr_pipeMethods); if( !fd ) { (void) _PR_MD_CLOSE_FILE(osfd); } else { _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE); #ifdef WINNT fd->secret->md.sync_file_io = PR_TRUE; #endif } return fd; } #ifndef NO_NSPR_10_SUPPORT /* ** PR_Stat() for Win16 is defined in w16io.c ** it is a hack to circumvent problems in Gromit and Java ** See also: BugSplat: 98516. */ #if !defined(WIN16) /* * This function is supposed to be for backward compatibility with * nspr 1.0. Therefore, it still uses the nspr 1.0 error-reporting * mechanism -- returns a PRInt32, which is the error code when the call * fails. * * If we need this function in nspr 2.0, it should be changed to * return PRStatus, as follows: * * PR_IMPLEMENT(PRStatus) PR_Stat(const char *name, struct stat *buf) * { * PRInt32 rv; * * rv = _PR_MD_STAT(name, buf); * if (rv < 0) * return PR_FAILURE; * else * return PR_SUCCESS; * } * * -- wtc, 2/14/97. */ PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf) { PRInt32 rv; rv = _PR_MD_STAT(name, buf); return rv; } #endif /* !defined(WIN16) */ #endif /* ! NO_NSPR_10_SUPPORT */ PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd) { PRStatus status = PR_SUCCESS; #ifdef WINNT if (!fd->secret->md.io_model_committed) { PRInt32 rv; rv = _md_Associate((HANDLE)fd->secret->md.osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } #endif PR_Lock(_pr_flock_lock); while (fd->secret->lockCount == -1) PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT); if (fd->secret->lockCount == 0) { fd->secret->lockCount = -1; PR_Unlock(_pr_flock_lock); status = _PR_MD_LOCKFILE(fd->secret->md.osfd); PR_Lock(_pr_flock_lock); fd->secret->lockCount = (status == PR_SUCCESS) ? 1 : 0; PR_NotifyAllCondVar(_pr_flock_cv); } else { fd->secret->lockCount++; } PR_Unlock(_pr_flock_lock); return status; } PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd) { PRStatus status = PR_SUCCESS; #ifdef WINNT if (!fd->secret->md.io_model_committed) { PRInt32 rv; rv = _md_Associate((HANDLE)fd->secret->md.osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } #endif PR_Lock(_pr_flock_lock); if (fd->secret->lockCount == 0) { status = _PR_MD_TLOCKFILE(fd->secret->md.osfd); PR_ASSERT(status == PR_SUCCESS || fd->secret->lockCount == 0); if (status == PR_SUCCESS) fd->secret->lockCount = 1; } else { fd->secret->lockCount++; } PR_Unlock(_pr_flock_lock); return status; } PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd) { PRStatus rv = PR_SUCCESS; PR_Lock(_pr_flock_lock); if (fd->secret->lockCount == 1) { rv = _PR_MD_UNLOCKFILE(fd->secret->md.osfd); if (rv == PR_SUCCESS) fd->secret->lockCount = 0; } else { fd->secret->lockCount--; } PR_Unlock(_pr_flock_lock); return rv; } PR_IMPLEMENT(PRStatus) PR_CreatePipe( PRFileDesc **readPipe, PRFileDesc **writePipe ) { #if defined(WIN32) && !defined(WINCE) HANDLE readEnd, writeEnd; SECURITY_ATTRIBUTES pipeAttributes; if (!_pr_initialized) _PR_ImplicitInitialization(); ZeroMemory(&pipeAttributes, sizeof(pipeAttributes)); pipeAttributes.nLength = sizeof(pipeAttributes); pipeAttributes.bInheritHandle = TRUE; if (CreatePipe(&readEnd, &writeEnd, &pipeAttributes, 0) == 0) { PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); return PR_FAILURE; } *readPipe = PR_AllocFileDesc((PROsfd)readEnd, &_pr_pipeMethods); if (NULL == *readPipe) { CloseHandle(readEnd); CloseHandle(writeEnd); return PR_FAILURE; } *writePipe = PR_AllocFileDesc((PROsfd)writeEnd, &_pr_pipeMethods); if (NULL == *writePipe) { PR_Close(*readPipe); CloseHandle(writeEnd); return PR_FAILURE; } #ifdef WINNT (*readPipe)->secret->md.sync_file_io = PR_TRUE; (*writePipe)->secret->md.sync_file_io = PR_TRUE; #endif (*readPipe)->secret->inheritable = _PR_TRI_TRUE; (*writePipe)->secret->inheritable = _PR_TRI_TRUE; return PR_SUCCESS; #elif defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) #ifdef XP_OS2 HFILE pipefd[2]; #else int pipefd[2]; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); #ifdef XP_OS2 if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) { #else if (pipe(pipefd) == -1) { #endif /* XXX map pipe error */ PR_SetError(PR_UNKNOWN_ERROR, errno); return PR_FAILURE; } *readPipe = PR_AllocFileDesc(pipefd[0], &_pr_pipeMethods); if (NULL == *readPipe) { close(pipefd[0]); close(pipefd[1]); return PR_FAILURE; } *writePipe = PR_AllocFileDesc(pipefd[1], &_pr_pipeMethods); if (NULL == *writePipe) { PR_Close(*readPipe); close(pipefd[1]); return PR_FAILURE; } #ifndef XP_BEOS /* Pipes are nonblocking on BeOS */ _PR_MD_MAKE_NONBLOCK(*readPipe); #endif _PR_MD_INIT_FD_INHERITABLE(*readPipe, PR_FALSE); #ifndef XP_BEOS /* Pipes are nonblocking on BeOS */ _PR_MD_MAKE_NONBLOCK(*writePipe); #endif _PR_MD_INIT_FD_INHERITABLE(*writePipe, PR_FALSE); return PR_SUCCESS; #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; #endif } #ifdef MOZ_UNICODE /* ================ UTF16 Interfaces ================================ */ PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16( const PRUnichar *name, PRIntn flags, PRIntn mode) { PROsfd osfd; PRFileDesc *fd = 0; #if !defined(_PR_HAVE_O_APPEND) PRBool appendMode = ( PR_APPEND & flags )? PR_TRUE : PR_FALSE; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); /* Map pr open flags and mode to os specific flags */ osfd = _PR_MD_OPEN_FILE_UTF16(name, flags, mode); if (osfd != -1) { fd = PR_AllocFileDesc(osfd, &_pr_fileMethods); if (!fd) { (void) _PR_MD_CLOSE_FILE(osfd); } else { #if !defined(_PR_HAVE_O_APPEND) fd->secret->appendMode = appendMode; #endif _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE); } } return fd; } PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info) { PRInt32 rv; if (!_pr_initialized) _PR_ImplicitInitialization(); rv = _PR_MD_GETFILEINFO64_UTF16(fn, info); if (rv < 0) { return PR_FAILURE; } else { return PR_SUCCESS; } } /* ================ UTF16 Interfaces ================================ */ #endif /* MOZ_UNICODE */ nspr-4.11/nspr/pr/src/io/prio.c0000644000000000000000000001122312623070344014465 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* for memset() */ /************************************************************************/ PRLock *_pr_flock_lock; PRCondVar *_pr_flock_cv; #ifdef WINCE /* * There are no stdin, stdout, stderr in Windows CE. INVALID_HANDLE_VALUE * should cause all I/O functions on the handle to fail. */ #define STD_INPUT_HANDLE ((DWORD)-10) #define STD_OUTPUT_HANDLE ((DWORD)-11) #define STD_ERROR_HANDLE ((DWORD)-12) static HANDLE GetStdHandle(DWORD nStdHandle) { SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return INVALID_HANDLE_VALUE; } #endif void _PR_InitIO(void) { const PRIOMethods *methods = PR_GetFileMethods(); _PR_InitFdCache(); _pr_flock_lock = PR_NewLock(); _pr_flock_cv = PR_NewCondVar(_pr_flock_lock); #ifdef WIN32 _pr_stdin = PR_AllocFileDesc((PROsfd)GetStdHandle(STD_INPUT_HANDLE), methods); _pr_stdout = PR_AllocFileDesc((PROsfd)GetStdHandle(STD_OUTPUT_HANDLE), methods); _pr_stderr = PR_AllocFileDesc((PROsfd)GetStdHandle(STD_ERROR_HANDLE), methods); #ifdef WINNT _pr_stdin->secret->md.sync_file_io = PR_TRUE; _pr_stdout->secret->md.sync_file_io = PR_TRUE; _pr_stderr->secret->md.sync_file_io = PR_TRUE; #endif #else _pr_stdin = PR_AllocFileDesc(0, methods); _pr_stdout = PR_AllocFileDesc(1, methods); _pr_stderr = PR_AllocFileDesc(2, methods); #endif _PR_MD_INIT_FD_INHERITABLE(_pr_stdin, PR_TRUE); _PR_MD_INIT_FD_INHERITABLE(_pr_stdout, PR_TRUE); _PR_MD_INIT_FD_INHERITABLE(_pr_stderr, PR_TRUE); _PR_MD_INIT_IO(); } void _PR_CleanupIO(void) { PR_FreeFileDesc(_pr_stdin); _pr_stdin = NULL; PR_FreeFileDesc(_pr_stdout); _pr_stdout = NULL; PR_FreeFileDesc(_pr_stderr); _pr_stderr = NULL; if (_pr_flock_cv) { PR_DestroyCondVar(_pr_flock_cv); _pr_flock_cv = NULL; } if (_pr_flock_lock) { PR_DestroyLock(_pr_flock_lock); _pr_flock_lock = NULL; } _PR_CleanupFdCache(); } PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd) { PRFileDesc *result = NULL; PR_ASSERT((int) osfd >= PR_StandardInput && osfd <= PR_StandardError); if (!_pr_initialized) _PR_ImplicitInitialization(); switch (osfd) { case PR_StandardInput: result = _pr_stdin; break; case PR_StandardOutput: result = _pr_stdout; break; case PR_StandardError: result = _pr_stderr; break; default: (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); } return result; } PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc( PROsfd osfd, const PRIOMethods *methods) { PRFileDesc *fd; #ifdef XP_UNIX /* * Assert that the file descriptor is small enough to fit in the * fd_set passed to select */ PR_ASSERT(osfd < FD_SETSIZE); #endif fd = _PR_Getfd(); if (fd) { /* Initialize the members of PRFileDesc and PRFilePrivate */ fd->methods = methods; fd->secret->state = _PR_FILEDESC_OPEN; fd->secret->md.osfd = osfd; _PR_MD_INIT_FILEDESC(fd); } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return fd; } PR_IMPLEMENT(void) PR_FreeFileDesc(PRFileDesc *fd) { PR_ASSERT(fd); _PR_Putfd(fd); } /* ** Wait for some i/o to finish on one or more more poll descriptors. */ PR_IMPLEMENT(PRInt32) PR_Poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { return(_PR_MD_PR_POLL(pds, npds, timeout)); } /* ** Set the inheritance attribute of a file descriptor. */ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable( PRFileDesc *fd, PRBool inheritable) { #if defined(XP_UNIX) || defined(WIN32) || defined(XP_OS2) || defined(XP_BEOS) /* * Only a non-layered, NSPR file descriptor can be inherited * by a child process. */ if (fd->identity != PR_NSPR_IO_LAYER) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } if (fd->secret->inheritable != inheritable) { if (_PR_MD_SET_FD_INHERITABLE(fd, inheritable) == PR_FAILURE) { return PR_FAILURE; } fd->secret->inheritable = inheritable; } return PR_SUCCESS; #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; #endif } /* ** This function only has a useful implementation in the debug build of ** the pthreads version. */ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) { /* do nothing */ } /* PT_FPrintStats */ nspr-4.11/nspr/pr/src/io/priometh.c0000644000000000000000000003764012623070344015356 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /*****************************************************************************/ /************************** Invalid I/O method object ************************/ /*****************************************************************************/ PRIOMethods _pr_faulty_methods = { (PRDescType)0, (PRCloseFN)_PR_InvalidStatus, (PRReadFN)_PR_InvalidInt, (PRWriteFN)_PR_InvalidInt, (PRAvailableFN)_PR_InvalidInt, (PRAvailable64FN)_PR_InvalidInt64, (PRFsyncFN)_PR_InvalidStatus, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, (PRPollFN)_PR_InvalidInt16, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; PRIntn _PR_InvalidInt(void) { PR_NOT_REACHED("I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } /* _PR_InvalidInt */ PRInt16 _PR_InvalidInt16(void) { PR_NOT_REACHED("I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return -1; } /* _PR_InvalidInt */ PRInt64 _PR_InvalidInt64(void) { PRInt64 rv; LL_I2L(rv, -1); PR_NOT_REACHED("I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return rv; } /* _PR_InvalidInt */ /* * An invalid method that returns PRStatus */ PRStatus _PR_InvalidStatus(void) { PR_NOT_REACHED("I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return PR_FAILURE; } /* _PR_InvalidDesc */ /* * An invalid method that returns a pointer */ PRFileDesc *_PR_InvalidDesc(void) { PR_NOT_REACHED("I/O method is invalid"); PR_SetError(PR_INVALID_METHOD_ERROR, 0); return NULL; } /* _PR_InvalidDesc */ PR_IMPLEMENT(PRDescType) PR_GetDescType(PRFileDesc *file) { return file->methods->file_type; } PR_IMPLEMENT(PRStatus) PR_Close(PRFileDesc *fd) { return (fd->methods->close)(fd); } PR_IMPLEMENT(PRInt32) PR_Read(PRFileDesc *fd, void *buf, PRInt32 amount) { return((fd->methods->read)(fd,buf,amount)); } PR_IMPLEMENT(PRInt32) PR_Write(PRFileDesc *fd, const void *buf, PRInt32 amount) { return((fd->methods->write)(fd,buf,amount)); } PR_IMPLEMENT(PRInt32) PR_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) { return((fd->methods->seek)(fd, offset, whence)); } PR_IMPLEMENT(PRInt64) PR_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) { return((fd->methods->seek64)(fd, offset, whence)); } PR_IMPLEMENT(PRInt32) PR_Available(PRFileDesc *fd) { return((fd->methods->available)(fd)); } PR_IMPLEMENT(PRInt64) PR_Available64(PRFileDesc *fd) { return((fd->methods->available64)(fd)); } PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo(PRFileDesc *fd, PRFileInfo *info) { return((fd->methods->fileInfo)(fd, info)); } PR_IMPLEMENT(PRStatus) PR_GetOpenFileInfo64(PRFileDesc *fd, PRFileInfo64 *info) { return((fd->methods->fileInfo64)(fd, info)); } PR_IMPLEMENT(PRStatus) PR_Sync(PRFileDesc *fd) { return((fd->methods->fsync)(fd)); } PR_IMPLEMENT(PRStatus) PR_Connect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { return((fd->methods->connect)(fd,addr,timeout)); } PR_IMPLEMENT(PRStatus) PR_ConnectContinue( PRFileDesc *fd, PRInt16 out_flags) { return((fd->methods->connectcontinue)(fd,out_flags)); } PR_IMPLEMENT(PRFileDesc*) PR_Accept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { return((fd->methods->accept)(fd,addr,timeout)); } PR_IMPLEMENT(PRStatus) PR_Bind(PRFileDesc *fd, const PRNetAddr *addr) { return((fd->methods->bind)(fd,addr)); } PR_IMPLEMENT(PRStatus) PR_Shutdown(PRFileDesc *fd, PRShutdownHow how) { return((fd->methods->shutdown)(fd,how)); } PR_IMPLEMENT(PRStatus) PR_Listen(PRFileDesc *fd, PRIntn backlog) { return((fd->methods->listen)(fd,backlog)); } PR_IMPLEMENT(PRInt32) PR_Recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { return((fd->methods->recv)(fd,buf,amount,flags,timeout)); } PR_IMPLEMENT(PRInt32) PR_Send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { return((fd->methods->send)(fd,buf,amount,flags,timeout)); } PR_IMPLEMENT(PRInt32) PR_Writev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { if (iov_size > PR_MAX_IOVECTOR_SIZE) { PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); return -1; } return((fd->methods->writev)(fd,iov,iov_size,timeout)); } PR_IMPLEMENT(PRInt32) PR_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { return((fd->methods->recvfrom)(fd,buf,amount,flags,addr,timeout)); } PR_IMPLEMENT(PRInt32) PR_SendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { return((fd->methods->sendto)(fd,buf,amount,flags,addr,timeout)); } PR_IMPLEMENT(PRInt32) PR_TransmitFile( PRFileDesc *sd, PRFileDesc *fd, const void *hdr, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout) { return((sd->methods->transmitfile)(sd,fd,hdr,hlen,flags,timeout)); } PR_IMPLEMENT(PRInt32) PR_AcceptRead( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { return((sd->methods->acceptread)(sd, nd, raddr, buf, amount,timeout)); } PR_IMPLEMENT(PRStatus) PR_GetSockName(PRFileDesc *fd, PRNetAddr *addr) { return((fd->methods->getsockname)(fd,addr)); } PR_IMPLEMENT(PRStatus) PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) { return((fd->methods->getpeername)(fd,addr)); } PR_IMPLEMENT(PRStatus) PR_GetSocketOption( PRFileDesc *fd, PRSocketOptionData *data) { return((fd->methods->getsocketoption)(fd, data)); } PR_IMPLEMENT(PRStatus) PR_SetSocketOption( PRFileDesc *fd, const PRSocketOptionData *data) { return((fd->methods->setsocketoption)(fd, data)); } PR_IMPLEMENT(PRInt32) PR_SendFile( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { return((sd->methods->sendfile)(sd,sfd,flags,timeout)); } PR_IMPLEMENT(PRInt32) PR_EmulateAcceptRead( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv = -1; PRNetAddr remote; PRFileDesc *accepted = NULL; /* ** The timeout does not apply to the accept portion of the ** operation - it waits indefinitely. */ accepted = PR_Accept(sd, &remote, PR_INTERVAL_NO_TIMEOUT); if (NULL == accepted) return rv; rv = PR_Recv(accepted, buf, amount, 0, timeout); if (rv >= 0) { /* copy the new info out where caller can see it */ #define AMASK ((PRPtrdiff)7) /* mask for alignment of PRNetAddr */ PRPtrdiff aligned = (PRPtrdiff)buf + amount + AMASK; *raddr = (PRNetAddr*)(aligned & ~AMASK); memcpy(*raddr, &remote, PR_NETADDR_SIZE(&remote)); *nd = accepted; return rv; } PR_Close(accepted); return rv; } /* * PR_EmulateSendFile * * Send file sfd->fd across socket sd. If header/trailer are specified * they are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * */ #if defined(XP_UNIX) || defined(WIN32) /* * An implementation based on memory-mapped files */ #define SENDFILE_MMAP_CHUNK (256 * 1024) PR_IMPLEMENT(PRInt32) PR_EmulateSendFile( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRInt32 rv, count = 0; PRInt32 len, file_bytes, index = 0; PRFileInfo info; PRIOVec iov[3]; PRFileMap *mapHandle = NULL; void *addr = (void*)0; /* initialized to some arbitrary value. Keeps compiler warnings down. */ PRUint32 file_mmap_offset, alignment; PRInt64 zero64; PROffset64 file_mmap_offset64; PRUint32 addr_offset, mmap_len; /* Get file size */ if (PR_SUCCESS != PR_GetOpenFileInfo(sfd->fd, &info)) { count = -1; goto done; } if (sfd->file_nbytes && (info.size < (sfd->file_offset + sfd->file_nbytes))) { /* * there are fewer bytes in file to send than specified */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); count = -1; goto done; } if (sfd->file_nbytes) file_bytes = sfd->file_nbytes; else file_bytes = info.size - sfd->file_offset; alignment = PR_GetMemMapAlignment(); /* number of initial bytes to skip in mmap'd segment */ addr_offset = sfd->file_offset % alignment; /* find previous mmap alignment boundary */ file_mmap_offset = sfd->file_offset - addr_offset; /* * If the file is large, mmap and send the file in chunks so as * to not consume too much virtual address space */ mmap_len = PR_MIN(file_bytes + addr_offset, SENDFILE_MMAP_CHUNK); len = mmap_len - addr_offset; /* * Map in (part of) file. Take care of zero-length files. */ if (len) { LL_I2L(zero64, 0); mapHandle = PR_CreateFileMap(sfd->fd, zero64, PR_PROT_READONLY); if (!mapHandle) { count = -1; goto done; } LL_I2L(file_mmap_offset64, file_mmap_offset); addr = PR_MemMap(mapHandle, file_mmap_offset64, mmap_len); if (!addr) { count = -1; goto done; } } /* * send headers first, followed by the file */ if (sfd->hlen) { iov[index].iov_base = (char *) sfd->header; iov[index].iov_len = sfd->hlen; index++; } if (len) { iov[index].iov_base = (char*)addr + addr_offset; iov[index].iov_len = len; index++; } if ((file_bytes == len) && (sfd->tlen)) { /* * all file data is mapped in; send the trailer too */ iov[index].iov_base = (char *) sfd->trailer; iov[index].iov_len = sfd->tlen; index++; } rv = PR_Writev(sd, iov, index, timeout); if (len) PR_MemUnmap(addr, mmap_len); if (rv < 0) { count = -1; goto done; } PR_ASSERT(rv == sfd->hlen + len + ((len == file_bytes) ? sfd->tlen : 0)); file_bytes -= len; count += rv; if (!file_bytes) /* header, file and trailer are sent */ goto done; /* * send remaining bytes of the file, if any */ len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK); while (len > 0) { /* * Map in (part of) file */ file_mmap_offset = sfd->file_offset + count - sfd->hlen; PR_ASSERT((file_mmap_offset % alignment) == 0); LL_I2L(file_mmap_offset64, file_mmap_offset); addr = PR_MemMap(mapHandle, file_mmap_offset64, len); if (!addr) { count = -1; goto done; } rv = PR_Send(sd, addr, len, 0, timeout); PR_MemUnmap(addr, len); if (rv < 0) { count = -1; goto done; } PR_ASSERT(rv == len); file_bytes -= rv; count += rv; len = PR_MIN(file_bytes, SENDFILE_MMAP_CHUNK); } PR_ASSERT(0 == file_bytes); if (sfd->tlen) { rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout); if (rv >= 0) { PR_ASSERT(rv == sfd->tlen); count += rv; } else count = -1; } done: if (mapHandle) PR_CloseFileMap(mapHandle); if ((count >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET)) PR_Close(sd); return count; } #else PR_IMPLEMENT(PRInt32) PR_EmulateSendFile( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRInt32 rv, count = 0; PRInt32 rlen; const void * buffer; PRInt32 buflen; PRInt32 sendbytes, readbytes; char *buf; #define _SENDFILE_BUFSIZE (16 * 1024) buf = (char*)PR_MALLOC(_SENDFILE_BUFSIZE); if (buf == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } /* * send header first */ buflen = sfd->hlen; buffer = sfd->header; while (buflen) { rv = PR_Send(sd, buffer, buflen, 0, timeout); if (rv < 0) { /* PR_Send() has invoked PR_SetError(). */ rv = -1; goto done; } else { count += rv; buffer = (const void*) ((const char*)buffer + rv); buflen -= rv; } } /* * send file next */ if (PR_Seek(sfd->fd, sfd->file_offset, PR_SEEK_SET) < 0) { rv = -1; goto done; } sendbytes = sfd->file_nbytes; if (sendbytes == 0) { /* send entire file */ while ((rlen = PR_Read(sfd->fd, buf, _SENDFILE_BUFSIZE)) > 0) { while (rlen) { char *bufptr = buf; rv = PR_Send(sd, bufptr, rlen, 0, timeout); if (rv < 0) { /* PR_Send() has invoked PR_SetError(). */ rv = -1; goto done; } else { count += rv; bufptr = ((char*)bufptr + rv); rlen -= rv; } } } if (rlen < 0) { /* PR_Read() has invoked PR_SetError(). */ rv = -1; goto done; } } else { readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE); while (readbytes && ((rlen = PR_Read(sfd->fd, buf, readbytes)) > 0)) { while (rlen) { char *bufptr = buf; rv = PR_Send(sd, bufptr, rlen, 0, timeout); if (rv < 0) { /* PR_Send() has invoked PR_SetError(). */ rv = -1; goto done; } else { count += rv; sendbytes -= rv; bufptr = ((char*)bufptr + rv); rlen -= rv; } } readbytes = PR_MIN(sendbytes, _SENDFILE_BUFSIZE); } if (rlen < 0) { /* PR_Read() has invoked PR_SetError(). */ rv = -1; goto done; } else if (sendbytes != 0) { /* * there are fewer bytes in file to send than specified */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = -1; goto done; } } /* * send trailer last */ buflen = sfd->tlen; buffer = sfd->trailer; while (buflen) { rv = PR_Send(sd, buffer, buflen, 0, timeout); if (rv < 0) { /* PR_Send() has invoked PR_SetError(). */ rv = -1; goto done; } else { count += rv; buffer = (const void*) ((const char*)buffer + rv); buflen -= rv; } } rv = count; done: if (buf) PR_DELETE(buf); if ((rv >= 0) && (flags & PR_TRANSMITFILE_CLOSE_SOCKET)) PR_Close(sd); return rv; } #endif /* priometh.c */ nspr-4.11/nspr/pr/src/io/pripv6.c0000644000000000000000000002450612623070344014752 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: pripv6.c ** Description: Support for various functions unique to IPv6 */ #include "primpl.h" #include #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) static PRIOMethods ipv6_to_v4_tcpMethods; static PRIOMethods ipv6_to_v4_udpMethods; static PRDescIdentity _pr_ipv6_to_ipv4_id; extern PRBool IsValidNetAddr(const PRNetAddr *addr); extern PRIPv6Addr _pr_in6addr_any; extern PRIPv6Addr _pr_in6addr_loopback; /* * convert an IPv4-mapped IPv6 addr to an IPv4 addr */ static void _PR_ConvertToIpv4NetAddr(const PRNetAddr *src_v6addr, PRNetAddr *dst_v4addr) { const PRUint8 *srcp; PR_ASSERT(PR_AF_INET6 == src_v6addr->ipv6.family); if (PR_IsNetAddrType(src_v6addr, PR_IpAddrV4Mapped)) { srcp = src_v6addr->ipv6.ip.pr_s6_addr; memcpy((char *) &dst_v4addr->inet.ip, srcp + 12, 4); } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrAny)) { dst_v4addr->inet.ip = htonl(INADDR_ANY); } else if (PR_IsNetAddrType(src_v6addr, PR_IpAddrLoopback)) { dst_v4addr->inet.ip = htonl(INADDR_LOOPBACK); } dst_v4addr->inet.family = PR_AF_INET; dst_v4addr->inet.port = src_v6addr->ipv6.port; } /* * convert an IPv4 addr to an IPv4-mapped IPv6 addr */ static void _PR_ConvertToIpv6NetAddr(const PRNetAddr *src_v4addr, PRNetAddr *dst_v6addr) { PRUint8 *dstp; PR_ASSERT(PR_AF_INET == src_v4addr->inet.family); dst_v6addr->ipv6.family = PR_AF_INET6; dst_v6addr->ipv6.port = src_v4addr->inet.port; if (htonl(INADDR_ANY) == src_v4addr->inet.ip) { dst_v6addr->ipv6.ip = _pr_in6addr_any; } else { dstp = dst_v6addr->ipv6.ip.pr_s6_addr; memset(dstp, 0, 10); memset(dstp + 10, 0xff, 2); memcpy(dstp + 12,(char *) &src_v4addr->inet.ip, 4); } } static PRStatus PR_CALLBACK Ipv6ToIpv4SocketBind(PRFileDesc *fd, const PRNetAddr *addr) { PRNetAddr tmp_ipv4addr; const PRNetAddr *tmp_addrp; PRFileDesc *lo = fd->lower; if (PR_AF_INET6 != addr->raw.family) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return PR_FAILURE; } if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || PR_IsNetAddrType(addr, PR_IpAddrAny)) { _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); tmp_addrp = &tmp_ipv4addr; } else { PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); return PR_FAILURE; } return((lo->methods->bind)(lo,tmp_addrp)); } static PRStatus PR_CALLBACK Ipv6ToIpv4SocketConnect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PRNetAddr tmp_ipv4addr; const PRNetAddr *tmp_addrp; if (PR_AF_INET6 != addr->raw.family) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return PR_FAILURE; } if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || PR_IsNetAddrType(addr, PR_IpAddrLoopback)) { _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); tmp_addrp = &tmp_ipv4addr; } else { PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); return PR_FAILURE; } return (fd->lower->methods->connect)(fd->lower, tmp_addrp, timeout); } static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketSendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PRNetAddr tmp_ipv4addr; const PRNetAddr *tmp_addrp; if (PR_AF_INET6 != addr->raw.family) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return PR_FAILURE; } if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped) || PR_IsNetAddrType(addr, PR_IpAddrLoopback)) { _PR_ConvertToIpv4NetAddr(addr, &tmp_ipv4addr); tmp_addrp = &tmp_ipv4addr; } else { PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0); return PR_FAILURE; } return (fd->lower->methods->sendto)( fd->lower, buf, amount, flags, tmp_addrp, timeout); } static PRFileDesc* PR_CALLBACK Ipv6ToIpv4SocketAccept ( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PRStatus rv; PRFileDesc *newfd; PRFileDesc *newstack; PRNetAddr tmp_ipv4addr; PRNetAddr *addrlower = NULL; PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); newstack = PR_NEW(PRFileDesc); if (NULL == newstack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } *newstack = *fd; /* make a copy of the accepting layer */ if (addr) addrlower = &tmp_ipv4addr; newfd = (fd->lower->methods->accept)(fd->lower, addrlower, timeout); if (NULL == newfd) { PR_DELETE(newstack); return NULL; } if (addr) _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, addr); rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); PR_ASSERT(PR_SUCCESS == rv); return newfd; /* that's it */ } static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **ipv6_raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 nbytes; PRStatus rv; PRNetAddr tmp_ipv4addr; PRFileDesc *newstack; PR_ASSERT(sd != NULL); PR_ASSERT(sd->lower != NULL); newstack = PR_NEW(PRFileDesc); if (NULL == newstack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } *newstack = *sd; /* make a copy of the accepting layer */ nbytes = sd->lower->methods->acceptread( sd->lower, nd, ipv6_raddr, buf, amount, timeout); if (-1 == nbytes) { PR_DELETE(newstack); return nbytes; } tmp_ipv4addr = **ipv6_raddr; /* copy */ _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, *ipv6_raddr); /* this PR_PushIOLayer call cannot fail */ rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); PR_ASSERT(PR_SUCCESS == rv); return nbytes; } static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetName(PRFileDesc *fd, PRNetAddr *ipv6addr) { PRStatus result; PRNetAddr tmp_ipv4addr; result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr); if (PR_SUCCESS == result) { _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); } return result; } static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetPeerName(PRFileDesc *fd, PRNetAddr *ipv6addr) { PRStatus result; PRNetAddr tmp_ipv4addr; result = (fd->lower->methods->getpeername)(fd->lower, &tmp_ipv4addr); if (PR_SUCCESS == result) { _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); } return result; } static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *ipv6addr, PRIntervalTime timeout) { PRNetAddr tmp_ipv4addr; PRInt32 result; result = (fd->lower->methods->recvfrom)( fd->lower, buf, amount, flags, &tmp_ipv4addr, timeout); if (-1 != result) { _PR_ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr); PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE); } return result; } #if defined(_PR_INET6_PROBE) static PRBool ipv6_is_present; extern PRBool _pr_test_ipv6_socket(void); #if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) extern PRStatus _pr_find_getipnodebyname(void); #endif #if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO) extern PRStatus _pr_find_getaddrinfo(void); #endif static PRBool _pr_probe_ipv6_presence(void) { #if !defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) if (_pr_find_getipnodebyname() != PR_SUCCESS) return PR_FALSE; #endif #if !defined(_PR_INET6) && defined(_PR_HAVE_GETADDRINFO) if (_pr_find_getaddrinfo() != PR_SUCCESS) return PR_FALSE; #endif return _pr_test_ipv6_socket(); } #endif /* _PR_INET6_PROBE */ static PRCallOnceType _pr_init_ipv6_once; static PRStatus PR_CALLBACK _pr_init_ipv6(void) { const PRIOMethods *stubMethods; #if defined(_PR_INET6_PROBE) ipv6_is_present = _pr_probe_ipv6_presence(); if (ipv6_is_present) return PR_SUCCESS; #endif _pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer"); PR_ASSERT(PR_INVALID_IO_LAYER != _pr_ipv6_to_ipv4_id); stubMethods = PR_GetDefaultIOMethods(); ipv6_to_v4_tcpMethods = *stubMethods; /* first get the entire batch */ /* then override the ones we care about */ ipv6_to_v4_tcpMethods.connect = Ipv6ToIpv4SocketConnect; ipv6_to_v4_tcpMethods.bind = Ipv6ToIpv4SocketBind; ipv6_to_v4_tcpMethods.accept = Ipv6ToIpv4SocketAccept; ipv6_to_v4_tcpMethods.acceptread = Ipv6ToIpv4SocketAcceptRead; ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName; ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName; /* ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption; ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption; */ ipv6_to_v4_udpMethods = *stubMethods; /* first get the entire batch */ /* then override the ones we care about */ ipv6_to_v4_udpMethods.connect = Ipv6ToIpv4SocketConnect; ipv6_to_v4_udpMethods.bind = Ipv6ToIpv4SocketBind; ipv6_to_v4_udpMethods.sendto = Ipv6ToIpv4SocketSendTo; ipv6_to_v4_udpMethods.recvfrom = Ipv6ToIpv4SocketRecvFrom; ipv6_to_v4_udpMethods.getsockname = Ipv6ToIpv4SocketGetName; ipv6_to_v4_udpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName; /* ipv6_to_v4_udpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption; ipv6_to_v4_udpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption; */ return PR_SUCCESS; } #if defined(_PR_INET6_PROBE) PRBool _pr_ipv6_is_present(void) { if (PR_CallOnce(&_pr_init_ipv6_once, _pr_init_ipv6) != PR_SUCCESS) return PR_FALSE; return ipv6_is_present; } #endif PR_IMPLEMENT(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd) { PRFileDesc *ipv6_fd = NULL; if (PR_CallOnce(&_pr_init_ipv6_once, _pr_init_ipv6) != PR_SUCCESS) return PR_FAILURE; /* * For platforms with no support for IPv6 * create layered socket for IPv4-mapped IPv6 addresses */ if (fd->methods->file_type == PR_DESC_SOCKET_TCP) ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id, &ipv6_to_v4_tcpMethods); else ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id, &ipv6_to_v4_udpMethods); if (NULL == ipv6_fd) { goto errorExit; } ipv6_fd->secret = NULL; if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, ipv6_fd) == PR_FAILURE) { goto errorExit; } return PR_SUCCESS; errorExit: if (ipv6_fd) ipv6_fd->dtor(ipv6_fd); return PR_FAILURE; } #endif /* !defined(_PR_INET6) || defined(_PR_INET6_PROBE) */ nspr-4.11/nspr/pr/src/io/prlayer.c0000644000000000000000000004646212623070344015207 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prlayer.c ** Description: Routines for handling pushable protocol modules on sockets. */ #include "primpl.h" #include "prerror.h" #include "prmem.h" #include "prlock.h" #include "prlog.h" #include "prio.h" #include /* for memset() */ static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack); void PR_CALLBACK pl_FDDestructor(PRFileDesc *fd) { PR_ASSERT(fd != NULL); if (NULL != fd->lower) fd->lower->higher = fd->higher; if (NULL != fd->higher) fd->higher->lower = fd->lower; PR_DELETE(fd); } /* ** Default methods that just call down to the next fd. */ static PRStatus PR_CALLBACK pl_TopClose (PRFileDesc *fd) { PRFileDesc *top, *lower; PRStatus rv; PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); PR_ASSERT(fd->secret == NULL); PR_ASSERT(fd->methods->file_type == PR_DESC_LAYERED); if (PR_IO_LAYER_HEAD == fd->identity) { /* * new style stack; close all the layers, before deleting the * stack head */ rv = fd->lower->methods->close(fd->lower); _PR_DestroyIOLayer(fd); return rv; } else if ((fd->higher) && (PR_IO_LAYER_HEAD == fd->higher->identity)) { /* * lower layers of new style stack */ lower = fd->lower; /* * pop and cleanup current layer */ top = PR_PopIOLayer(fd->higher, PR_TOP_IO_LAYER); top->dtor(top); /* * then call lower layer */ return (lower->methods->close(lower)); } else { /* old style stack */ top = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); top->dtor(top); return (fd->methods->close)(fd); } } static PRInt32 PR_CALLBACK pl_DefRead (PRFileDesc *fd, void *buf, PRInt32 amount) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->read)(fd->lower, buf, amount); } static PRInt32 PR_CALLBACK pl_DefWrite ( PRFileDesc *fd, const void *buf, PRInt32 amount) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->write)(fd->lower, buf, amount); } static PRInt32 PR_CALLBACK pl_DefAvailable (PRFileDesc *fd) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->available)(fd->lower); } static PRInt64 PR_CALLBACK pl_DefAvailable64 (PRFileDesc *fd) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->available64)(fd->lower); } static PRStatus PR_CALLBACK pl_DefFsync (PRFileDesc *fd) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->fsync)(fd->lower); } static PRInt32 PR_CALLBACK pl_DefSeek ( PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->seek)(fd->lower, offset, how); } static PRInt64 PR_CALLBACK pl_DefSeek64 ( PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->seek64)(fd->lower, offset, how); } static PRStatus PR_CALLBACK pl_DefFileInfo (PRFileDesc *fd, PRFileInfo *info) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->fileInfo)(fd->lower, info); } static PRStatus PR_CALLBACK pl_DefFileInfo64 (PRFileDesc *fd, PRFileInfo64 *info) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->fileInfo64)(fd->lower, info); } static PRInt32 PR_CALLBACK pl_DefWritev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 size, PRIntervalTime timeout) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->writev)(fd->lower, iov, size, timeout); } static PRStatus PR_CALLBACK pl_DefConnect ( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->connect)(fd->lower, addr, timeout); } static PRStatus PR_CALLBACK pl_DefConnectcontinue ( PRFileDesc *fd, PRInt16 out_flags) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->connectcontinue)(fd->lower, out_flags); } static PRFileDesc* PR_CALLBACK pl_TopAccept ( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PRStatus rv; PRFileDesc *newfd, *layer = fd; PRFileDesc *newstack; PRBool newstyle_stack = PR_FALSE; PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); /* test for new style stack */ while (NULL != layer->higher) layer = layer->higher; newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE; newstack = PR_NEW(PRFileDesc); if (NULL == newstack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } *newstack = *fd; /* make a copy of the accepting layer */ newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout); if (NULL == newfd) { PR_DELETE(newstack); return NULL; } if (newstyle_stack) { newstack->lower = newfd; newfd->higher = newstack; return newstack; } else { /* this PR_PushIOLayer call cannot fail */ rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); PR_ASSERT(PR_SUCCESS == rv); return newfd; /* that's it */ } } static PRStatus PR_CALLBACK pl_DefBind (PRFileDesc *fd, const PRNetAddr *addr) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->bind)(fd->lower, addr); } static PRStatus PR_CALLBACK pl_DefListen (PRFileDesc *fd, PRIntn backlog) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->listen)(fd->lower, backlog); } static PRStatus PR_CALLBACK pl_DefShutdown (PRFileDesc *fd, PRIntn how) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->shutdown)(fd->lower, how); } static PRInt32 PR_CALLBACK pl_DefRecv ( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->recv)( fd->lower, buf, amount, flags, timeout); } static PRInt32 PR_CALLBACK pl_DefSend ( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout); } static PRInt32 PR_CALLBACK pl_DefRecvfrom ( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->recvfrom)( fd->lower, buf, amount, flags, addr, timeout); } static PRInt32 PR_CALLBACK pl_DefSendto ( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->sendto)( fd->lower, buf, amount, flags, addr, timeout); } static PRInt16 PR_CALLBACK pl_DefPoll ( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags); } static PRInt32 PR_CALLBACK pl_DefAcceptread ( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime t) { PRInt32 nbytes; PRStatus rv; PRFileDesc *newstack; PRFileDesc *layer = sd; PRBool newstyle_stack = PR_FALSE; PR_ASSERT(sd != NULL); PR_ASSERT(sd->lower != NULL); /* test for new style stack */ while (NULL != layer->higher) layer = layer->higher; newstyle_stack = (PR_IO_LAYER_HEAD == layer->identity) ? PR_TRUE : PR_FALSE; newstack = PR_NEW(PRFileDesc); if (NULL == newstack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } *newstack = *sd; /* make a copy of the accepting layer */ nbytes = sd->lower->methods->acceptread( sd->lower, nd, raddr, buf, amount, t); if (-1 == nbytes) { PR_DELETE(newstack); return nbytes; } if (newstyle_stack) { newstack->lower = *nd; (*nd)->higher = newstack; *nd = newstack; return nbytes; } else { /* this PR_PushIOLayer call cannot fail */ rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack); PR_ASSERT(PR_SUCCESS == rv); return nbytes; } } static PRInt32 PR_CALLBACK pl_DefTransmitfile ( PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime t) { PR_ASSERT(sd != NULL); PR_ASSERT(sd->lower != NULL); return sd->lower->methods->transmitfile( sd->lower, fd, headers, hlen, flags, t); } static PRStatus PR_CALLBACK pl_DefGetsockname (PRFileDesc *fd, PRNetAddr *addr) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->getsockname)(fd->lower, addr); } static PRStatus PR_CALLBACK pl_DefGetpeername (PRFileDesc *fd, PRNetAddr *addr) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->getpeername)(fd->lower, addr); } static PRStatus PR_CALLBACK pl_DefGetsocketoption ( PRFileDesc *fd, PRSocketOptionData *data) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->getsocketoption)(fd->lower, data); } static PRStatus PR_CALLBACK pl_DefSetsocketoption ( PRFileDesc *fd, const PRSocketOptionData *data) { PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); return (fd->lower->methods->setsocketoption)(fd->lower, data); } static PRInt32 PR_CALLBACK pl_DefSendfile ( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { PR_ASSERT(sd != NULL); PR_ASSERT(sd->lower != NULL); return sd->lower->methods->sendfile( sd->lower, sfd, flags, timeout); } /* Methods for the top of the stack. Just call down to the next fd. */ static PRIOMethods pl_methods = { PR_DESC_LAYERED, pl_TopClose, pl_DefRead, pl_DefWrite, pl_DefAvailable, pl_DefAvailable64, pl_DefFsync, pl_DefSeek, pl_DefSeek64, pl_DefFileInfo, pl_DefFileInfo64, pl_DefWritev, pl_DefConnect, pl_TopAccept, pl_DefBind, pl_DefListen, pl_DefShutdown, pl_DefRecv, pl_DefSend, pl_DefRecvfrom, pl_DefSendto, pl_DefPoll, pl_DefAcceptread, pl_DefTransmitfile, pl_DefGetsockname, pl_DefGetpeername, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, pl_DefGetsocketoption, pl_DefSetsocketoption, pl_DefSendfile, pl_DefConnectcontinue, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; PR_IMPLEMENT(const PRIOMethods*) PR_GetDefaultIOMethods(void) { return &pl_methods; } /* PR_GetDefaultIOMethods */ PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayerStub( PRDescIdentity ident, const PRIOMethods *methods) { PRFileDesc *fd = NULL; PR_ASSERT((PR_NSPR_IO_LAYER != ident) && (PR_TOP_IO_LAYER != ident)); if ((PR_NSPR_IO_LAYER == ident) || (PR_TOP_IO_LAYER == ident)) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); else { fd = PR_NEWZAP(PRFileDesc); if (NULL == fd) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); else { fd->methods = methods; fd->dtor = pl_FDDestructor; fd->identity = ident; } } return fd; } /* PR_CreateIOLayerStub */ /* * PR_CreateIOLayer * Create a new style stack, where the stack top is a dummy header. * Unlike the old style stacks, the contents of the stack head * are not modified when a layer is pushed onto or popped from a new * style stack. */ PR_IMPLEMENT(PRFileDesc*) PR_CreateIOLayer(PRFileDesc *top) { PRFileDesc *fd = NULL; fd = PR_NEWZAP(PRFileDesc); if (NULL == fd) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); else { fd->methods = &pl_methods; fd->dtor = pl_FDDestructor; fd->identity = PR_IO_LAYER_HEAD; fd->higher = NULL; fd->lower = top; top->higher = fd; top->lower = NULL; } return fd; } /* PR_CreateIOLayer */ /* * _PR_DestroyIOLayer * Delete the stack head of a new style stack. */ static PRStatus _PR_DestroyIOLayer(PRFileDesc *stack) { if (NULL == stack) return PR_FAILURE; else { PR_DELETE(stack); return PR_SUCCESS; } } /* _PR_DestroyIOLayer */ PR_IMPLEMENT(PRStatus) PR_PushIOLayer( PRFileDesc *stack, PRDescIdentity id, PRFileDesc *fd) { PRFileDesc *insert = PR_GetIdentitiesLayer(stack, id); PR_ASSERT(fd != NULL); PR_ASSERT(stack != NULL); PR_ASSERT(insert != NULL); PR_ASSERT(PR_IO_LAYER_HEAD != id); if ((NULL == stack) || (NULL == fd) || (NULL == insert)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } if (stack == insert) { /* going on top of the stack */ /* old-style stack */ PRFileDesc copy = *stack; *stack = *fd; *fd = copy; fd->higher = stack; if (fd->lower) { PR_ASSERT(fd->lower->higher == stack); fd->lower->higher = fd; } stack->lower = fd; stack->higher = NULL; } else { /* * going somewhere in the middle of the stack for both old and new * style stacks, or going on top of stack for new style stack */ fd->lower = insert; fd->higher = insert->higher; insert->higher->lower = fd; insert->higher = fd; } return PR_SUCCESS; } PR_IMPLEMENT(PRFileDesc*) PR_PopIOLayer(PRFileDesc *stack, PRDescIdentity id) { PRFileDesc *extract = PR_GetIdentitiesLayer(stack, id); PR_ASSERT(0 != id); PR_ASSERT(NULL != stack); PR_ASSERT(NULL != extract); if ((NULL == stack) || (0 == id) || (NULL == extract)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } if (extract == stack) { /* popping top layer of the stack */ /* old style stack */ PRFileDesc copy = *stack; extract = stack->lower; *stack = *extract; *extract = copy; stack->higher = NULL; if (stack->lower) { PR_ASSERT(stack->lower->higher == extract); stack->lower->higher = stack; } } else if ((PR_IO_LAYER_HEAD == stack->identity) && (extract == stack->lower) && (extract->lower == NULL)) { /* * new style stack * popping the only layer in the stack; delete the stack too */ stack->lower = NULL; _PR_DestroyIOLayer(stack); } else { /* for both kinds of stacks */ extract->lower->higher = extract->higher; extract->higher->lower = extract->lower; } extract->higher = extract->lower = NULL; return extract; } /* PR_PopIOLayer */ #define ID_CACHE_INCREMENT 16 typedef struct _PRIdentity_cache { PRLock *ml; char **name; PRIntn length; PRDescIdentity ident; } _PRIdentity_cache; static _PRIdentity_cache identity_cache; PR_IMPLEMENT(PRDescIdentity) PR_GetUniqueIdentity(const char *layer_name) { PRDescIdentity identity, length; char **names = NULL, *name = NULL, **old = NULL; if (!_pr_initialized) _PR_ImplicitInitialization(); PR_ASSERT((PRDescIdentity)0x7fff > identity_cache.ident); if (NULL != layer_name) { name = (char*)PR_Malloc(strlen(layer_name) + 1); if (NULL == name) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return PR_INVALID_IO_LAYER; } strcpy(name, layer_name); } /* this initial code runs unsafe */ retry: PR_ASSERT(NULL == names); /* * In the initial round, both identity_cache.ident and * identity_cache.length are 0, so (identity_cache.ident + 1) is greater * than length. In later rounds, identity_cache.ident is always less * than length, so (identity_cache.ident + 1) can be equal to but cannot * be greater than length. */ length = identity_cache.length; if ((identity_cache.ident + 1) >= length) { length += ID_CACHE_INCREMENT; names = (char**)PR_CALLOC(length * sizeof(char*)); if (NULL == names) { if (NULL != name) PR_DELETE(name); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return PR_INVALID_IO_LAYER; } } /* now we get serious about thread safety */ PR_Lock(identity_cache.ml); PR_ASSERT(identity_cache.length == 0 || identity_cache.ident < identity_cache.length); identity = identity_cache.ident + 1; if (identity >= identity_cache.length) /* there's no room */ { /* we have to do something - hopefully it's already done */ if ((NULL != names) && (identity < length)) { /* what we did is still okay */ memcpy( names, identity_cache.name, identity_cache.length * sizeof(char*)); old = identity_cache.name; identity_cache.name = names; identity_cache.length = length; names = NULL; } else { PR_Unlock(identity_cache.ml); if (NULL != names) PR_DELETE(names); goto retry; } } if (NULL != name) /* there's a name to be stored */ { identity_cache.name[identity] = name; } identity_cache.ident = identity; PR_ASSERT(identity_cache.ident < identity_cache.length); PR_Unlock(identity_cache.ml); if (NULL != old) PR_DELETE(old); if (NULL != names) PR_DELETE(names); return identity; } /* PR_GetUniqueIdentity */ PR_IMPLEMENT(const char*) PR_GetNameForIdentity(PRDescIdentity ident) { if (!_pr_initialized) _PR_ImplicitInitialization(); if (PR_TOP_IO_LAYER == ident) return NULL; PR_ASSERT(ident <= identity_cache.ident); return (ident > identity_cache.ident) ? NULL : identity_cache.name[ident]; } /* PR_GetNameForIdentity */ PR_IMPLEMENT(PRDescIdentity) PR_GetLayersIdentity(PRFileDesc* fd) { PR_ASSERT(NULL != fd); if (PR_IO_LAYER_HEAD == fd->identity) { PR_ASSERT(NULL != fd->lower); return fd->lower->identity; } else return fd->identity; } /* PR_GetLayersIdentity */ PR_IMPLEMENT(PRFileDesc*) PR_GetIdentitiesLayer(PRFileDesc* fd, PRDescIdentity id) { PRFileDesc *layer = fd; if (PR_TOP_IO_LAYER == id) { if (PR_IO_LAYER_HEAD == fd->identity) return fd->lower; else return fd; } for (layer = fd; layer != NULL; layer = layer->lower) { if (id == layer->identity) return layer; } for (layer = fd; layer != NULL; layer = layer->higher) { if (id == layer->identity) return layer; } return NULL; } /* PR_GetIdentitiesLayer */ void _PR_InitLayerCache(void) { memset(&identity_cache, 0, sizeof(identity_cache)); identity_cache.ml = PR_NewLock(); PR_ASSERT(NULL != identity_cache.ml); } /* _PR_InitLayerCache */ void _PR_CleanupLayerCache(void) { if (identity_cache.ml) { PR_DestroyLock(identity_cache.ml); identity_cache.ml = NULL; } if (identity_cache.name) { PRDescIdentity ident; for (ident = 0; ident <= identity_cache.ident; ident++) PR_DELETE(identity_cache.name[ident]); PR_DELETE(identity_cache.name); } } /* _PR_CleanupLayerCache */ /* prlayer.c */ nspr-4.11/nspr/pr/src/io/prlog.c0000644000000000000000000004011612623070344014642 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include "prenv.h" #include "prprf.h" #include #ifdef ANDROID #include #endif /* * Lock used to lock the log. * * We can't define _PR_LOCK_LOG simply as PR_Lock because PR_Lock may * contain assertions. We have to avoid assertions in _PR_LOCK_LOG * because PR_ASSERT calls PR_LogPrint, which in turn calls _PR_LOCK_LOG. * This can lead to infinite recursion. */ static PRLock *_pr_logLock; #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) #define _PR_LOCK_LOG() PR_Lock(_pr_logLock); #define _PR_UNLOCK_LOG() PR_Unlock(_pr_logLock); #elif defined(_PR_GLOBAL_THREADS_ONLY) #define _PR_LOCK_LOG() { _PR_LOCK_LOCK(_pr_logLock) #define _PR_UNLOCK_LOG() _PR_LOCK_UNLOCK(_pr_logLock); } #else #define _PR_LOCK_LOG() \ { \ PRIntn _is; \ PRThread *_me = _PR_MD_CURRENT_THREAD(); \ if (!_PR_IS_NATIVE_THREAD(_me)) \ _PR_INTSOFF(_is); \ _PR_LOCK_LOCK(_pr_logLock) #define _PR_UNLOCK_LOG() \ _PR_LOCK_UNLOCK(_pr_logLock); \ PR_ASSERT(_me == _PR_MD_CURRENT_THREAD()); \ if (!_PR_IS_NATIVE_THREAD(_me)) \ _PR_INTSON(_is); \ } #endif #if defined(XP_PC) #define strcasecmp stricmp #endif /* * On NT, we can't define _PUT_LOG as PR_Write or _PR_MD_WRITE, * because every asynchronous file io operation leads to a fiber context * switch. So we define _PUT_LOG as fputs (from stdio.h). A side * benefit is that fputs handles the LF->CRLF translation. This * code can also be used on other platforms with file stream io. */ #if defined(WIN32) || defined(XP_OS2) #define _PR_USE_STDIO_FOR_LOGGING #endif /* ** Coerce Win32 log output to use OutputDebugString() when ** NSPR_LOG_FILE is set to "WinDebug". */ #if defined(XP_PC) #define WIN32_DEBUG_FILE (FILE*)-2 #endif #ifdef WINCE static void OutputDebugStringA(const char* msg) { int len = MultiByteToWideChar(CP_ACP, 0, msg, -1, 0, 0); WCHAR *wMsg = (WCHAR *)PR_Malloc(len * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, msg, -1, wMsg, len); OutputDebugStringW(wMsg); PR_Free(wMsg); } #endif /* Macros used to reduce #ifdef pollution */ #if defined(_PR_USE_STDIO_FOR_LOGGING) && defined(XP_PC) #define _PUT_LOG(fd, buf, nb) \ PR_BEGIN_MACRO \ if (logFile == WIN32_DEBUG_FILE) { \ char savebyte = buf[nb]; \ buf[nb] = '\0'; \ OutputDebugStringA(buf); \ buf[nb] = savebyte; \ } else { \ fwrite(buf, 1, nb, fd); \ fflush(fd); \ } \ PR_END_MACRO #elif defined(_PR_USE_STDIO_FOR_LOGGING) #define _PUT_LOG(fd, buf, nb) {fwrite(buf, 1, nb, fd); fflush(fd);} #elif defined(ANDROID) #define _PUT_LOG(fd, buf, nb) \ PR_BEGIN_MACRO \ if (fd == _pr_stderr) { \ char savebyte = buf[nb]; \ buf[nb] = '\0'; \ __android_log_write(ANDROID_LOG_INFO, "PRLog", buf); \ buf[nb] = savebyte; \ } else { \ PR_Write(fd, buf, nb); \ } \ PR_END_MACRO #elif defined(_PR_PTHREADS) #define _PUT_LOG(fd, buf, nb) PR_Write(fd, buf, nb) #else #define _PUT_LOG(fd, buf, nb) _PR_MD_WRITE(fd, buf, nb) #endif /************************************************************************/ static PRLogModuleInfo *logModules; static char *logBuf = NULL; static char *logp; static char *logEndp; #ifdef _PR_USE_STDIO_FOR_LOGGING static FILE *logFile = NULL; #else static PRFileDesc *logFile = 0; #endif static PRBool outputTimeStamp = PR_FALSE; static PRBool appendToLog = PR_FALSE; #define LINE_BUF_SIZE 512 #define DEFAULT_BUF_SIZE 16384 #ifdef _PR_NEED_STRCASECMP /* * strcasecmp is defined in /usr/ucblib/libucb.a on some platforms * such as NCR and Unixware. Linking with both libc and libucb * may cause some problem, so I just provide our own implementation * of strcasecmp here. */ static const unsigned char uc[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', '\177' }; PRIntn strcasecmp(const char *a, const char *b) { const unsigned char *ua = (const unsigned char *)a; const unsigned char *ub = (const unsigned char *)b; if( ((const char *)0 == a) || (const char *)0 == b ) return (PRIntn)(a-b); while( (uc[*ua] == uc[*ub]) && ('\0' != *a) ) { a++; ua++; ub++; } return (PRIntn)(uc[*ua] - uc[*ub]); } #endif /* _PR_NEED_STRCASECMP */ void _PR_InitLog(void) { char *ev; _pr_logLock = PR_NewLock(); ev = PR_GetEnv("NSPR_LOG_MODULES"); if (ev && ev[0]) { char module[64]; /* Security-Critical: If you change this * size, you must also change the sscanf * format string to be size-1. */ PRBool isSync = PR_FALSE; PRIntn evlen = strlen(ev), pos = 0; PRInt32 bufSize = DEFAULT_BUF_SIZE; while (pos < evlen) { PRIntn level = 1, count = 0, delta = 0; count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n", module, &delta, &level, &delta); pos += delta; if (count == 0) break; /* ** If count == 2, then we got module and level. If count ** == 1, then level defaults to 1 (module enabled). */ if (strcasecmp(module, "sync") == 0) { isSync = PR_TRUE; } else if (strcasecmp(module, "bufsize") == 0) { if (level >= LINE_BUF_SIZE) { bufSize = level; } } else if (strcasecmp(module, "timestamp") == 0) { outputTimeStamp = PR_TRUE; } else if (strcasecmp(module, "append") == 0) { appendToLog = PR_TRUE; } else { PRLogModuleInfo *lm = logModules; PRBool skip_modcheck = (0 == strcasecmp (module, "all")) ? PR_TRUE : PR_FALSE; while (lm != NULL) { if (skip_modcheck) lm -> level = (PRLogModuleLevel)level; else if (strcasecmp(module, lm->name) == 0) { lm->level = (PRLogModuleLevel)level; break; } lm = lm->next; } } /*found:*/ count = sscanf(&ev[pos], " , %n", &delta); pos += delta; if (count == EOF) break; } PR_SetLogBuffering(isSync ? 0 : bufSize); #ifdef XP_UNIX if ((getuid() != geteuid()) || (getgid() != getegid())) { return; } #endif /* XP_UNIX */ ev = PR_GetEnv("NSPR_LOG_FILE"); if (ev && ev[0]) { if (!PR_SetLogFile(ev)) { #ifdef XP_PC char* str = PR_smprintf("Unable to create nspr log file '%s'\n", ev); if (str) { OutputDebugStringA(str); PR_smprintf_free(str); } #else fprintf(stderr, "Unable to create nspr log file '%s'\n", ev); #endif } } else { #ifdef _PR_USE_STDIO_FOR_LOGGING logFile = stderr; #else logFile = _pr_stderr; #endif } } } void _PR_LogCleanup(void) { PRLogModuleInfo *lm = logModules; PR_LogFlush(); #ifdef _PR_USE_STDIO_FOR_LOGGING if (logFile && logFile != stdout && logFile != stderr #ifdef XP_PC && logFile != WIN32_DEBUG_FILE #endif ) { fclose(logFile); } #else if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) { PR_Close(logFile); } #endif logFile = NULL; if (logBuf) PR_DELETE(logBuf); while (lm != NULL) { PRLogModuleInfo *next = lm->next; free((/*const*/ char *)lm->name); PR_Free(lm); lm = next; } logModules = NULL; if (_pr_logLock) { PR_DestroyLock(_pr_logLock); _pr_logLock = NULL; } } static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm ) { char *ev; ev = PR_GetEnv("NSPR_LOG_MODULES"); if (ev && ev[0]) { char module[64]; /* Security-Critical: If you change this * size, you must also change the sscanf * format string to be size-1. */ PRIntn evlen = strlen(ev), pos = 0; while (pos < evlen) { PRIntn level = 1, count = 0, delta = 0; count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n", module, &delta, &level, &delta); pos += delta; if (count == 0) break; /* ** If count == 2, then we got module and level. If count ** == 1, then level defaults to 1 (module enabled). */ if (lm != NULL) { if ((strcasecmp(module, "all") == 0) || (strcasecmp(module, lm->name) == 0)) { lm->level = (PRLogModuleLevel)level; } } count = sscanf(&ev[pos], " , %n", &delta); pos += delta; if (count == EOF) break; } } } /* end _PR_SetLogModuleLevel() */ PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char *name) { PRLogModuleInfo *lm; if (!_pr_initialized) _PR_ImplicitInitialization(); lm = PR_NEWZAP(PRLogModuleInfo); if (lm) { lm->name = strdup(name); lm->level = PR_LOG_NONE; lm->next = logModules; logModules = lm; _PR_SetLogModuleLevel(lm); } return lm; } PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file) { #ifdef _PR_USE_STDIO_FOR_LOGGING FILE *newLogFile; #ifdef XP_PC if ( strcmp( file, "WinDebug") == 0) { newLogFile = WIN32_DEBUG_FILE; } else #endif { const char *mode = appendToLog ? "a" : "w"; newLogFile = fopen(file, mode); if (!newLogFile) return PR_FALSE; #ifndef WINCE /* _IONBF does not exist in the Windows Mobile 6 SDK. */ /* We do buffering ourselves. */ setvbuf(newLogFile, NULL, _IONBF, 0); #endif } if (logFile && logFile != stdout && logFile != stderr #ifdef XP_PC && logFile != WIN32_DEBUG_FILE #endif ) { fclose(logFile); } logFile = newLogFile; return PR_TRUE; #else PRFileDesc *newLogFile; PRIntn flags = PR_WRONLY|PR_CREATE_FILE; if (appendToLog) { flags |= PR_APPEND; } else { flags |= PR_TRUNCATE; } newLogFile = PR_Open(file, flags, 0666); if (newLogFile) { if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) { PR_Close(logFile); } logFile = newLogFile; } return (PRBool) (newLogFile != 0); #endif /* _PR_USE_STDIO_FOR_LOGGING */ } PR_IMPLEMENT(void) PR_SetLogBuffering(PRIntn buffer_size) { PR_LogFlush(); if (logBuf) PR_DELETE(logBuf); if (buffer_size >= LINE_BUF_SIZE) { logp = logBuf = (char*) PR_MALLOC(buffer_size); logEndp = logp + buffer_size; } } PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...) { va_list ap; char line[LINE_BUF_SIZE]; char *line_long = NULL; PRUint32 nb_tid = 0, nb; PRThread *me; PRExplodedTime now; if (!_pr_initialized) _PR_ImplicitInitialization(); if (!logFile) { return; } if (outputTimeStamp) { PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now); nb_tid = PR_snprintf(line, sizeof(line)-1, "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - ", now.tm_year, now.tm_month + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec); } me = PR_GetCurrentThread(); nb_tid += PR_snprintf(line+nb_tid, sizeof(line)-nb_tid-1, "%ld[%p]: ", #if defined(_PR_BTHREADS) me, me); #else me ? me->id : 0L, me); #endif va_start(ap, fmt); nb = nb_tid + PR_vsnprintf(line+nb_tid, sizeof(line)-nb_tid-1, fmt, ap); va_end(ap); /* * Check if we might have run out of buffer space (in case we have a * long line), and malloc a buffer just this once. */ if (nb == sizeof(line)-2) { va_start(ap, fmt); line_long = PR_vsmprintf(fmt, ap); va_end(ap); /* If this failed, we'll fall back to writing the truncated line. */ } if (line_long) { nb = strlen(line_long); _PR_LOCK_LOG(); if (logBuf != 0) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } /* * Write out the thread id (with an optional timestamp) and the * malloc'ed buffer. */ _PUT_LOG(logFile, line, nb_tid); _PUT_LOG(logFile, line_long, nb); /* Ensure there is a trailing newline. */ if (!nb || (line_long[nb-1] != '\n')) { char eol[2]; eol[0] = '\n'; eol[1] = '\0'; _PUT_LOG(logFile, eol, 1); } _PR_UNLOCK_LOG(); PR_smprintf_free(line_long); } else { /* Ensure there is a trailing newline. */ if (nb && (line[nb-1] != '\n')) { line[nb++] = '\n'; line[nb] = '\0'; } _PR_LOCK_LOG(); if (logBuf == 0) { _PUT_LOG(logFile, line, nb); } else { /* If nb can't fit into logBuf, write out logBuf first. */ if (logp + nb > logEndp) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } /* nb is guaranteed to fit into logBuf. */ memcpy(logp, line, nb); logp += nb; } _PR_UNLOCK_LOG(); } PR_LogFlush(); } PR_IMPLEMENT(void) PR_LogFlush(void) { if (logBuf && logFile) { _PR_LOCK_LOG(); if (logp > logBuf) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } _PR_UNLOCK_LOG(); } } PR_IMPLEMENT(void) PR_Abort(void) { PR_LogPrint("Aborting"); #ifdef ANDROID __android_log_write(ANDROID_LOG_ERROR, "PRLog", "Aborting"); #endif abort(); } PR_IMPLEMENT(void) PR_Assert(const char *s, const char *file, PRIntn ln) { PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln); fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln); fflush(stderr); #ifdef WIN32 DebugBreak(); #elif defined(XP_OS2) asm("int $3"); #elif defined(ANDROID) __android_log_assert(NULL, "PRLog", "Assertion failure: %s, at %s:%d\n", s, file, ln); #endif abort(); } nspr-4.11/nspr/pr/src/io/prmapopt.c0000644000000000000000000003473112623070344015367 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file defines _PR_MapOptionName(). The purpose of putting * _PR_MapOptionName() in a separate file is to work around a Winsock * header file problem on Windows NT. * * On Windows NT, if we define _WIN32_WINNT to be 0x0400 (in order * to use Service Pack 3 extensions), windows.h includes winsock2.h * (instead of winsock.h), which doesn't define many socket options * defined in winsock.h. * * We need the socket options defined in winsock.h. So this file * includes winsock.h, with _WIN32_WINNT undefined. */ #if defined(WINNT) || defined(__MINGW32__) #include #endif /* MinGW doesn't define these in its winsock.h. */ #ifdef __MINGW32__ #ifndef IP_TTL #define IP_TTL 7 #endif #ifndef IP_TOS #define IP_TOS 8 #endif #endif #include "primpl.h" #ifdef HAVE_NETINET_TCP_H #include /* TCP_NODELAY, TCP_MAXSEG */ #endif #ifndef _PR_PTHREADS PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) { PRStatus rv; PRInt32 length; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a getsockopt() call */ if (PR_SockOpt_Nonblocking == data->option) { data->value.non_blocking = fd->secret->nonblocking; return PR_SUCCESS; } rv = _PR_MapOptionName(data->option, &level, &name); if (PR_SUCCESS == rv) { switch (data->option) { case PR_SockOpt_Linger: { #if !defined(XP_BEOS) || defined(BONE_VERSION) struct linger linger; length = sizeof(linger); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char *) &linger, &length); if (PR_SUCCESS == rv) { PR_ASSERT(sizeof(linger) == length); data->value.linger.polarity = (linger.l_onoff) ? PR_TRUE : PR_FALSE; data->value.linger.linger = PR_SecondsToInterval(linger.l_linger); } break; #else PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; #endif } case PR_SockOpt_Reuseaddr: case PR_SockOpt_Keepalive: case PR_SockOpt_NoDelay: case PR_SockOpt_Broadcast: case PR_SockOpt_Reuseport: { #ifdef WIN32 /* Winsock */ BOOL value; #else PRIntn value; #endif length = sizeof(value); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&value, &length); if (PR_SUCCESS == rv) data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE; break; } case PR_SockOpt_McastLoopback: { #ifdef WIN32 /* Winsock */ BOOL bool; #else PRUint8 bool; #endif length = sizeof(bool); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&bool, &length); if (PR_SUCCESS == rv) data->value.mcast_loopback = (0 == bool) ? PR_FALSE : PR_TRUE; break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value; length = sizeof(value); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&value, &length); if (PR_SUCCESS == rv) data->value.recv_buffer_size = value; break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { /* These options should really be an int (or PRIntn). */ length = sizeof(PRUintn); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&data->value.ip_ttl, &length); break; } case PR_SockOpt_McastTimeToLive: { #ifdef WIN32 /* Winsock */ int ttl; #else PRUint8 ttl; #endif length = sizeof(ttl); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&ttl, &length); if (PR_SUCCESS == rv) data->value.mcast_ttl = ttl; break; } #ifdef IP_ADD_MEMBERSHIP case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; length = sizeof(mreq); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&mreq, &length); if (PR_SUCCESS == rv) { data->value.add_member.mcaddr.inet.ip = mreq.imr_multiaddr.s_addr; data->value.add_member.ifaddr.inet.ip = mreq.imr_interface.s_addr; } break; } #endif /* IP_ADD_MEMBERSHIP */ case PR_SockOpt_McastInterface: { /* This option is a struct in_addr. */ length = sizeof(data->value.mcast_if.inet.ip); rv = _PR_MD_GETSOCKOPT( fd, level, name, (char*)&data->value.mcast_if.inet.ip, &length); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } } return rv; } /* _PR_SocketGetSocketOption */ PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data) { PRStatus rv; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a setsockopt call. */ if (PR_SockOpt_Nonblocking == data->option) { #ifdef WINNT PR_ASSERT((fd->secret->md.io_model_committed == PR_FALSE) || (fd->secret->nonblocking == data->value.non_blocking)); if (fd->secret->md.io_model_committed && (fd->secret->nonblocking != data->value.non_blocking)) { /* * On NT, once we have associated a socket with the io * completion port, we can't disassociate it. So we * can't change the nonblocking option of the socket * afterwards. */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #endif fd->secret->nonblocking = data->value.non_blocking; return PR_SUCCESS; } rv = _PR_MapOptionName(data->option, &level, &name); if (PR_SUCCESS == rv) { switch (data->option) { case PR_SockOpt_Linger: { #if !defined(XP_BEOS) || defined(BONE_VERSION) struct linger linger; linger.l_onoff = data->value.linger.polarity; linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger); rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&linger, sizeof(linger)); break; #else PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; #endif } case PR_SockOpt_Reuseaddr: case PR_SockOpt_Keepalive: case PR_SockOpt_NoDelay: case PR_SockOpt_Broadcast: case PR_SockOpt_Reuseport: { #ifdef WIN32 /* Winsock */ BOOL value; #else PRIntn value; #endif value = (data->value.reuse_addr) ? 1 : 0; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&value, sizeof(value)); break; } case PR_SockOpt_McastLoopback: { #ifdef WIN32 /* Winsock */ BOOL bool; #else PRUint8 bool; #endif bool = data->value.mcast_loopback ? 1 : 0; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&bool, sizeof(bool)); break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value = data->value.recv_buffer_size; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&value, sizeof(value)); break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { /* These options should really be an int (or PRIntn). */ rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn)); break; } case PR_SockOpt_McastTimeToLive: { #ifdef WIN32 /* Winsock */ int ttl; #else PRUint8 ttl; #endif ttl = data->value.mcast_ttl; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&ttl, sizeof(ttl)); break; } #ifdef IP_ADD_MEMBERSHIP case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = data->value.add_member.mcaddr.inet.ip; mreq.imr_interface.s_addr = data->value.add_member.ifaddr.inet.ip; rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&mreq, sizeof(mreq)); break; } #endif /* IP_ADD_MEMBERSHIP */ case PR_SockOpt_McastInterface: { /* This option is a struct in_addr. */ rv = _PR_MD_SETSOCKOPT( fd, level, name, (char*)&data->value.mcast_if.inet.ip, sizeof(data->value.mcast_if.inet.ip)); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } } return rv; } /* _PR_SocketSetSocketOption */ #endif /* ! _PR_PTHREADS */ /* ********************************************************************* ********************************************************************* ** ** Make sure that the following is at the end of this file, ** because we will be playing with macro redefines. ** ********************************************************************* ********************************************************************* */ /* * Not every platform has all the socket options we want to * support. Some older operating systems such as SunOS 4.1.3 * don't have the IP multicast socket options. Win32 doesn't * have TCP_MAXSEG. * * To deal with this problem, we define the missing socket * options as _PR_NO_SUCH_SOCKOPT. _PR_MapOptionName() fails with * PR_OPERATION_NOT_SUPPORTED_ERROR if a socket option not * available on the platform is requested. */ /* * Sanity check. SO_LINGER and TCP_NODELAY should be available * on all platforms. Just to make sure we have included the * appropriate header files. Then any undefined socket options * are really missing. */ #if !defined(SO_LINGER) #error "SO_LINGER is not defined" #endif #if !defined(TCP_NODELAY) #error "TCP_NODELAY is not defined" #endif /* * Make sure the value of _PR_NO_SUCH_SOCKOPT is not * a valid socket option. */ #define _PR_NO_SUCH_SOCKOPT -1 #ifndef SO_KEEPALIVE #define SO_KEEPALIVE _PR_NO_SUCH_SOCKOPT #endif #ifndef SO_SNDBUF #define SO_SNDBUF _PR_NO_SUCH_SOCKOPT #endif #ifndef SO_RCVBUF #define SO_RCVBUF _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_MULTICAST_IF /* set/get IP multicast interface */ #define IP_MULTICAST_IF _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_MULTICAST_TTL /* set/get IP multicast timetolive */ #define IP_MULTICAST_TTL _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_MULTICAST_LOOP /* set/get IP multicast loopback */ #define IP_MULTICAST_LOOP _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_ADD_MEMBERSHIP /* add an IP group membership */ #define IP_ADD_MEMBERSHIP _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_DROP_MEMBERSHIP /* drop an IP group membership */ #define IP_DROP_MEMBERSHIP _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_TTL /* set/get IP Time To Live */ #define IP_TTL _PR_NO_SUCH_SOCKOPT #endif #ifndef IP_TOS /* set/get IP Type Of Service */ #define IP_TOS _PR_NO_SUCH_SOCKOPT #endif #ifndef TCP_NODELAY /* don't delay to coalesce data */ #define TCP_NODELAY _PR_NO_SUCH_SOCKOPT #endif #ifndef TCP_MAXSEG /* maxumum segment size for tcp */ #define TCP_MAXSEG _PR_NO_SUCH_SOCKOPT #endif #ifndef SO_BROADCAST /* enable broadcast on UDP sockets */ #define SO_BROADCAST _PR_NO_SUCH_SOCKOPT #endif #ifndef SO_REUSEPORT /* allow local address & port reuse */ #define SO_REUSEPORT _PR_NO_SUCH_SOCKOPT #endif PRStatus _PR_MapOptionName( PRSockOption optname, PRInt32 *level, PRInt32 *name) { static PRInt32 socketOptions[PR_SockOpt_Last] = { 0, SO_LINGER, SO_REUSEADDR, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF, IP_TTL, IP_TOS, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, TCP_NODELAY, TCP_MAXSEG, SO_BROADCAST, SO_REUSEPORT }; static PRInt32 socketLevels[PR_SockOpt_Last] = { 0, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_TCP, IPPROTO_TCP, SOL_SOCKET, SOL_SOCKET }; if ((optname < PR_SockOpt_Linger) || (optname >= PR_SockOpt_Last)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } if (socketOptions[optname] == _PR_NO_SUCH_SOCKOPT) { PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0); return PR_FAILURE; } *name = socketOptions[optname]; *level = socketLevels[optname]; return PR_SUCCESS; } /* _PR_MapOptionName */ nspr-4.11/nspr/pr/src/io/prmmap.c0000644000000000000000000000311112623070344015005 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ********************************************************************* * * Memory-mapped files * ********************************************************************* */ #include "primpl.h" PR_IMPLEMENT(PRFileMap *) PR_CreateFileMap( PRFileDesc *fd, PRInt64 size, PRFileMapProtect prot) { PRFileMap *fmap; PR_ASSERT(prot == PR_PROT_READONLY || prot == PR_PROT_READWRITE || prot == PR_PROT_WRITECOPY); fmap = PR_NEWZAP(PRFileMap); if (NULL == fmap) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } fmap->fd = fd; fmap->prot = prot; if (_PR_MD_CREATE_FILE_MAP(fmap, size) == PR_SUCCESS) { return fmap; } else { PR_DELETE(fmap); return NULL; } } PR_IMPLEMENT(PRInt32) PR_GetMemMapAlignment(void) { return _PR_MD_GET_MEM_MAP_ALIGNMENT(); } PR_IMPLEMENT(void *) PR_MemMap( PRFileMap *fmap, PROffset64 offset, PRUint32 len) { return _PR_MD_MEM_MAP(fmap, offset, len); } PR_IMPLEMENT(PRStatus) PR_MemUnmap(void *addr, PRUint32 len) { return _PR_MD_MEM_UNMAP(addr, len); } PR_IMPLEMENT(PRStatus) PR_CloseFileMap(PRFileMap *fmap) { return _PR_MD_CLOSE_FILE_MAP(fmap); } PR_IMPLEMENT(PRStatus) PR_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len) { return _PR_MD_SYNC_MEM_MAP(fd, addr, len); } nspr-4.11/nspr/pr/src/io/prmwait.c0000644000000000000000000012647712623070344015221 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include "pprmwait.h" #define _MW_REHASH_MAX 11 static PRLock *mw_lock = NULL; static _PRGlobalState *mw_state = NULL; static PRIntervalTime max_polling_interval; #ifdef WINNT typedef struct TimerEvent { PRIntervalTime absolute; void (*func)(void *); void *arg; LONG ref_count; PRCList links; } TimerEvent; #define TIMER_EVENT_PTR(_qp) \ ((TimerEvent *) ((char *) (_qp) - offsetof(TimerEvent, links))) struct { PRLock *ml; PRCondVar *new_timer; PRCondVar *cancel_timer; PRThread *manager_thread; PRCList timer_queue; } tm_vars; static PRStatus TimerInit(void); static void TimerManager(void *arg); static TimerEvent *CreateTimer(PRIntervalTime timeout, void (*func)(void *), void *arg); static PRBool CancelTimer(TimerEvent *timer); static void TimerManager(void *arg) { PRIntervalTime now; PRIntervalTime timeout; PRCList *head; TimerEvent *timer; PR_Lock(tm_vars.ml); while (1) { if (PR_CLIST_IS_EMPTY(&tm_vars.timer_queue)) { PR_WaitCondVar(tm_vars.new_timer, PR_INTERVAL_NO_TIMEOUT); } else { now = PR_IntervalNow(); head = PR_LIST_HEAD(&tm_vars.timer_queue); timer = TIMER_EVENT_PTR(head); if ((PRInt32) (now - timer->absolute) >= 0) { PR_REMOVE_LINK(head); /* * make its prev and next point to itself so that * it's obvious that it's not on the timer_queue. */ PR_INIT_CLIST(head); PR_ASSERT(2 == timer->ref_count); PR_Unlock(tm_vars.ml); timer->func(timer->arg); PR_Lock(tm_vars.ml); timer->ref_count -= 1; if (0 == timer->ref_count) { PR_NotifyAllCondVar(tm_vars.cancel_timer); } } else { timeout = (PRIntervalTime)(timer->absolute - now); PR_WaitCondVar(tm_vars.new_timer, timeout); } } } PR_Unlock(tm_vars.ml); } static TimerEvent *CreateTimer( PRIntervalTime timeout, void (*func)(void *), void *arg) { TimerEvent *timer; PRCList *links, *tail; TimerEvent *elem; timer = PR_NEW(TimerEvent); if (NULL == timer) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return timer; } timer->absolute = PR_IntervalNow() + timeout; timer->func = func; timer->arg = arg; timer->ref_count = 2; PR_Lock(tm_vars.ml); tail = links = PR_LIST_TAIL(&tm_vars.timer_queue); while (links->prev != tail) { elem = TIMER_EVENT_PTR(links); if ((PRInt32)(timer->absolute - elem->absolute) >= 0) { break; } links = links->prev; } PR_INSERT_AFTER(&timer->links, links); PR_NotifyCondVar(tm_vars.new_timer); PR_Unlock(tm_vars.ml); return timer; } static PRBool CancelTimer(TimerEvent *timer) { PRBool canceled = PR_FALSE; PR_Lock(tm_vars.ml); timer->ref_count -= 1; if (timer->links.prev == &timer->links) { while (timer->ref_count == 1) { PR_WaitCondVar(tm_vars.cancel_timer, PR_INTERVAL_NO_TIMEOUT); } } else { PR_REMOVE_LINK(&timer->links); canceled = PR_TRUE; } PR_Unlock(tm_vars.ml); PR_DELETE(timer); return canceled; } static PRStatus TimerInit(void) { tm_vars.ml = PR_NewLock(); if (NULL == tm_vars.ml) { goto failed; } tm_vars.new_timer = PR_NewCondVar(tm_vars.ml); if (NULL == tm_vars.new_timer) { goto failed; } tm_vars.cancel_timer = PR_NewCondVar(tm_vars.ml); if (NULL == tm_vars.cancel_timer) { goto failed; } PR_INIT_CLIST(&tm_vars.timer_queue); tm_vars.manager_thread = PR_CreateThread( PR_SYSTEM_THREAD, TimerManager, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (NULL == tm_vars.manager_thread) { goto failed; } return PR_SUCCESS; failed: if (NULL != tm_vars.cancel_timer) { PR_DestroyCondVar(tm_vars.cancel_timer); } if (NULL != tm_vars.new_timer) { PR_DestroyCondVar(tm_vars.new_timer); } if (NULL != tm_vars.ml) { PR_DestroyLock(tm_vars.ml); } return PR_FAILURE; } #endif /* WINNT */ /******************************************************************/ /******************************************************************/ /************************ The private portion *********************/ /******************************************************************/ /******************************************************************/ void _PR_InitMW(void) { #ifdef WINNT /* * We use NT 4's InterlockedCompareExchange() to operate * on PRMWStatus variables. */ PR_ASSERT(sizeof(LONG) == sizeof(PRMWStatus)); TimerInit(); #endif mw_lock = PR_NewLock(); PR_ASSERT(NULL != mw_lock); mw_state = PR_NEWZAP(_PRGlobalState); PR_ASSERT(NULL != mw_state); PR_INIT_CLIST(&mw_state->group_list); max_polling_interval = PR_MillisecondsToInterval(MAX_POLLING_INTERVAL); } /* _PR_InitMW */ void _PR_CleanupMW(void) { PR_DestroyLock(mw_lock); mw_lock = NULL; if (mw_state->group) { PR_DestroyWaitGroup(mw_state->group); /* mw_state->group is set to NULL as a side effect. */ } PR_DELETE(mw_state); } /* _PR_CleanupMW */ static PRWaitGroup *MW_Init2(void) { PRWaitGroup *group = mw_state->group; /* it's the null group */ if (NULL == group) /* there is this special case */ { group = PR_CreateWaitGroup(_PR_DEFAULT_HASH_LENGTH); if (NULL == group) goto failed_alloc; PR_Lock(mw_lock); if (NULL == mw_state->group) { mw_state->group = group; group = NULL; } PR_Unlock(mw_lock); if (group != NULL) (void)PR_DestroyWaitGroup(group); group = mw_state->group; /* somebody beat us to it */ } failed_alloc: return group; /* whatever */ } /* MW_Init2 */ static _PR_HashStory MW_AddHashInternal(PRRecvWait *desc, _PRWaiterHash *hash) { /* ** The entries are put in the table using the fd (PRFileDesc*) of ** the receive descriptor as the key. This allows us to locate ** the appropriate entry aqain when the poll operation finishes. ** ** The pointer to the file descriptor object is first divided by ** the natural alignment of a pointer in the belief that object ** will have at least that many zeros in the low order bits. ** This may not be a good assuption. ** ** We try to put the entry in by rehashing _MW_REHASH_MAX times. After ** that we declare defeat and force the table to be reconstructed. ** Since some fds might be added more than once, won't that cause ** collisions even in an empty table? */ PRIntn rehash = _MW_REHASH_MAX; PRRecvWait **waiter; PRUintn hidx = _MW_HASH(desc->fd, hash->length); PRUintn hoffset = 0; while (rehash-- > 0) { waiter = &hash->recv_wait; if (NULL == waiter[hidx]) { waiter[hidx] = desc; hash->count += 1; #if 0 printf("Adding 0x%x->0x%x ", desc, desc->fd); printf( "table[%u:%u:*%u]: 0x%x->0x%x\n", hidx, hash->count, hash->length, waiter[hidx], waiter[hidx]->fd); #endif return _prmw_success; } if (desc == waiter[hidx]) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); /* desc already in table */ return _prmw_error; } #if 0 printf("Failing 0x%x->0x%x ", desc, desc->fd); printf( "table[*%u:%u:%u]: 0x%x->0x%x\n", hidx, hash->count, hash->length, waiter[hidx], waiter[hidx]->fd); #endif if (0 == hoffset) { hoffset = _MW_HASH2(desc->fd, hash->length); PR_ASSERT(0 != hoffset); } hidx = (hidx + hoffset) % (hash->length); } return _prmw_rehash; } /* MW_AddHashInternal */ static _PR_HashStory MW_ExpandHashInternal(PRWaitGroup *group) { PRRecvWait **desc; PRUint32 pidx, length; _PRWaiterHash *newHash, *oldHash = group->waiter; PRBool retry; _PR_HashStory hrv; static const PRInt32 prime_number[] = { _PR_DEFAULT_HASH_LENGTH, 179, 521, 907, 1427, 2711, 3917, 5021, 8219, 11549, 18911, 26711, 33749, 44771}; PRUintn primes = (sizeof(prime_number) / sizeof(PRInt32)); /* look up the next size we'd like to use for the hash table */ for (pidx = 0; pidx < primes; ++pidx) { if (prime_number[pidx] == oldHash->length) { break; } } /* table size must be one of the prime numbers */ PR_ASSERT(pidx < primes); /* if pidx == primes - 1, we can't expand the table any more */ while (pidx < primes - 1) { /* next size */ ++pidx; length = prime_number[pidx]; /* allocate the new hash table and fill it in with the old */ newHash = (_PRWaiterHash*)PR_CALLOC( sizeof(_PRWaiterHash) + (length * sizeof(PRRecvWait*))); if (NULL == newHash) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return _prmw_error; } newHash->length = length; retry = PR_FALSE; for (desc = &oldHash->recv_wait; newHash->count < oldHash->count; ++desc) { PR_ASSERT(desc < &oldHash->recv_wait + oldHash->length); if (NULL != *desc) { hrv = MW_AddHashInternal(*desc, newHash); PR_ASSERT(_prmw_error != hrv); if (_prmw_success != hrv) { PR_DELETE(newHash); retry = PR_TRUE; break; } } } if (retry) continue; PR_DELETE(group->waiter); group->waiter = newHash; group->p_timestamp += 1; return _prmw_success; } PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return _prmw_error; /* we're hosed */ } /* MW_ExpandHashInternal */ #ifndef WINNT static void _MW_DoneInternal( PRWaitGroup *group, PRRecvWait **waiter, PRMWStatus outcome) { /* ** Add this receive wait object to the list of finished I/O ** operations for this particular group. If there are other ** threads waiting on the group, notify one. If not, arrange ** for this thread to return. */ #if 0 printf("Removing 0x%x->0x%x\n", *waiter, (*waiter)->fd); #endif (*waiter)->outcome = outcome; PR_APPEND_LINK(&((*waiter)->internal), &group->io_ready); PR_NotifyCondVar(group->io_complete); PR_ASSERT(0 != group->waiter->count); group->waiter->count -= 1; *waiter = NULL; } /* _MW_DoneInternal */ #endif /* WINNT */ static PRRecvWait **_MW_LookupInternal(PRWaitGroup *group, PRFileDesc *fd) { /* ** Find the receive wait object corresponding to the file descriptor. ** Only search the wait group specified. */ PRRecvWait **desc; PRIntn rehash = _MW_REHASH_MAX; _PRWaiterHash *hash = group->waiter; PRUintn hidx = _MW_HASH(fd, hash->length); PRUintn hoffset = 0; while (rehash-- > 0) { desc = (&hash->recv_wait) + hidx; if ((*desc != NULL) && ((*desc)->fd == fd)) return desc; if (0 == hoffset) { hoffset = _MW_HASH2(fd, hash->length); PR_ASSERT(0 != hoffset); } hidx = (hidx + hoffset) % (hash->length); } return NULL; } /* _MW_LookupInternal */ #ifndef WINNT static PRStatus _MW_PollInternal(PRWaitGroup *group) { PRRecvWait **waiter; PRStatus rv = PR_FAILURE; PRInt32 count, count_ready; PRIntervalTime polling_interval; group->poller = PR_GetCurrentThread(); while (PR_TRUE) { PRIntervalTime now, since_last_poll; PRPollDesc *poll_list; while (0 == group->waiter->count) { PRStatus st; st = PR_WaitCondVar(group->new_business, PR_INTERVAL_NO_TIMEOUT); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } if (_MW_ABORTED(st)) goto aborted; } /* ** There's something to do. See if our existing polling list ** is large enough for what we have to do? */ while (group->polling_count < group->waiter->count) { PRUint32 old_count = group->waiter->count; PRUint32 new_count = PR_ROUNDUP(old_count, _PR_POLL_COUNT_FUDGE); PRSize new_size = sizeof(PRPollDesc) * new_count; PRPollDesc *old_polling_list = group->polling_list; PR_Unlock(group->ml); poll_list = (PRPollDesc*)PR_CALLOC(new_size); if (NULL == poll_list) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); PR_Lock(group->ml); goto failed_alloc; } if (NULL != old_polling_list) PR_DELETE(old_polling_list); PR_Lock(group->ml); if (_prmw_running != group->state) { PR_DELETE(poll_list); PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } group->polling_list = poll_list; group->polling_count = new_count; } now = PR_IntervalNow(); polling_interval = max_polling_interval; since_last_poll = now - group->last_poll; waiter = &group->waiter->recv_wait; poll_list = group->polling_list; for (count = 0; count < group->waiter->count; ++waiter) { PR_ASSERT(waiter < &group->waiter->recv_wait + group->waiter->length); if (NULL != *waiter) /* a live one! */ { if ((PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout) && (since_last_poll >= (*waiter)->timeout)) _MW_DoneInternal(group, waiter, PR_MW_TIMEOUT); else { if (PR_INTERVAL_NO_TIMEOUT != (*waiter)->timeout) { (*waiter)->timeout -= since_last_poll; if ((*waiter)->timeout < polling_interval) polling_interval = (*waiter)->timeout; } PR_ASSERT(poll_list < group->polling_list + group->polling_count); poll_list->fd = (*waiter)->fd; poll_list->in_flags = PR_POLL_READ; poll_list->out_flags = 0; #if 0 printf( "Polling 0x%x[%d]: [fd: 0x%x, tmo: %u]\n", poll_list, count, poll_list->fd, (*waiter)->timeout); #endif poll_list += 1; count += 1; } } } PR_ASSERT(count == group->waiter->count); /* ** If there are no more threads waiting for completion, ** we need to return. */ if ((!PR_CLIST_IS_EMPTY(&group->io_ready)) && (1 == group->waiting_threads)) break; if (0 == count) continue; /* wait for new business */ group->last_poll = now; PR_Unlock(group->ml); count_ready = PR_Poll(group->polling_list, count, polling_interval); PR_Lock(group->ml); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } if (-1 == count_ready) { goto failed_poll; /* that's a shame */ } else if (0 < count_ready) { for (poll_list = group->polling_list; count > 0; poll_list++, count--) { PR_ASSERT( poll_list < group->polling_list + group->polling_count); if (poll_list->out_flags != 0) { waiter = _MW_LookupInternal(group, poll_list->fd); /* ** If 'waiter' is NULL, that means the wait receive ** descriptor has been canceled. */ if (NULL != waiter) _MW_DoneInternal(group, waiter, PR_MW_SUCCESS); } } } /* ** If there are no more threads waiting for completion, ** we need to return. ** This thread was "borrowed" to do the polling, but it really ** belongs to the client. */ if ((!PR_CLIST_IS_EMPTY(&group->io_ready)) && (1 == group->waiting_threads)) break; } rv = PR_SUCCESS; aborted: failed_poll: failed_alloc: group->poller = NULL; /* we were that, not we ain't */ if ((_prmw_running == group->state) && (group->waiting_threads > 1)) { /* Wake up one thread to become the new poller. */ PR_NotifyCondVar(group->io_complete); } return rv; /* we return with the lock held */ } /* _MW_PollInternal */ #endif /* !WINNT */ static PRMWGroupState MW_TestForShutdownInternal(PRWaitGroup *group) { PRMWGroupState rv = group->state; /* ** Looking at the group's fields is safe because ** once the group's state is no longer running, it ** cannot revert and there is a safe check on entry ** to make sure no more threads are made to wait. */ if ((_prmw_stopping == rv) && (0 == group->waiting_threads)) { rv = group->state = _prmw_stopped; PR_NotifyCondVar(group->mw_manage); } return rv; } /* MW_TestForShutdownInternal */ #ifndef WINNT static void _MW_InitialRecv(PRCList *io_ready) { PRRecvWait *desc = (PRRecvWait*)io_ready; if ((NULL == desc->buffer.start) || (0 == desc->buffer.length)) desc->bytesRecv = 0; else { desc->bytesRecv = (desc->fd->methods->recv)( desc->fd, desc->buffer.start, desc->buffer.length, 0, desc->timeout); if (desc->bytesRecv < 0) /* SetError should already be there */ desc->outcome = PR_MW_FAILURE; } } /* _MW_InitialRecv */ #endif #ifdef WINNT static void NT_TimeProc(void *arg) { _MDOverlapped *overlapped = (_MDOverlapped *)arg; PRRecvWait *desc = overlapped->data.mw.desc; PRFileDesc *bottom; if (InterlockedCompareExchange((LONG *)&desc->outcome, (LONG)PR_MW_TIMEOUT, (LONG)PR_MW_PENDING) != (LONG)PR_MW_PENDING) { /* This wait recv descriptor has already completed. */ return; } /* close the osfd to abort the outstanding async io request */ /* $$$$ ** Little late to be checking if NSPR's on the bottom of stack, ** but if we don't check, we can't assert that the private data ** is what we think it is. ** $$$$ */ bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); if (NULL != bottom) /* now what!?!?! */ { bottom->secret->state = _PR_FILEDESC_CLOSED; if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR) { fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError()); PR_NOT_REACHED("What shall I do?"); } } return; } /* NT_TimeProc */ static PRStatus NT_HashRemove(PRWaitGroup *group, PRFileDesc *fd) { PRRecvWait **waiter; _PR_MD_LOCK(&group->mdlock); waiter = _MW_LookupInternal(group, fd); if (NULL != waiter) { group->waiter->count -= 1; *waiter = NULL; } _PR_MD_UNLOCK(&group->mdlock); return (NULL != waiter) ? PR_SUCCESS : PR_FAILURE; } PRStatus NT_HashRemoveInternal(PRWaitGroup *group, PRFileDesc *fd) { PRRecvWait **waiter; waiter = _MW_LookupInternal(group, fd); if (NULL != waiter) { group->waiter->count -= 1; *waiter = NULL; } return (NULL != waiter) ? PR_SUCCESS : PR_FAILURE; } #endif /* WINNT */ /******************************************************************/ /******************************************************************/ /********************** The public API portion ********************/ /******************************************************************/ /******************************************************************/ PR_IMPLEMENT(PRStatus) PR_AddWaitFileDesc( PRWaitGroup *group, PRRecvWait *desc) { _PR_HashStory hrv; PRStatus rv = PR_FAILURE; #ifdef WINNT _MDOverlapped *overlapped; HANDLE hFile; BOOL bResult; DWORD dwError; PRFileDesc *bottom; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); if ((NULL == group) && (NULL == (group = MW_Init2()))) { return rv; } PR_ASSERT(NULL != desc->fd); desc->outcome = PR_MW_PENDING; /* nice, well known value */ desc->bytesRecv = 0; /* likewise, though this value is ambiguious */ PR_Lock(group->ml); if (_prmw_running != group->state) { /* Not allowed to add after cancelling the group */ desc->outcome = PR_MW_INTERRUPT; PR_SetError(PR_INVALID_STATE_ERROR, 0); PR_Unlock(group->ml); return rv; } #ifdef WINNT _PR_MD_LOCK(&group->mdlock); #endif /* ** If the waiter count is zero at this point, there's no telling ** how long we've been idle. Therefore, initialize the beginning ** of the timing interval. As long as the list doesn't go empty, ** it will maintain itself. */ if (0 == group->waiter->count) group->last_poll = PR_IntervalNow(); do { hrv = MW_AddHashInternal(desc, group->waiter); if (_prmw_rehash != hrv) break; hrv = MW_ExpandHashInternal(group); /* gruesome */ if (_prmw_success != hrv) break; } while (PR_TRUE); #ifdef WINNT _PR_MD_UNLOCK(&group->mdlock); #endif PR_NotifyCondVar(group->new_business); /* tell the world */ rv = (_prmw_success == hrv) ? PR_SUCCESS : PR_FAILURE; PR_Unlock(group->ml); #ifdef WINNT overlapped = PR_NEWZAP(_MDOverlapped); if (NULL == overlapped) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); NT_HashRemove(group, desc->fd); return rv; } overlapped->ioModel = _MD_MultiWaitIO; overlapped->data.mw.desc = desc; overlapped->data.mw.group = group; if (desc->timeout != PR_INTERVAL_NO_TIMEOUT) { overlapped->data.mw.timer = CreateTimer( desc->timeout, NT_TimeProc, overlapped); if (0 == overlapped->data.mw.timer) { NT_HashRemove(group, desc->fd); PR_DELETE(overlapped); /* * XXX It appears that a maximum of 16 timer events can * be outstanding. GetLastError() returns 0 when I try it. */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, GetLastError()); return PR_FAILURE; } } /* Reach to the bottom layer to get the OS fd */ bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); if (NULL == bottom) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } hFile = (HANDLE)bottom->secret->md.osfd; if (!bottom->secret->md.io_model_committed) { PRInt32 st; st = _md_Associate(hFile); PR_ASSERT(0 != st); bottom->secret->md.io_model_committed = PR_TRUE; } bResult = ReadFile(hFile, desc->buffer.start, (DWORD)desc->buffer.length, NULL, &overlapped->overlapped); if (FALSE == bResult && (dwError = GetLastError()) != ERROR_IO_PENDING) { if (desc->timeout != PR_INTERVAL_NO_TIMEOUT) { if (InterlockedCompareExchange((LONG *)&desc->outcome, (LONG)PR_MW_FAILURE, (LONG)PR_MW_PENDING) == (LONG)PR_MW_PENDING) { CancelTimer(overlapped->data.mw.timer); } NT_HashRemove(group, desc->fd); PR_DELETE(overlapped); } _PR_MD_MAP_READ_ERROR(dwError); rv = PR_FAILURE; } #endif return rv; } /* PR_AddWaitFileDesc */ PR_IMPLEMENT(PRRecvWait*) PR_WaitRecvReady(PRWaitGroup *group) { PRCList *io_ready = NULL; #ifdef WINNT PRThread *me = _PR_MD_CURRENT_THREAD(); _MDOverlapped *overlapped; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); if ((NULL == group) && (NULL == (group = MW_Init2()))) goto failed_init; PR_Lock(group->ml); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto invalid_state; } group->waiting_threads += 1; /* the polling thread is counted */ #ifdef WINNT _PR_MD_LOCK(&group->mdlock); while (PR_CLIST_IS_EMPTY(&group->io_ready)) { _PR_THREAD_LOCK(me); me->state = _PR_IO_WAIT; PR_APPEND_LINK(&me->waitQLinks, &group->wait_list); if (!_PR_IS_NATIVE_THREAD(me)) { _PR_SLEEPQ_LOCK(me->cpu); _PR_ADD_SLEEPQ(me, PR_INTERVAL_NO_TIMEOUT); _PR_SLEEPQ_UNLOCK(me->cpu); } _PR_THREAD_UNLOCK(me); _PR_MD_UNLOCK(&group->mdlock); PR_Unlock(group->ml); _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT); me->state = _PR_RUNNING; PR_Lock(group->ml); _PR_MD_LOCK(&group->mdlock); if (_PR_PENDING_INTERRUPT(me)) { PR_REMOVE_LINK(&me->waitQLinks); _PR_MD_UNLOCK(&group->mdlock); me->flags &= ~_PR_INTERRUPT; me->io_suspended = PR_FALSE; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); goto aborted; } } io_ready = PR_LIST_HEAD(&group->io_ready); PR_ASSERT(io_ready != NULL); PR_REMOVE_LINK(io_ready); _PR_MD_UNLOCK(&group->mdlock); overlapped = (_MDOverlapped *) ((char *)io_ready - offsetof(_MDOverlapped, data)); io_ready = &overlapped->data.mw.desc->internal; #else do { /* ** If the I/O ready list isn't empty, have this thread ** return with the first receive wait object that's available. */ if (PR_CLIST_IS_EMPTY(&group->io_ready)) { /* ** Is there a polling thread yet? If not, grab this thread ** and use it. */ if (NULL == group->poller) { /* ** This thread will stay do polling until it becomes the only one ** left to service a completion. Then it will return and there will ** be none left to actually poll or to run completions. ** ** The polling function should only return w/ failure or ** with some I/O ready. */ if (PR_FAILURE == _MW_PollInternal(group)) goto failed_poll; } else { /* ** There are four reasons a thread can be awakened from ** a wait on the io_complete condition variable. ** 1. Some I/O has completed, i.e., the io_ready list ** is nonempty. ** 2. The wait group is canceled. ** 3. The thread is interrupted. ** 4. The current polling thread has to leave and needs ** a replacement. ** The logic to find a new polling thread is made more ** complicated by all the other possible events. ** I tried my best to write the logic clearly, but ** it is still full of if's with continue and goto. */ PRStatus st; do { st = PR_WaitCondVar(group->io_complete, PR_INTERVAL_NO_TIMEOUT); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); goto aborted; } if (_MW_ABORTED(st) || (NULL == group->poller)) break; } while (PR_CLIST_IS_EMPTY(&group->io_ready)); /* ** The thread is interrupted and has to leave. It might ** have also been awakened to process ready i/o or be the ** new poller. To be safe, if either condition is true, ** we awaken another thread to take its place. */ if (_MW_ABORTED(st)) { if ((NULL == group->poller || !PR_CLIST_IS_EMPTY(&group->io_ready)) && group->waiting_threads > 1) PR_NotifyCondVar(group->io_complete); goto aborted; } /* ** A new poller is needed, but can I be the new poller? ** If there is no i/o ready, sure. But if there is any ** i/o ready, it has a higher priority. I want to ** process the ready i/o first and wake up another ** thread to be the new poller. */ if (NULL == group->poller) { if (PR_CLIST_IS_EMPTY(&group->io_ready)) continue; if (group->waiting_threads > 1) PR_NotifyCondVar(group->io_complete); } } PR_ASSERT(!PR_CLIST_IS_EMPTY(&group->io_ready)); } io_ready = PR_LIST_HEAD(&group->io_ready); PR_NotifyCondVar(group->io_taken); PR_ASSERT(io_ready != NULL); PR_REMOVE_LINK(io_ready); } while (NULL == io_ready); failed_poll: #endif aborted: group->waiting_threads -= 1; invalid_state: (void)MW_TestForShutdownInternal(group); PR_Unlock(group->ml); failed_init: if (NULL != io_ready) { /* If the operation failed, record the reason why */ switch (((PRRecvWait*)io_ready)->outcome) { case PR_MW_PENDING: PR_ASSERT(0); break; case PR_MW_SUCCESS: #ifndef WINNT _MW_InitialRecv(io_ready); #endif break; #ifdef WINNT case PR_MW_FAILURE: _PR_MD_MAP_READ_ERROR(overlapped->data.mw.error); break; #endif case PR_MW_TIMEOUT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_MW_INTERRUPT: PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); break; default: break; } #ifdef WINNT if (NULL != overlapped->data.mw.timer) { PR_ASSERT(PR_INTERVAL_NO_TIMEOUT != overlapped->data.mw.desc->timeout); CancelTimer(overlapped->data.mw.timer); } else { PR_ASSERT(PR_INTERVAL_NO_TIMEOUT == overlapped->data.mw.desc->timeout); } PR_DELETE(overlapped); #endif } return (PRRecvWait*)io_ready; } /* PR_WaitRecvReady */ PR_IMPLEMENT(PRStatus) PR_CancelWaitFileDesc(PRWaitGroup *group, PRRecvWait *desc) { #if !defined(WINNT) PRRecvWait **recv_wait; #endif PRStatus rv = PR_SUCCESS; if (NULL == group) group = mw_state->group; PR_ASSERT(NULL != group); if (NULL == group) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } PR_Lock(group->ml); if (_prmw_running != group->state) { PR_SetError(PR_INVALID_STATE_ERROR, 0); rv = PR_FAILURE; goto unlock; } #ifdef WINNT if (InterlockedCompareExchange((LONG *)&desc->outcome, (LONG)PR_MW_INTERRUPT, (LONG)PR_MW_PENDING) == (LONG)PR_MW_PENDING) { PRFileDesc *bottom = PR_GetIdentitiesLayer(desc->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); if (NULL == bottom) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); goto unlock; } bottom->secret->state = _PR_FILEDESC_CLOSED; #if 0 fprintf(stderr, "cancel wait recv: closing socket\n"); #endif if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR) { fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError()); exit(1); } } #else if (NULL != (recv_wait = _MW_LookupInternal(group, desc->fd))) { /* it was in the wait table */ _MW_DoneInternal(group, recv_wait, PR_MW_INTERRUPT); goto unlock; } if (!PR_CLIST_IS_EMPTY(&group->io_ready)) { /* is it already complete? */ PRCList *head = PR_LIST_HEAD(&group->io_ready); do { PRRecvWait *done = (PRRecvWait*)head; if (done == desc) goto unlock; head = PR_NEXT_LINK(head); } while (head != &group->io_ready); } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = PR_FAILURE; #endif unlock: PR_Unlock(group->ml); return rv; } /* PR_CancelWaitFileDesc */ PR_IMPLEMENT(PRRecvWait*) PR_CancelWaitGroup(PRWaitGroup *group) { PRRecvWait **desc; PRRecvWait *recv_wait = NULL; #ifdef WINNT _MDOverlapped *overlapped; PRRecvWait **end; PRThread *me = _PR_MD_CURRENT_THREAD(); #endif if (NULL == group) group = mw_state->group; PR_ASSERT(NULL != group); if (NULL == group) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } PR_Lock(group->ml); if (_prmw_stopped != group->state) { if (_prmw_running == group->state) group->state = _prmw_stopping; /* so nothing new comes in */ if (0 == group->waiting_threads) /* is there anybody else? */ group->state = _prmw_stopped; /* we can stop right now */ else { PR_NotifyAllCondVar(group->new_business); PR_NotifyAllCondVar(group->io_complete); } while (_prmw_stopped != group->state) (void)PR_WaitCondVar(group->mw_manage, PR_INTERVAL_NO_TIMEOUT); } #ifdef WINNT _PR_MD_LOCK(&group->mdlock); #endif /* make all the existing descriptors look done/interrupted */ #ifdef WINNT end = &group->waiter->recv_wait + group->waiter->length; for (desc = &group->waiter->recv_wait; desc < end; ++desc) { if (NULL != *desc) { if (InterlockedCompareExchange((LONG *)&(*desc)->outcome, (LONG)PR_MW_INTERRUPT, (LONG)PR_MW_PENDING) == (LONG)PR_MW_PENDING) { PRFileDesc *bottom = PR_GetIdentitiesLayer( (*desc)->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); if (NULL == bottom) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); goto invalid_arg; } bottom->secret->state = _PR_FILEDESC_CLOSED; #if 0 fprintf(stderr, "cancel wait group: closing socket\n"); #endif if (closesocket(bottom->secret->md.osfd) == SOCKET_ERROR) { fprintf(stderr, "closesocket failed: %d\n", WSAGetLastError()); exit(1); } } } } while (group->waiter->count > 0) { _PR_THREAD_LOCK(me); me->state = _PR_IO_WAIT; PR_APPEND_LINK(&me->waitQLinks, &group->wait_list); if (!_PR_IS_NATIVE_THREAD(me)) { _PR_SLEEPQ_LOCK(me->cpu); _PR_ADD_SLEEPQ(me, PR_INTERVAL_NO_TIMEOUT); _PR_SLEEPQ_UNLOCK(me->cpu); } _PR_THREAD_UNLOCK(me); _PR_MD_UNLOCK(&group->mdlock); PR_Unlock(group->ml); _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT); me->state = _PR_RUNNING; PR_Lock(group->ml); _PR_MD_LOCK(&group->mdlock); } #else for (desc = &group->waiter->recv_wait; group->waiter->count > 0; ++desc) { PR_ASSERT(desc < &group->waiter->recv_wait + group->waiter->length); if (NULL != *desc) _MW_DoneInternal(group, desc, PR_MW_INTERRUPT); } #endif /* take first element of finished list and return it or NULL */ if (PR_CLIST_IS_EMPTY(&group->io_ready)) PR_SetError(PR_GROUP_EMPTY_ERROR, 0); else { PRCList *head = PR_LIST_HEAD(&group->io_ready); PR_REMOVE_AND_INIT_LINK(head); #ifdef WINNT overlapped = (_MDOverlapped *) ((char *)head - offsetof(_MDOverlapped, data)); head = &overlapped->data.mw.desc->internal; if (NULL != overlapped->data.mw.timer) { PR_ASSERT(PR_INTERVAL_NO_TIMEOUT != overlapped->data.mw.desc->timeout); CancelTimer(overlapped->data.mw.timer); } else { PR_ASSERT(PR_INTERVAL_NO_TIMEOUT == overlapped->data.mw.desc->timeout); } PR_DELETE(overlapped); #endif recv_wait = (PRRecvWait*)head; } #ifdef WINNT invalid_arg: _PR_MD_UNLOCK(&group->mdlock); #endif PR_Unlock(group->ml); return recv_wait; } /* PR_CancelWaitGroup */ PR_IMPLEMENT(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size /* ignored */) { PRWaitGroup *wg; if (NULL == (wg = PR_NEWZAP(PRWaitGroup))) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto failed; } /* the wait group itself */ wg->ml = PR_NewLock(); if (NULL == wg->ml) goto failed_lock; wg->io_taken = PR_NewCondVar(wg->ml); if (NULL == wg->io_taken) goto failed_cvar0; wg->io_complete = PR_NewCondVar(wg->ml); if (NULL == wg->io_complete) goto failed_cvar1; wg->new_business = PR_NewCondVar(wg->ml); if (NULL == wg->new_business) goto failed_cvar2; wg->mw_manage = PR_NewCondVar(wg->ml); if (NULL == wg->mw_manage) goto failed_cvar3; PR_INIT_CLIST(&wg->group_link); PR_INIT_CLIST(&wg->io_ready); /* the waiters sequence */ wg->waiter = (_PRWaiterHash*)PR_CALLOC( sizeof(_PRWaiterHash) + (_PR_DEFAULT_HASH_LENGTH * sizeof(PRRecvWait*))); if (NULL == wg->waiter) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto failed_waiter; } wg->waiter->count = 0; wg->waiter->length = _PR_DEFAULT_HASH_LENGTH; #ifdef WINNT _PR_MD_NEW_LOCK(&wg->mdlock); PR_INIT_CLIST(&wg->wait_list); #endif /* WINNT */ PR_Lock(mw_lock); PR_APPEND_LINK(&wg->group_link, &mw_state->group_list); PR_Unlock(mw_lock); return wg; failed_waiter: PR_DestroyCondVar(wg->mw_manage); failed_cvar3: PR_DestroyCondVar(wg->new_business); failed_cvar2: PR_DestroyCondVar(wg->io_complete); failed_cvar1: PR_DestroyCondVar(wg->io_taken); failed_cvar0: PR_DestroyLock(wg->ml); failed_lock: PR_DELETE(wg); wg = NULL; failed: return wg; } /* MW_CreateWaitGroup */ PR_IMPLEMENT(PRStatus) PR_DestroyWaitGroup(PRWaitGroup *group) { PRStatus rv = PR_SUCCESS; if (NULL == group) group = mw_state->group; PR_ASSERT(NULL != group); if (NULL != group) { PR_Lock(group->ml); if ((group->waiting_threads == 0) && (group->waiter->count == 0) && PR_CLIST_IS_EMPTY(&group->io_ready)) { group->state = _prmw_stopped; } else { PR_SetError(PR_INVALID_STATE_ERROR, 0); rv = PR_FAILURE; } PR_Unlock(group->ml); if (PR_FAILURE == rv) return rv; PR_Lock(mw_lock); PR_REMOVE_LINK(&group->group_link); PR_Unlock(mw_lock); #ifdef WINNT /* * XXX make sure wait_list is empty and waiter is empty. * These must be checked while holding mdlock. */ _PR_MD_FREE_LOCK(&group->mdlock); #endif PR_DELETE(group->waiter); PR_DELETE(group->polling_list); PR_DestroyCondVar(group->mw_manage); PR_DestroyCondVar(group->new_business); PR_DestroyCondVar(group->io_complete); PR_DestroyCondVar(group->io_taken); PR_DestroyLock(group->ml); if (group == mw_state->group) mw_state->group = NULL; PR_DELETE(group); } else { /* The default wait group is not created yet. */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = PR_FAILURE; } return rv; } /* PR_DestroyWaitGroup */ /********************************************************************** *********************************************************************** ******************** Wait group enumerations ************************** *********************************************************************** **********************************************************************/ PR_IMPLEMENT(PRMWaitEnumerator*) PR_CreateMWaitEnumerator(PRWaitGroup *group) { PRMWaitEnumerator *enumerator = PR_NEWZAP(PRMWaitEnumerator); if (NULL == enumerator) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); else { enumerator->group = group; enumerator->seal = _PR_ENUM_SEALED; } return enumerator; } /* PR_CreateMWaitEnumerator */ PR_IMPLEMENT(PRStatus) PR_DestroyMWaitEnumerator(PRMWaitEnumerator* enumerator) { PR_ASSERT(NULL != enumerator); PR_ASSERT(_PR_ENUM_SEALED == enumerator->seal); if ((NULL == enumerator) || (_PR_ENUM_SEALED != enumerator->seal)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } enumerator->seal = _PR_ENUM_UNSEALED; PR_Free(enumerator); return PR_SUCCESS; } /* PR_DestroyMWaitEnumerator */ PR_IMPLEMENT(PRRecvWait*) PR_EnumerateWaitGroup( PRMWaitEnumerator *enumerator, const PRRecvWait *previous) { PRRecvWait *result = NULL; /* entry point sanity checking */ PR_ASSERT(NULL != enumerator); PR_ASSERT(_PR_ENUM_SEALED == enumerator->seal); if ((NULL == enumerator) || (_PR_ENUM_SEALED != enumerator->seal)) goto bad_argument; /* beginning of enumeration */ if (NULL == previous) { if (NULL == enumerator->group) { enumerator->group = mw_state->group; if (NULL == enumerator->group) { PR_SetError(PR_GROUP_EMPTY_ERROR, 0); return NULL; } } enumerator->waiter = &enumerator->group->waiter->recv_wait; enumerator->p_timestamp = enumerator->group->p_timestamp; enumerator->thread = PR_GetCurrentThread(); enumerator->index = 0; } /* continuing an enumeration */ else { PRThread *me = PR_GetCurrentThread(); PR_ASSERT(me == enumerator->thread); if (me != enumerator->thread) goto bad_argument; /* need to restart the enumeration */ if (enumerator->p_timestamp != enumerator->group->p_timestamp) return PR_EnumerateWaitGroup(enumerator, NULL); } /* actually progress the enumeration */ #if defined(WINNT) _PR_MD_LOCK(&enumerator->group->mdlock); #else PR_Lock(enumerator->group->ml); #endif while (enumerator->index++ < enumerator->group->waiter->length) { if (NULL != (result = *(enumerator->waiter)++)) break; } #if defined(WINNT) _PR_MD_UNLOCK(&enumerator->group->mdlock); #else PR_Unlock(enumerator->group->ml); #endif return result; /* what we live for */ bad_argument: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; /* probably ambiguous */ } /* PR_EnumerateWaitGroup */ /* prmwait.c */ nspr-4.11/nspr/pr/src/io/prpolevt.c0000644000000000000000000001427512623070344015401 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ********************************************************************* * * Pollable events * * Pollable events are implemented using layered I/O. The only * I/O methods that are implemented for pollable events are poll * and close. No other methods can be invoked on a pollable * event. * * A pipe or socket pair is created and the pollable event layer * is pushed onto the read end. A pointer to the write end is * saved in the PRFilePrivate structure of the pollable event. * ********************************************************************* */ #include "prinit.h" #include "prio.h" #include "prmem.h" #include "prerror.h" #include "prlog.h" /* * These internal functions are declared in primpl.h, * but we can't include primpl.h because the definition * of struct PRFilePrivate in this file (for the pollable * event layer) will conflict with the definition of * struct PRFilePrivate in primpl.h (for the NSPR layer). */ extern PRIntn _PR_InvalidInt(void); extern PRInt64 _PR_InvalidInt64(void); extern PRStatus _PR_InvalidStatus(void); extern PRFileDesc *_PR_InvalidDesc(void); /* * PRFilePrivate structure for the NSPR pollable events layer */ struct PRFilePrivate { PRFileDesc *writeEnd; /* the write end of the pipe/socketpair */ }; static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd); static PRInt16 PR_CALLBACK _pr_PolEvtPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags); static PRIOMethods _pr_polevt_methods = { PR_DESC_LAYERED, _pr_PolEvtClose, (PRReadFN)_PR_InvalidInt, (PRWriteFN)_PR_InvalidInt, (PRAvailableFN)_PR_InvalidInt, (PRAvailable64FN)_PR_InvalidInt64, (PRFsyncFN)_PR_InvalidStatus, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, _pr_PolEvtPoll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRDescIdentity _pr_polevt_id; static PRCallOnceType _pr_polevt_once_control; static PRStatus PR_CALLBACK _pr_PolEvtInit(void); static PRInt16 PR_CALLBACK _pr_PolEvtPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { return (fd->lower->methods->poll)(fd->lower, in_flags, out_flags); } static PRStatus PR_CALLBACK _pr_PolEvtInit(void) { _pr_polevt_id = PR_GetUniqueIdentity("NSPR pollable events"); if (PR_INVALID_IO_LAYER == _pr_polevt_id) { return PR_FAILURE; } return PR_SUCCESS; } #if !defined(XP_UNIX) #define USE_TCP_SOCKETPAIR #endif PR_IMPLEMENT(PRFileDesc *) PR_NewPollableEvent(void) { PRFileDesc *event; PRFileDesc *fd[2]; /* fd[0] is the read end; fd[1] is the write end */ #ifdef USE_TCP_SOCKETPAIR PRSocketOptionData socket_opt; PRStatus rv; #endif fd[0] = fd[1] = NULL; if (PR_CallOnce(&_pr_polevt_once_control, _pr_PolEvtInit) == PR_FAILURE) { return NULL; } event = PR_CreateIOLayerStub(_pr_polevt_id, &_pr_polevt_methods); if (NULL == event) { goto errorExit; } event->secret = PR_NEW(PRFilePrivate); if (event->secret == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } #ifndef USE_TCP_SOCKETPAIR if (PR_CreatePipe(&fd[0], &fd[1]) == PR_FAILURE) { fd[0] = fd[1] = NULL; goto errorExit; } #else if (PR_NewTCPSocketPair(fd) == PR_FAILURE) { fd[0] = fd[1] = NULL; goto errorExit; } /* * set the TCP_NODELAY option to reduce notification latency */ socket_opt.option = PR_SockOpt_NoDelay; socket_opt.value.no_delay = PR_TRUE; rv = PR_SetSocketOption(fd[1], &socket_opt); PR_ASSERT(PR_SUCCESS == rv); #endif event->secret->writeEnd = fd[1]; if (PR_PushIOLayer(fd[0], PR_TOP_IO_LAYER, event) == PR_FAILURE) { goto errorExit; } return fd[0]; errorExit: if (fd[0]) { PR_Close(fd[0]); PR_Close(fd[1]); } if (event) { PR_DELETE(event->secret); event->dtor(event); } return NULL; } static PRStatus PR_CALLBACK _pr_PolEvtClose(PRFileDesc *fd) { PRFileDesc *event; event = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); PR_ASSERT(NULL == event->higher && NULL == event->lower); PR_Close(fd); PR_Close(event->secret->writeEnd); PR_DELETE(event->secret); event->dtor(event); return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_DestroyPollableEvent(PRFileDesc *event) { return PR_Close(event); } static const char magicChar = '\x38'; PR_IMPLEMENT(PRStatus) PR_SetPollableEvent(PRFileDesc *event) { if (PR_Write(event->secret->writeEnd, &magicChar, 1) != 1) { return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_WaitForPollableEvent(PRFileDesc *event) { char buf[1024]; PRInt32 nBytes; #ifdef DEBUG PRIntn i; #endif nBytes = PR_Read(event->lower, buf, sizeof(buf)); if (nBytes == -1) { return PR_FAILURE; } #ifdef DEBUG /* * Make sure people do not write to the pollable event fd * directly. */ for (i = 0; i < nBytes; i++) { PR_ASSERT(buf[i] == magicChar); } #endif return PR_SUCCESS; } nspr-4.11/nspr/pr/src/io/prprf.c0000644000000000000000000006215312623070344014655 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Portable safe sprintf code. ** ** Author: Kipp E.B. Hickman */ #include #include #include #include #include "primpl.h" #include "prprf.h" #include "prlong.h" #include "prlog.h" #include "prmem.h" #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif /* ** WARNING: This code may *NOT* call PR_LOG (because PR_LOG calls it) */ /* ** XXX This needs to be internationalized! */ typedef struct SprintfStateStr SprintfState; struct SprintfStateStr { int (*stuff)(SprintfState *ss, const char *sp, PRUint32 len); char *base; char *cur; PRUint32 maxlen; int (*func)(void *arg, const char *sp, PRUint32 len); void *arg; }; /* ** Numbered Argument */ struct NumArg { int type; /* type of the numbered argument */ union { /* the numbered argument */ int i; unsigned int ui; PRInt32 i32; PRUint32 ui32; PRInt64 ll; PRUint64 ull; double d; const char *s; int *ip; #ifdef WIN32 const WCHAR *ws; #endif } u; }; #define NAS_DEFAULT_NUM 20 /* default number of NumberedArgument array */ /* ** For numeric types, the signed versions must have even values, ** and their corresponding unsigned versions must have the subsequent ** odd value. */ #define TYPE_INT16 0 #define TYPE_UINT16 1 #define TYPE_INTN 2 #define TYPE_UINTN 3 #define TYPE_INT32 4 #define TYPE_UINT32 5 #define TYPE_INT64 6 #define TYPE_UINT64 7 #define TYPE_STRING 8 #define TYPE_DOUBLE 9 #define TYPE_INTSTR 10 #ifdef WIN32 #define TYPE_WSTRING 11 #endif #define TYPE_UNKNOWN 20 #define FLAG_LEFT 0x1 #define FLAG_SIGNED 0x2 #define FLAG_SPACED 0x4 #define FLAG_ZEROS 0x8 #define FLAG_NEG 0x10 /* ** Fill into the buffer using the data in src */ static int fill2(SprintfState *ss, const char *src, int srclen, int width, int flags) { char space = ' '; int rv; width -= srclen; if ((width > 0) && ((flags & FLAG_LEFT) == 0)) { /* Right adjusting */ if (flags & FLAG_ZEROS) { space = '0'; } while (--width >= 0) { rv = (*ss->stuff)(ss, &space, 1); if (rv < 0) { return rv; } } } /* Copy out the source data */ rv = (*ss->stuff)(ss, src, srclen); if (rv < 0) { return rv; } if ((width > 0) && ((flags & FLAG_LEFT) != 0)) { /* Left adjusting */ while (--width >= 0) { rv = (*ss->stuff)(ss, &space, 1); if (rv < 0) { return rv; } } } return 0; } /* ** Fill a number. The order is: optional-sign zero-filling conversion-digits */ static int fill_n(SprintfState *ss, const char *src, int srclen, int width, int prec, int type, int flags) { int zerowidth = 0; int precwidth = 0; int signwidth = 0; int leftspaces = 0; int rightspaces = 0; int cvtwidth; int rv; char sign; if ((type & 1) == 0) { if (flags & FLAG_NEG) { sign = '-'; signwidth = 1; } else if (flags & FLAG_SIGNED) { sign = '+'; signwidth = 1; } else if (flags & FLAG_SPACED) { sign = ' '; signwidth = 1; } } cvtwidth = signwidth + srclen; if (prec > 0) { if (prec > srclen) { precwidth = prec - srclen; /* Need zero filling */ cvtwidth += precwidth; } } if ((flags & FLAG_ZEROS) && (prec < 0)) { if (width > cvtwidth) { zerowidth = width - cvtwidth; /* Zero filling */ cvtwidth += zerowidth; } } if (flags & FLAG_LEFT) { if (width > cvtwidth) { /* Space filling on the right (i.e. left adjusting) */ rightspaces = width - cvtwidth; } } else { if (width > cvtwidth) { /* Space filling on the left (i.e. right adjusting) */ leftspaces = width - cvtwidth; } } while (--leftspaces >= 0) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { return rv; } } if (signwidth) { rv = (*ss->stuff)(ss, &sign, 1); if (rv < 0) { return rv; } } while (--precwidth >= 0) { rv = (*ss->stuff)(ss, "0", 1); if (rv < 0) { return rv; } } while (--zerowidth >= 0) { rv = (*ss->stuff)(ss, "0", 1); if (rv < 0) { return rv; } } rv = (*ss->stuff)(ss, src, srclen); if (rv < 0) { return rv; } while (--rightspaces >= 0) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { return rv; } } return 0; } /* ** Convert a long into its printable form */ static int cvt_l(SprintfState *ss, long num, int width, int prec, int radix, int type, int flags, const char *hexp) { char cvtbuf[100]; char *cvt; int digits; /* according to the man page this needs to happen */ if ((prec == 0) && (num == 0)) { return 0; } /* ** Converting decimal is a little tricky. In the unsigned case we ** need to stop when we hit 10 digits. In the signed case, we can ** stop when the number is zero. */ cvt = cvtbuf + sizeof(cvtbuf); digits = 0; while (num) { int digit = (((unsigned long)num) % radix) & 0xF; *--cvt = hexp[digit]; digits++; num = (long)(((unsigned long)num) / radix); } if (digits == 0) { *--cvt = '0'; digits++; } /* ** Now that we have the number converted without its sign, deal with ** the sign and zero padding. */ return fill_n(ss, cvt, digits, width, prec, type, flags); } /* ** Convert a 64-bit integer into its printable form */ static int cvt_ll(SprintfState *ss, PRInt64 num, int width, int prec, int radix, int type, int flags, const char *hexp) { char cvtbuf[100]; char *cvt; int digits; PRInt64 rad; /* according to the man page this needs to happen */ if ((prec == 0) && (LL_IS_ZERO(num))) { return 0; } /* ** Converting decimal is a little tricky. In the unsigned case we ** need to stop when we hit 10 digits. In the signed case, we can ** stop when the number is zero. */ LL_I2L(rad, radix); cvt = cvtbuf + sizeof(cvtbuf); digits = 0; while (!LL_IS_ZERO(num)) { PRInt32 digit; PRInt64 quot, rem; LL_UDIVMOD(", &rem, num, rad); LL_L2I(digit, rem); *--cvt = hexp[digit & 0xf]; digits++; num = quot; } if (digits == 0) { *--cvt = '0'; digits++; } /* ** Now that we have the number converted without its sign, deal with ** the sign and zero padding. */ return fill_n(ss, cvt, digits, width, prec, type, flags); } /* ** Convert a double precision floating point number into its printable ** form. ** ** XXX stop using snprintf to convert floating point */ static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1) { char fin[20]; char fout[300]; int amount = fmt1 - fmt0; if (amount <= 0 || amount >= sizeof(fin)) { /* Totally bogus % command to snprintf. Just ignore it */ return 0; } memcpy(fin, fmt0, amount); fin[amount] = 0; /* Convert floating point using the native snprintf code */ #ifdef DEBUG { const char *p = fin; while (*p) { PR_ASSERT(*p != 'L'); p++; } } #endif memset(fout, 0, sizeof(fout)); snprintf(fout, sizeof(fout), fin, d); /* Explicitly null-terminate fout because on Windows snprintf doesn't * append a null-terminator if the buffer is too small. */ fout[sizeof(fout) - 1] = '\0'; return (*ss->stuff)(ss, fout, strlen(fout)); } /* ** Convert a string into its printable form. "width" is the output ** width. "prec" is the maximum number of characters of "s" to output, ** where -1 means until NUL. */ static int cvt_s(SprintfState *ss, const char *str, int width, int prec, int flags) { int slen; if (prec == 0) return 0; /* Limit string length by precision value */ if (!str) { str = "(null)"; } if (prec > 0) { /* this is: slen = strnlen(str, prec); */ register const char *s; for(s = str; prec && *s; s++, prec-- ) ; slen = s - str; } else { slen = strlen(str); } /* and away we go */ return fill2(ss, str, slen, width, flags); } /* ** BuildArgArray stands for Numbered Argument list Sprintf ** for example, ** fmt = "%4$i, %2$d, %3s, %1d"; ** the number must start from 1, and no gap among them */ static struct NumArg* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArg* nasArray ) { int number = 0, cn = 0, i; const char* p; char c; struct NumArg* nas; /* ** first pass: ** determine how many legal % I have got, then allocate space */ p = fmt; *rv = 0; i = 0; while( ( c = *p++ ) != 0 ){ if( c != '%' ) continue; if( ( c = *p++ ) == '%' ) /* skip %% case */ continue; while( c != 0 ){ if( c > '9' || c < '0' ){ if( c == '$' ){ /* numbered argument case */ if( i > 0 ){ *rv = -1; return NULL; } number++; } else{ /* non-numbered argument case */ if( number > 0 ){ *rv = -1; return NULL; } i = 1; } break; } c = *p++; } } if( number == 0 ){ return NULL; } if( number > NAS_DEFAULT_NUM ){ nas = (struct NumArg*)PR_MALLOC( number * sizeof( struct NumArg ) ); if( !nas ){ *rv = -1; return NULL; } } else { nas = nasArray; } for( i = 0; i < number; i++ ){ nas[i].type = TYPE_UNKNOWN; } /* ** second pass: ** set nas[].type */ p = fmt; while( ( c = *p++ ) != 0 ){ if( c != '%' ) continue; c = *p++; if( c == '%' ) continue; cn = 0; while( c && c != '$' ){ /* should imporve error check later */ cn = cn*10 + c - '0'; c = *p++; } if( !c || cn < 1 || cn > number ){ *rv = -1; break; } /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */ cn--; if( nas[cn].type != TYPE_UNKNOWN ) continue; c = *p++; /* width */ if (c == '*') { /* not supported feature, for the argument is not numbered */ *rv = -1; break; } while ((c >= '0') && (c <= '9')) { c = *p++; } /* precision */ if (c == '.') { c = *p++; if (c == '*') { /* not supported feature, for the argument is not numbered */ *rv = -1; break; } while ((c >= '0') && (c <= '9')) { c = *p++; } } /* size */ nas[cn].type = TYPE_INTN; if (c == 'h') { nas[cn].type = TYPE_INT16; c = *p++; } else if (c == 'L') { /* XXX not quite sure here */ nas[cn].type = TYPE_INT64; c = *p++; } else if (c == 'l') { nas[cn].type = TYPE_INT32; c = *p++; if (c == 'l') { nas[cn].type = TYPE_INT64; c = *p++; } } else if (c == 'z') { if (sizeof(size_t) == sizeof(PRInt32)) { nas[ cn ].type = TYPE_INT32; } else if (sizeof(size_t) == sizeof(PRInt64)) { nas[ cn ].type = TYPE_INT64; } else { nas[ cn ].type = TYPE_UNKNOWN; } c = *p++; } /* format */ switch (c) { case 'd': case 'c': case 'i': case 'o': case 'u': case 'x': case 'X': break; case 'e': case 'f': case 'g': nas[ cn ].type = TYPE_DOUBLE; break; case 'p': /* XXX should use cpp */ if (sizeof(void *) == sizeof(PRInt32)) { nas[ cn ].type = TYPE_UINT32; } else if (sizeof(void *) == sizeof(PRInt64)) { nas[ cn ].type = TYPE_UINT64; } else if (sizeof(void *) == sizeof(PRIntn)) { nas[ cn ].type = TYPE_UINTN; } else { nas[ cn ].type = TYPE_UNKNOWN; } break; case 'S': #ifdef WIN32 nas[ cn ].type = TYPE_WSTRING; break; #endif case 'C': case 'E': case 'G': /* XXX not supported I suppose */ PR_ASSERT(0); nas[ cn ].type = TYPE_UNKNOWN; break; case 's': nas[ cn ].type = TYPE_STRING; break; case 'n': nas[ cn ].type = TYPE_INTSTR; break; default: PR_ASSERT(0); nas[ cn ].type = TYPE_UNKNOWN; break; } /* get a legal para. */ if( nas[ cn ].type == TYPE_UNKNOWN ){ *rv = -1; break; } } /* ** third pass ** fill the nas[cn].ap */ if( *rv < 0 ){ if( nas != nasArray ) PR_DELETE( nas ); return NULL; } cn = 0; while( cn < number ){ if( nas[cn].type == TYPE_UNKNOWN ){ cn++; continue; } switch( nas[cn].type ){ case TYPE_INT16: case TYPE_UINT16: case TYPE_INTN: nas[cn].u.i = va_arg( ap, int ); break; case TYPE_UINTN: nas[cn].u.ui = va_arg( ap, unsigned int ); break; case TYPE_INT32: nas[cn].u.i32 = va_arg( ap, PRInt32 ); break; case TYPE_UINT32: nas[cn].u.ui32 = va_arg( ap, PRUint32 ); break; case TYPE_INT64: nas[cn].u.ll = va_arg( ap, PRInt64 ); break; case TYPE_UINT64: nas[cn].u.ull = va_arg( ap, PRUint64 ); break; case TYPE_STRING: nas[cn].u.s = va_arg( ap, char* ); break; #ifdef WIN32 case TYPE_WSTRING: nas[cn].u.ws = va_arg( ap, WCHAR* ); break; #endif case TYPE_INTSTR: nas[cn].u.ip = va_arg( ap, int* ); break; case TYPE_DOUBLE: nas[cn].u.d = va_arg( ap, double ); break; default: if( nas != nasArray ) PR_DELETE( nas ); *rv = -1; return NULL; } cn++; } return nas; } /* ** The workhorse sprintf code. */ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap) { char c; int flags, width, prec, radix, type; union { char ch; int i; long l; PRInt64 ll; double d; const char *s; int *ip; #ifdef WIN32 const WCHAR *ws; #endif } u; const char *fmt0; static char *hex = "0123456789abcdef"; static char *HEX = "0123456789ABCDEF"; char *hexp; int rv, i; struct NumArg* nas = NULL; struct NumArg* nap; struct NumArg nasArray[ NAS_DEFAULT_NUM ]; char pattern[20]; const char* dolPt = NULL; /* in "%4$.2f", dolPt will point to . */ #ifdef WIN32 char *pBuf = NULL; #endif /* ** build an argument array, IF the fmt is numbered argument ** list style, to contain the Numbered Argument list pointers */ nas = BuildArgArray( fmt, ap, &rv, nasArray ); if( rv < 0 ){ /* the fmt contains error Numbered Argument format, jliu@netscape.com */ PR_ASSERT(0); return rv; } while ((c = *fmt++) != 0) { if (c != '%') { rv = (*ss->stuff)(ss, fmt - 1, 1); if (rv < 0) { return rv; } continue; } fmt0 = fmt - 1; /* ** Gobble up the % format string. Hopefully we have handled all ** of the strange cases! */ flags = 0; c = *fmt++; if (c == '%') { /* quoting a % with %% */ rv = (*ss->stuff)(ss, fmt - 1, 1); if (rv < 0) { return rv; } continue; } if( nas != NULL ){ /* the fmt contains the Numbered Arguments feature */ i = 0; while( c && c != '$' ){ /* should imporve error check later */ i = ( i * 10 ) + ( c - '0' ); c = *fmt++; } if( nas[i-1].type == TYPE_UNKNOWN ){ if( nas && ( nas != nasArray ) ) PR_DELETE( nas ); return -1; } nap = &nas[i-1]; dolPt = fmt; c = *fmt++; } /* * Examine optional flags. Note that we do not implement the * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is * somewhat ambiguous and not ideal, which is perhaps why * the various sprintf() implementations are inconsistent * on this feature. */ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) { if (c == '-') flags |= FLAG_LEFT; if (c == '+') flags |= FLAG_SIGNED; if (c == ' ') flags |= FLAG_SPACED; if (c == '0') flags |= FLAG_ZEROS; c = *fmt++; } if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED; if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS; /* width */ if (c == '*') { c = *fmt++; width = va_arg(ap, int); } else { width = 0; while ((c >= '0') && (c <= '9')) { width = (width * 10) + (c - '0'); c = *fmt++; } } /* precision */ prec = -1; if (c == '.') { c = *fmt++; if (c == '*') { c = *fmt++; prec = va_arg(ap, int); } else { prec = 0; while ((c >= '0') && (c <= '9')) { prec = (prec * 10) + (c - '0'); c = *fmt++; } } } /* size */ type = TYPE_INTN; if (c == 'h') { type = TYPE_INT16; c = *fmt++; } else if (c == 'L') { /* XXX not quite sure here */ type = TYPE_INT64; c = *fmt++; } else if (c == 'l') { type = TYPE_INT32; c = *fmt++; if (c == 'l') { type = TYPE_INT64; c = *fmt++; } } else if (c == 'z') { if (sizeof(size_t) == sizeof(PRInt32)) { type = TYPE_INT32; } else if (sizeof(size_t) == sizeof(PRInt64)) { type = TYPE_INT64; } c = *fmt++; } /* format */ hexp = hex; switch (c) { case 'd': case 'i': /* decimal/integer */ radix = 10; goto fetch_and_convert; case 'o': /* octal */ radix = 8; type |= 1; goto fetch_and_convert; case 'u': /* unsigned decimal */ radix = 10; type |= 1; goto fetch_and_convert; case 'x': /* unsigned hex */ radix = 16; type |= 1; goto fetch_and_convert; case 'X': /* unsigned HEX */ radix = 16; hexp = HEX; type |= 1; goto fetch_and_convert; fetch_and_convert: switch (type) { case TYPE_INT16: u.l = nas ? nap->u.i : va_arg(ap, int); if (u.l < 0) { u.l = -u.l; flags |= FLAG_NEG; } goto do_long; case TYPE_UINT16: u.l = (nas ? nap->u.i : va_arg(ap, int)) & 0xffff; goto do_long; case TYPE_INTN: u.l = nas ? nap->u.i : va_arg(ap, int); if (u.l < 0) { u.l = -u.l; flags |= FLAG_NEG; } goto do_long; case TYPE_UINTN: u.l = (long)(nas ? nap->u.ui : va_arg(ap, unsigned int)); goto do_long; case TYPE_INT32: u.l = nas ? nap->u.i32 : va_arg(ap, PRInt32); if (u.l < 0) { u.l = -u.l; flags |= FLAG_NEG; } goto do_long; case TYPE_UINT32: u.l = (long)(nas ? nap->u.ui32 : va_arg(ap, PRUint32)); do_long: rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp); if (rv < 0) { return rv; } break; case TYPE_INT64: u.ll = nas ? nap->u.ll : va_arg(ap, PRInt64); if (!LL_GE_ZERO(u.ll)) { LL_NEG(u.ll, u.ll); flags |= FLAG_NEG; } goto do_longlong; case TYPE_UINT64: u.ll = nas ? nap->u.ull : va_arg(ap, PRUint64); do_longlong: rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp); if (rv < 0) { return rv; } break; } break; case 'e': case 'E': case 'f': case 'g': u.d = nas ? nap->u.d : va_arg(ap, double); if( nas != NULL ){ i = fmt - dolPt; if( i < sizeof( pattern ) ){ pattern[0] = '%'; memcpy( &pattern[1], dolPt, i ); rv = cvt_f(ss, u.d, pattern, &pattern[i+1] ); } } else rv = cvt_f(ss, u.d, fmt0, fmt); if (rv < 0) { return rv; } break; case 'c': u.ch = nas ? nap->u.i : va_arg(ap, int); if ((flags & FLAG_LEFT) == 0) { while (width-- > 1) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { return rv; } } } rv = (*ss->stuff)(ss, &u.ch, 1); if (rv < 0) { return rv; } if (flags & FLAG_LEFT) { while (width-- > 1) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { return rv; } } } break; case 'p': if (sizeof(void *) == sizeof(PRInt32)) { type = TYPE_UINT32; } else if (sizeof(void *) == sizeof(PRInt64)) { type = TYPE_UINT64; } else if (sizeof(void *) == sizeof(int)) { type = TYPE_UINTN; } else { PR_ASSERT(0); break; } radix = 16; goto fetch_and_convert; #ifndef WIN32 case 'S': /* XXX not supported I suppose */ PR_ASSERT(0); break; #endif #if 0 case 'C': case 'E': case 'G': /* XXX not supported I suppose */ PR_ASSERT(0); break; #endif #ifdef WIN32 case 'S': u.ws = nas ? nap->u.ws : va_arg(ap, const WCHAR*); /* Get the required size in rv */ rv = WideCharToMultiByte(CP_ACP, 0, u.ws, -1, NULL, 0, NULL, NULL); if (rv == 0) rv = 1; pBuf = PR_MALLOC(rv); WideCharToMultiByte(CP_ACP, 0, u.ws, -1, pBuf, (int)rv, NULL, NULL); pBuf[rv-1] = '\0'; rv = cvt_s(ss, pBuf, width, prec, flags); /* We don't need the allocated buffer anymore */ PR_Free(pBuf); if (rv < 0) { return rv; } break; #endif case 's': u.s = nas ? nap->u.s : va_arg(ap, const char*); rv = cvt_s(ss, u.s, width, prec, flags); if (rv < 0) { return rv; } break; case 'n': u.ip = nas ? nap->u.ip : va_arg(ap, int*); if (u.ip) { *u.ip = ss->cur - ss->base; } break; default: /* Not a % token after all... skip it */ #if 0 PR_ASSERT(0); #endif rv = (*ss->stuff)(ss, "%", 1); if (rv < 0) { return rv; } rv = (*ss->stuff)(ss, fmt - 1, 1); if (rv < 0) { return rv; } } } /* Stuff trailing NUL */ rv = (*ss->stuff)(ss, "\0", 1); if( nas && ( nas != nasArray ) ){ PR_DELETE( nas ); } return rv; } /************************************************************************/ static int FuncStuff(SprintfState *ss, const char *sp, PRUint32 len) { int rv; rv = (*ss->func)(ss->arg, sp, len); if (rv < 0) { return rv; } ss->maxlen += len; return 0; } PR_IMPLEMENT(PRUint32) PR_sxprintf(PRStuffFunc func, void *arg, const char *fmt, ...) { va_list ap; PRUint32 rv; va_start(ap, fmt); rv = PR_vsxprintf(func, arg, fmt, ap); va_end(ap); return rv; } PR_IMPLEMENT(PRUint32) PR_vsxprintf(PRStuffFunc func, void *arg, const char *fmt, va_list ap) { SprintfState ss; int rv; ss.stuff = FuncStuff; ss.func = func; ss.arg = arg; ss.maxlen = 0; rv = dosprintf(&ss, fmt, ap); return (rv < 0) ? (PRUint32)-1 : ss.maxlen; } /* ** Stuff routine that automatically grows the malloc'd output buffer ** before it overflows. */ static int GrowStuff(SprintfState *ss, const char *sp, PRUint32 len) { ptrdiff_t off; char *newbase; PRUint32 newlen; off = ss->cur - ss->base; if (off + len >= ss->maxlen) { /* Grow the buffer */ newlen = ss->maxlen + ((len > 32) ? len : 32); if (ss->base) { newbase = (char*) PR_REALLOC(ss->base, newlen); } else { newbase = (char*) PR_MALLOC(newlen); } if (!newbase) { /* Ran out of memory */ return -1; } ss->base = newbase; ss->maxlen = newlen; ss->cur = ss->base + off; } /* Copy data */ while (len) { --len; *ss->cur++ = *sp++; } PR_ASSERT((PRUint32)(ss->cur - ss->base) <= ss->maxlen); return 0; } /* ** sprintf into a malloc'd buffer */ PR_IMPLEMENT(char *) PR_smprintf(const char *fmt, ...) { va_list ap; char *rv; va_start(ap, fmt); rv = PR_vsmprintf(fmt, ap); va_end(ap); return rv; } /* ** Free memory allocated, for the caller, by PR_smprintf */ PR_IMPLEMENT(void) PR_smprintf_free(char *mem) { PR_DELETE(mem); } PR_IMPLEMENT(char *) PR_vsmprintf(const char *fmt, va_list ap) { SprintfState ss; int rv; ss.stuff = GrowStuff; ss.base = 0; ss.cur = 0; ss.maxlen = 0; rv = dosprintf(&ss, fmt, ap); if (rv < 0) { if (ss.base) { PR_DELETE(ss.base); } return 0; } return ss.base; } /* ** Stuff routine that discards overflow data */ static int LimitStuff(SprintfState *ss, const char *sp, PRUint32 len) { PRUint32 limit = ss->maxlen - (ss->cur - ss->base); if (len > limit) { len = limit; } while (len) { --len; *ss->cur++ = *sp++; } return 0; } /* ** sprintf into a fixed size buffer. Make sure there is a NUL at the end ** when finished. */ PR_IMPLEMENT(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...) { va_list ap; PRUint32 rv; va_start(ap, fmt); rv = PR_vsnprintf(out, outlen, fmt, ap); va_end(ap); return rv; } PR_IMPLEMENT(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen,const char *fmt, va_list ap) { SprintfState ss; PRUint32 n; PR_ASSERT((PRInt32)outlen > 0); if ((PRInt32)outlen <= 0) { return 0; } ss.stuff = LimitStuff; ss.base = out; ss.cur = out; ss.maxlen = outlen; (void) dosprintf(&ss, fmt, ap); /* If we added chars, and we didn't append a null, do it now. */ if( (ss.cur != ss.base) && (*(ss.cur - 1) != '\0') ) *(ss.cur - 1) = '\0'; n = ss.cur - ss.base; return n ? n - 1 : n; } PR_IMPLEMENT(char *) PR_sprintf_append(char *last, const char *fmt, ...) { va_list ap; char *rv; va_start(ap, fmt); rv = PR_vsprintf_append(last, fmt, ap); va_end(ap); return rv; } PR_IMPLEMENT(char *) PR_vsprintf_append(char *last, const char *fmt, va_list ap) { SprintfState ss; int rv; ss.stuff = GrowStuff; if (last) { int lastlen = strlen(last); ss.base = last; ss.cur = last + lastlen; ss.maxlen = lastlen; } else { ss.base = 0; ss.cur = 0; ss.maxlen = 0; } rv = dosprintf(&ss, fmt, ap); if (rv < 0) { if (ss.base) { PR_DELETE(ss.base); } return 0; } return ss.base; } nspr-4.11/nspr/pr/src/io/prscanf.c0000644000000000000000000004274412623070344015164 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Scan functions for NSPR types * * Author: Wan-Teh Chang * * Acknowledgment: The implementation is inspired by the source code * in P.J. Plauger's "The Standard C Library," Prentice-Hall, 1992. */ #include #include #include #include #include "prprf.h" #include "prdtoa.h" #include "prlog.h" #include "prerror.h" /* * A function that reads a character from 'stream'. * Returns the character read, or EOF if end of stream is reached. */ typedef int (*_PRGetCharFN)(void *stream); /* * A function that pushes the character 'ch' back to 'stream'. */ typedef void (*_PRUngetCharFN)(void *stream, int ch); /* * The size specifier for the integer and floating point number * conversions in format control strings. */ typedef enum { _PR_size_none, /* No size specifier is given */ _PR_size_h, /* The 'h' specifier, suggesting "short" */ _PR_size_l, /* The 'l' specifier, suggesting "long" */ _PR_size_L, /* The 'L' specifier, meaning a 'long double' */ _PR_size_ll /* The 'll' specifier, suggesting "long long" */ } _PRSizeSpec; /* * The collection of data that is passed between the scan function * and its subordinate functions. The fields of this structure * serve as the input or output arguments for these functions. */ typedef struct { _PRGetCharFN get; /* get a character from input stream */ _PRUngetCharFN unget; /* unget (push back) a character */ void *stream; /* argument for get and unget */ va_list ap; /* the variable argument list */ int nChar; /* number of characters read from 'stream' */ PRBool assign; /* assign, or suppress assignment? */ int width; /* field width */ _PRSizeSpec sizeSpec; /* 'h', 'l', 'L', or 'll' */ PRBool converted; /* is the value actually converted? */ } ScanfState; #define GET(state) ((state)->nChar++, (state)->get((state)->stream)) #define UNGET(state, ch) \ ((state)->nChar--, (state)->unget((state)->stream, ch)) /* * The following two macros, GET_IF_WITHIN_WIDTH and WITHIN_WIDTH, * are always used together. * * GET_IF_WITHIN_WIDTH calls the GET macro and assigns its return * value to 'ch' only if we have not exceeded the field width of * 'state'. Therefore, after GET_IF_WITHIN_WIDTH, the value of * 'ch' is valid only if the macro WITHIN_WIDTH evaluates to true. */ #define GET_IF_WITHIN_WIDTH(state, ch) \ if (--(state)->width >= 0) { \ (ch) = GET(state); \ } #define WITHIN_WIDTH(state) ((state)->width >= 0) /* * _pr_strtoull: * Convert a string to an unsigned 64-bit integer. The string * 'str' is assumed to be a representation of the integer in * base 'base'. * * Warning: * - Only handle base 8, 10, and 16. * - No overflow checking. */ static PRUint64 _pr_strtoull(const char *str, char **endptr, int base) { static const int BASE_MAX = 16; static const char digits[] = "0123456789abcdef"; char *digitPtr; PRUint64 x; /* return value */ PRInt64 base64; const char *cPtr; PRBool negative; const char *digitStart; PR_ASSERT(base == 0 || base == 8 || base == 10 || base == 16); if (base < 0 || base == 1 || base > BASE_MAX) { if (endptr) { *endptr = (char *) str; return LL_ZERO; } } cPtr = str; while (isspace(*cPtr)) { ++cPtr; } negative = PR_FALSE; if (*cPtr == '-') { negative = PR_TRUE; cPtr++; } else if (*cPtr == '+') { cPtr++; } if (base == 16) { if (*cPtr == '0' && (cPtr[1] == 'x' || cPtr[1] == 'X')) { cPtr += 2; } } else if (base == 0) { if (*cPtr != '0') { base = 10; } else if (cPtr[1] == 'x' || cPtr[1] == 'X') { base = 16; cPtr += 2; } else { base = 8; } } PR_ASSERT(base != 0); LL_I2L(base64, base); digitStart = cPtr; /* Skip leading zeros */ while (*cPtr == '0') { cPtr++; } LL_I2L(x, 0); while ((digitPtr = (char*)memchr(digits, tolower(*cPtr), base)) != NULL) { PRUint64 d; LL_I2L(d, (digitPtr - digits)); LL_MUL(x, x, base64); LL_ADD(x, x, d); cPtr++; } if (cPtr == digitStart) { if (endptr) { *endptr = (char *) str; } return LL_ZERO; } if (negative) { #ifdef HAVE_LONG_LONG /* The cast to a signed type is to avoid a compiler warning */ x = -(PRInt64)x; #else LL_NEG(x, x); #endif } if (endptr) { *endptr = (char *) cPtr; } return x; } /* * The maximum field width (in number of characters) that is enough * (may be more than necessary) to represent a 64-bit integer or * floating point number. */ #define FMAX 31 #define DECIMAL_POINT '.' static PRStatus GetInt(ScanfState *state, int code) { char buf[FMAX + 1], *p; int ch; static const char digits[] = "0123456789abcdefABCDEF"; PRBool seenDigit = PR_FALSE; int base; int dlen; switch (code) { case 'd': case 'u': base = 10; break; case 'i': base = 0; break; case 'x': case 'X': case 'p': base = 16; break; case 'o': base = 8; break; default: return PR_FAILURE; } if (state->width == 0 || state->width > FMAX) { state->width = FMAX; } p = buf; GET_IF_WITHIN_WIDTH(state, ch); if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } if (WITHIN_WIDTH(state) && ch == '0') { seenDigit = PR_TRUE; *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); if (WITHIN_WIDTH(state) && (ch == 'x' || ch == 'X') && (base == 0 || base == 16)) { base = 16; *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } else if (base == 0) { base = 8; } } if (base == 0 || base == 10) { dlen = 10; } else if (base == 8) { dlen = 8; } else { PR_ASSERT(base == 16); dlen = 16 + 6; /* 16 digits, plus 6 in uppercase */ } while (WITHIN_WIDTH(state) && memchr(digits, ch, dlen)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); seenDigit = PR_TRUE; } if (WITHIN_WIDTH(state)) { UNGET(state, ch); } if (!seenDigit) { return PR_FAILURE; } *p = '\0'; if (state->assign) { if (code == 'd' || code == 'i') { if (state->sizeSpec == _PR_size_ll) { PRInt64 llval = _pr_strtoull(buf, NULL, base); *va_arg(state->ap, PRInt64 *) = llval; } else { long lval = strtol(buf, NULL, base); if (state->sizeSpec == _PR_size_none) { *va_arg(state->ap, PRIntn *) = lval; } else if (state->sizeSpec == _PR_size_h) { *va_arg(state->ap, PRInt16 *) = (PRInt16)lval; } else if (state->sizeSpec == _PR_size_l) { *va_arg(state->ap, PRInt32 *) = lval; } else { return PR_FAILURE; } } } else { if (state->sizeSpec == _PR_size_ll) { PRUint64 llval = _pr_strtoull(buf, NULL, base); *va_arg(state->ap, PRUint64 *) = llval; } else { unsigned long lval = strtoul(buf, NULL, base); if (state->sizeSpec == _PR_size_none) { *va_arg(state->ap, PRUintn *) = lval; } else if (state->sizeSpec == _PR_size_h) { *va_arg(state->ap, PRUint16 *) = (PRUint16)lval; } else if (state->sizeSpec == _PR_size_l) { *va_arg(state->ap, PRUint32 *) = lval; } else { return PR_FAILURE; } } } state->converted = PR_TRUE; } return PR_SUCCESS; } static PRStatus GetFloat(ScanfState *state) { char buf[FMAX + 1], *p; int ch; PRBool seenDigit = PR_FALSE; if (state->width == 0 || state->width > FMAX) { state->width = FMAX; } p = buf; GET_IF_WITHIN_WIDTH(state, ch); if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } while (WITHIN_WIDTH(state) && isdigit(ch)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); seenDigit = PR_TRUE; } if (WITHIN_WIDTH(state) && ch == DECIMAL_POINT) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); while (WITHIN_WIDTH(state) && isdigit(ch)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); seenDigit = PR_TRUE; } } /* * This is not robust. For example, "1.2e+" would confuse * the code below to read 'e' and '+', only to realize that * it should have stopped at "1.2". But we can't push back * more than one character, so there is nothing I can do. */ /* Parse exponent */ if (WITHIN_WIDTH(state) && (ch == 'e' || ch == 'E') && seenDigit) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); if (WITHIN_WIDTH(state) && (ch == '+' || ch == '-')) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } while (WITHIN_WIDTH(state) && isdigit(ch)) { *p++ = ch; GET_IF_WITHIN_WIDTH(state, ch); } } if (WITHIN_WIDTH(state)) { UNGET(state, ch); } if (!seenDigit) { return PR_FAILURE; } *p = '\0'; if (state->assign) { PRFloat64 dval = PR_strtod(buf, NULL); state->converted = PR_TRUE; if (state->sizeSpec == _PR_size_l) { *va_arg(state->ap, PRFloat64 *) = dval; } else if (state->sizeSpec == _PR_size_L) { #if defined(OSF1) || defined(IRIX) *va_arg(state->ap, double *) = dval; #else *va_arg(state->ap, long double *) = dval; #endif } else { *va_arg(state->ap, float *) = (float) dval; } } return PR_SUCCESS; } /* * Convert, and return the end of the conversion spec. * Return NULL on error. */ static const char * Convert(ScanfState *state, const char *fmt) { const char *cPtr; int ch; char *cArg = NULL; state->converted = PR_FALSE; cPtr = fmt; if (*cPtr != 'c' && *cPtr != 'n' && *cPtr != '[') { do { ch = GET(state); } while (isspace(ch)); UNGET(state, ch); } switch (*cPtr) { case 'c': if (state->assign) { cArg = va_arg(state->ap, char *); } if (state->width == 0) { state->width = 1; } for (; state->width > 0; state->width--) { ch = GET(state); if (ch == EOF) { return NULL; } else if (state->assign) { *cArg++ = ch; } } if (state->assign) { state->converted = PR_TRUE; } break; case 'p': case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (GetInt(state, *cPtr) == PR_FAILURE) { return NULL; } break; case 'e': case 'E': case 'f': case 'g': case 'G': if (GetFloat(state) == PR_FAILURE) { return NULL; } break; case 'n': /* do not consume any input */ if (state->assign) { switch (state->sizeSpec) { case _PR_size_none: *va_arg(state->ap, PRIntn *) = state->nChar; break; case _PR_size_h: *va_arg(state->ap, PRInt16 *) = state->nChar; break; case _PR_size_l: *va_arg(state->ap, PRInt32 *) = state->nChar; break; case _PR_size_ll: LL_I2L(*va_arg(state->ap, PRInt64 *), state->nChar); break; default: PR_ASSERT(0); } } break; case 's': if (state->width == 0) { state->width = INT_MAX; } if (state->assign) { cArg = va_arg(state->ap, char *); } for (; state->width > 0; state->width--) { ch = GET(state); if ((ch == EOF) || isspace(ch)) { UNGET(state, ch); break; } if (state->assign) { *cArg++ = ch; } } if (state->assign) { *cArg = '\0'; state->converted = PR_TRUE; } break; case '%': ch = GET(state); if (ch != '%') { UNGET(state, ch); return NULL; } break; case '[': { PRBool complement = PR_FALSE; const char *closeBracket; size_t n; if (*++cPtr == '^') { complement = PR_TRUE; cPtr++; } closeBracket = strchr(*cPtr == ']' ? cPtr + 1 : cPtr, ']'); if (closeBracket == NULL) { return NULL; } n = closeBracket - cPtr; if (state->width == 0) { state->width = INT_MAX; } if (state->assign) { cArg = va_arg(state->ap, char *); } for (; state->width > 0; state->width--) { ch = GET(state); if ((ch == EOF) || (!complement && !memchr(cPtr, ch, n)) || (complement && memchr(cPtr, ch, n))) { UNGET(state, ch); break; } if (state->assign) { *cArg++ = ch; } } if (state->assign) { *cArg = '\0'; state->converted = PR_TRUE; } cPtr = closeBracket; } break; default: return NULL; } return cPtr; } static PRInt32 DoScanf(ScanfState *state, const char *fmt) { PRInt32 nConverted = 0; const char *cPtr; int ch; state->nChar = 0; cPtr = fmt; while (1) { if (isspace(*cPtr)) { /* white space: skip */ do { cPtr++; } while (isspace(*cPtr)); do { ch = GET(state); } while (isspace(ch)); UNGET(state, ch); } else if (*cPtr == '%') { /* format spec: convert */ cPtr++; state->assign = PR_TRUE; if (*cPtr == '*') { cPtr++; state->assign = PR_FALSE; } for (state->width = 0; isdigit(*cPtr); cPtr++) { state->width = state->width * 10 + *cPtr - '0'; } state->sizeSpec = _PR_size_none; if (*cPtr == 'h') { cPtr++; state->sizeSpec = _PR_size_h; } else if (*cPtr == 'l') { cPtr++; if (*cPtr == 'l') { cPtr++; state->sizeSpec = _PR_size_ll; } else { state->sizeSpec = _PR_size_l; } } else if (*cPtr == 'L') { cPtr++; state->sizeSpec = _PR_size_L; } cPtr = Convert(state, cPtr); if (cPtr == NULL) { return (nConverted > 0 ? nConverted : EOF); } if (state->converted) { nConverted++; } cPtr++; } else { /* others: must match */ if (*cPtr == '\0') { return nConverted; } ch = GET(state); if (ch != *cPtr) { UNGET(state, ch); return nConverted; } cPtr++; } } } static int StringGetChar(void *stream) { char *cPtr = *((char **) stream); if (*cPtr == '\0') { return EOF; } else { *((char **) stream) = cPtr + 1; return (unsigned char) *cPtr; } } static void StringUngetChar(void *stream, int ch) { char *cPtr = *((char **) stream); if (ch != EOF) { *((char **) stream) = cPtr - 1; } } PR_IMPLEMENT(PRInt32) PR_sscanf(const char *buf, const char *fmt, ...) { PRInt32 rv; ScanfState state; state.get = &StringGetChar; state.unget = &StringUngetChar; state.stream = (void *) &buf; va_start(state.ap, fmt); rv = DoScanf(&state, fmt); va_end(state.ap); return rv; } nspr-4.11/nspr/pr/src/io/prsocket.c0000644000000000000000000013162112623070344015353 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /************************************************************************/ /* These two functions are only used in assertions. */ #if defined(DEBUG) PRBool IsValidNetAddr(const PRNetAddr *addr) { if ((addr != NULL) #if defined(XP_UNIX) || defined(XP_OS2) && (addr->raw.family != PR_AF_LOCAL) #endif && (addr->raw.family != PR_AF_INET6) && (addr->raw.family != PR_AF_INET)) { return PR_FALSE; } return PR_TRUE; } static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) { /* * The definition of the length of a Unix domain socket address * is not uniform, so we don't check it. */ if ((addr != NULL) #if defined(XP_UNIX) || defined(XP_OS2) && (addr->raw.family != AF_UNIX) #endif && (PR_NETADDR_SIZE(addr) != addr_len)) { #if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1 /* * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2 * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id * field and is 28 bytes. It is possible for socket functions * to return an addr_len greater than sizeof(struct sockaddr_in6). * We need to allow that. (Bugzilla bug #77264) */ if ((PR_AF_INET6 == addr->raw.family) && (sizeof(addr->ipv6) == addr_len)) { return PR_TRUE; } #endif /* * The accept(), getsockname(), etc. calls on some platforms * do not set the actual socket address length on return. * In this case, we verifiy addr_len is still the value we * passed in (i.e., sizeof(PRNetAddr)). */ #if defined(QNX) if (sizeof(PRNetAddr) == addr_len) { return PR_TRUE; } #endif return PR_FALSE; } return PR_TRUE; } #endif /* DEBUG */ static PRInt32 PR_CALLBACK SocketWritev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int w = 0; const PRIOVec *tmp_iov; #define LOCAL_MAXIOV 8 PRIOVec local_iov[LOCAL_MAXIOV]; PRIOVec *iov_copy = NULL; int tmp_out; int index, iov_cnt; int count=0, sz = 0; /* 'count' is the return value. */ if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* * Assume the first writev will succeed. Copy iov's only on * failure. */ tmp_iov = iov; for (index = 0; index < iov_size; index++) sz += iov[index].iov_len; iov_cnt = iov_size; while (sz > 0) { w = _PR_MD_WRITEV(fd, tmp_iov, iov_cnt, timeout); if (w < 0) { count = -1; break; } count += w; if (fd->secret->nonblocking) { break; } sz -= w; if (sz > 0) { /* find the next unwritten vector */ for ( index = 0, tmp_out = count; tmp_out >= iov[index].iov_len; tmp_out -= iov[index].iov_len, index++){;} /* nothing to execute */ if (tmp_iov == iov) { /* * The first writev failed so we * must copy iov's around. * Avoid calloc/free if there * are few enough iov's. */ if (iov_size - index <= LOCAL_MAXIOV) iov_copy = local_iov; else if ((iov_copy = (PRIOVec *) PR_CALLOC((iov_size - index) * sizeof *iov_copy)) == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } tmp_iov = iov_copy; } PR_ASSERT(tmp_iov == iov_copy); /* fill in the first partial read */ iov_copy[0].iov_base = &(((char *)iov[index].iov_base)[tmp_out]); iov_copy[0].iov_len = iov[index].iov_len - tmp_out; index++; /* copy the remaining vectors */ for (iov_cnt=1; indexsecret->af = AF_INET; #endif } else _PR_MD_CLOSE_SOCKET(osfd); return(fd); } PR_IMPLEMENT(PRFileDesc *) PR_ImportUDPSocket(PROsfd osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods()); if (fd != NULL) { _PR_MD_MAKE_NONBLOCK(fd); _PR_MD_INIT_FD_INHERITABLE(fd, PR_TRUE); } else _PR_MD_CLOSE_SOCKET(osfd); return(fd); } static const PRIOMethods* PR_GetSocketPollFdMethods(void); PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PROsfd osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = _PR_Getfd(); if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); else { fd->secret->md.osfd = osfd; fd->secret->inheritable = _PR_TRI_FALSE; fd->secret->state = _PR_FILEDESC_OPEN; fd->methods = PR_GetSocketPollFdMethods(); } return fd; } /* PR_CreateSocketPollFD */ PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd) { if (NULL == fd) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } fd->secret->state = _PR_FILEDESC_CLOSED; _PR_Putfd(fd); return PR_SUCCESS; } /* PR_DestroySocketPollFd */ static PRStatus PR_CALLBACK SocketConnect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 rv; /* Return value of _PR_MD_CONNECT */ const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return PR_FAILURE; } #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv)); if (rv == 0) return PR_SUCCESS; else return PR_FAILURE; } static PRStatus PR_CALLBACK SocketConnectContinue( PRFileDesc *fd, PRInt16 out_flags) { PROsfd osfd; int err; if (out_flags & PR_POLL_NVAL) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR)) == 0) { PR_ASSERT(out_flags == 0); PR_SetError(PR_IN_PROGRESS_ERROR, 0); return PR_FAILURE; } osfd = fd->secret->md.osfd; #if defined(XP_UNIX) err = _MD_unix_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; #elif defined(WIN32) || defined(WIN16) if (out_flags & PR_POLL_EXCEPT) { int len = sizeof(err); if (getsockopt(osfd, (int)SOL_SOCKET, SO_ERROR, (char *) &err, &len) == SOCKET_ERROR) { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return PR_FAILURE; } if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); } else { PR_SetError(PR_UNKNOWN_ERROR, 0); } return PR_FAILURE; } PR_ASSERT(out_flags & PR_POLL_WRITE); return PR_SUCCESS; #elif defined(XP_OS2) err = _MD_os2_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; #elif defined(XP_BEOS) #ifdef BONE_VERSION /* bug 122364 */ /* temporary workaround until getsockopt(SO_ERROR) works in BONE */ if (out_flags & PR_POLL_EXCEPT) { PR_SetError(PR_CONNECT_REFUSED_ERROR, 0); return PR_FAILURE; } PR_ASSERT(out_flags & PR_POLL_WRITE); return PR_SUCCESS; #else err = _MD_beos_get_nonblocking_connect_error(fd); if( err != 0 ) { _PR_MD_MAP_CONNECT_ERROR(err); return PR_FAILURE; } else return PR_SUCCESS; #endif /* BONE_VERSION */ #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; #endif } PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd) { /* Find the NSPR layer and invoke its connectcontinue method */ PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (NULL == bottom) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } return SocketConnectContinue(bottom, pd->out_flags); } static PRFileDesc* PR_CALLBACK SocketAccept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PROsfd osfd; PRFileDesc *fd2; PRUint32 al; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifdef WINNT PRNetAddr addrCopy; #endif if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return 0; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return 0; } #ifdef WINNT if (addr == NULL) { addr = &addrCopy; } #endif al = sizeof(PRNetAddr); osfd = _PR_MD_ACCEPT(fd, addr, &al, timeout); if (osfd == -1) return 0; fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); if (!fd2) { _PR_MD_CLOSE_SOCKET(osfd); return NULL; } fd2->secret->nonblocking = fd->secret->nonblocking; fd2->secret->inheritable = fd->secret->inheritable; #ifdef WINNT if (!fd2->secret->nonblocking && fd2->secret->inheritable != _PR_TRI_TRUE) { /* * The new socket has been associated with an I/O * completion port. There is no going back. */ fd2->secret->md.io_model_committed = PR_TRUE; } PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); #endif /* * On some platforms, the new socket created by accept() * inherits the nonblocking (or overlapped io) attribute * of the listening socket. As an optimization, these * platforms can skip the following _PR_MD_MAKE_NONBLOCK * call. */ #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT) _PR_MD_MAKE_NONBLOCK(fd2); #endif #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE); return fd2; } #ifdef WINNT PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PROsfd osfd; PRFileDesc *fd2; PRIntn al; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr addrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return 0; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return 0; } if (addr == NULL) { addr = &addrCopy; } al = PR_NETADDR_SIZE(addr); osfd = _PR_MD_FAST_ACCEPT(fd, addr, &al, timeout, PR_TRUE, NULL, NULL); if (osfd == -1) { return 0; } fd2 = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); if (!fd2) { _PR_MD_CLOSE_SOCKET(osfd); } else { fd2->secret->nonblocking = fd->secret->nonblocking; fd2->secret->md.io_model_committed = PR_TRUE; PR_ASSERT(al == PR_NETADDR_SIZE(addr)); fd2->secret->md.accepted_socket = PR_TRUE; memcpy(&fd2->secret->md.peer_addr, addr, al); #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF fd2->secret->af = fd->secret->af; #endif } return fd2; } #endif /* WINNT */ static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr) { PRInt32 result; const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); #ifdef XP_UNIX if (addr->raw.family == AF_UNIX) { /* Disallow relative pathnames */ if (addr->local.path[0] != '/') { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } } #endif /* XP_UNIX */ #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr)); if (result < 0) { return PR_FAILURE; } return PR_SUCCESS; } static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog) { PRInt32 result; result = _PR_MD_LISTEN(fd, backlog); if (result < 0) { return PR_FAILURE; } return PR_SUCCESS; } static PRStatus PR_CALLBACK SocketShutdown(PRFileDesc *fd, PRIntn how) { PRInt32 result; result = _PR_MD_SHUTDOWN(fd, how); if (result < 0) { return PR_FAILURE; } return PR_SUCCESS; } static PRInt32 PR_CALLBACK SocketRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if ((flags != 0) && (flags != PR_MSG_PEEK)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d flags=%d", fd, fd->secret->md.osfd, buf, amount, flags)); #ifdef _PR_HAVE_PEEK_BUFFER if (fd->secret->peekBytes != 0) { rv = (amount < fd->secret->peekBytes) ? amount : fd->secret->peekBytes; memcpy(buf, fd->secret->peekBuffer, rv); if (flags == 0) { /* consume the bytes in the peek buffer */ fd->secret->peekBytes -= rv; if (fd->secret->peekBytes != 0) { memmove(fd->secret->peekBuffer, fd->secret->peekBuffer + rv, fd->secret->peekBytes); } } return rv; } /* allocate peek buffer, if necessary */ if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) { PR_ASSERT(0 == fd->secret->peekBytes); /* impose a max size on the peek buffer */ if (amount > _PR_PEEK_BUFFER_MAX) { amount = _PR_PEEK_BUFFER_MAX; } if (fd->secret->peekBufSize < amount) { if (fd->secret->peekBuffer) { PR_Free(fd->secret->peekBuffer); } fd->secret->peekBufSize = amount; fd->secret->peekBuffer = PR_Malloc(amount); if (NULL == fd->secret->peekBuffer) { fd->secret->peekBufSize = 0; PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } } } #endif rv = _PR_MD_RECV(fd, buf, amount, flags, timeout); PR_LOG(_pr_io_lm, PR_LOG_MAX, ("recv -> %d, error = %d, os error = %d", rv, PR_GetError(), PR_GetOSError())); #ifdef _PR_HAVE_PEEK_BUFFER if ((PR_MSG_PEEK == flags) && _PR_FD_NEED_EMULATE_MSG_PEEK(fd)) { if (rv > 0) { memcpy(fd->secret->peekBuffer, buf, rv); fd->secret->peekBytes = rv; } } #endif return rv; } static PRInt32 PR_CALLBACK SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount) { return SocketRecv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); } static PRInt32 PR_CALLBACK SocketSend(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 temp, count; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } count = 0; while (amount > 0) { PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send: fd=%p osfd=%" PR_PRIdOSFD " buf=%p amount=%d", fd, fd->secret->md.osfd, buf, amount)); temp = _PR_MD_SEND(fd, buf, amount, flags, timeout); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } PR_LOG(_pr_io_lm, PR_LOG_MAX, ("send -> %d", count)); return count; } static PRInt32 PR_CALLBACK SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount) { return SocketSend(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); } static PRStatus PR_CALLBACK SocketClose(PRFileDesc *fd) { if (!fd || !fd->secret || (fd->secret->state != _PR_FILEDESC_OPEN && fd->secret->state != _PR_FILEDESC_CLOSED)) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if (fd->secret->state == _PR_FILEDESC_OPEN) { if (_PR_MD_CLOSE_SOCKET(fd->secret->md.osfd) < 0) { return PR_FAILURE; } fd->secret->state = _PR_FILEDESC_CLOSED; } #ifdef _PR_HAVE_PEEK_BUFFER if (fd->secret->peekBuffer) { PR_ASSERT(fd->secret->peekBufSize > 0); PR_DELETE(fd->secret->peekBuffer); fd->secret->peekBufSize = 0; fd->secret->peekBytes = 0; } #endif PR_FreeFileDesc(fd); return PR_SUCCESS; } static PRInt32 PR_CALLBACK SocketAvailable(PRFileDesc *fd) { PRInt32 rv; #ifdef _PR_HAVE_PEEK_BUFFER if (fd->secret->peekBytes != 0) { return fd->secret->peekBytes; } #endif rv = _PR_MD_SOCKETAVAILABLE(fd); return rv; } static PRInt64 PR_CALLBACK SocketAvailable64(PRFileDesc *fd) { PRInt64 rv; #ifdef _PR_HAVE_PEEK_BUFFER if (fd->secret->peekBytes != 0) { LL_I2L(rv, fd->secret->peekBytes); return rv; } #endif LL_I2L(rv, _PR_MD_SOCKETAVAILABLE(fd)); return rv; } static PRStatus PR_CALLBACK SocketSync(PRFileDesc *fd) { return PR_SUCCESS; } static PRInt32 PR_CALLBACK SocketSendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 temp, count; const PRNetAddr *addrp = addr; #if defined(_PR_INET6) PRNetAddr addrCopy; #endif PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; } #endif count = 0; while (amount > 0) { temp = _PR_MD_SENDTO(fd, buf, amount, flags, addrp, PR_NETADDR_SIZE(addr), timeout); if (temp < 0) { count = -1; break; } count += temp; if (fd->secret->nonblocking) { break; } buf = (const void*) ((const char*)buf + temp); amount -= temp; } return count; } static PRInt32 PR_CALLBACK SocketRecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 rv; PRUint32 al; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } al = sizeof(PRNetAddr); rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout); #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif return rv; } static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } *nd = NULL; #if defined(WINNT) { PROsfd newSock; PRNetAddr *raddrCopy; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif } } } #else rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout); #endif return rv; } #ifdef WINNT PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv; PROsfd newSock; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr *raddrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } *nd = NULL; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout, PR_TRUE, NULL, NULL); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF (*nd)->secret->af = sd->secret->af; #endif } } return rv; } PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead_WithTimeoutCallback( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, _PR_AcceptTimeoutCallback callback, void *callbackArg) { PRInt32 rv; PROsfd newSock; PRThread *me = _PR_MD_CURRENT_THREAD(); PRNetAddr *raddrCopy; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } *nd = NULL; if (raddr == NULL) { raddr = &raddrCopy; } rv = _PR_MD_FAST_ACCEPT_READ(sd, &newSock, raddr, buf, amount, timeout, PR_TRUE, callback, callbackArg); if (rv < 0) { rv = -1; } else { /* Successfully accepted and read; create the new PRFileDesc */ *nd = PR_AllocFileDesc(newSock, PR_GetTCPMethods()); if (*nd == 0) { _PR_MD_CLOSE_SOCKET(newSock); /* PR_AllocFileDesc() has invoked PR_SetError(). */ rv = -1; } else { (*nd)->secret->md.io_model_committed = PR_TRUE; (*nd)->secret->md.accepted_socket = PR_TRUE; memcpy(&(*nd)->secret->md.peer_addr, *raddr, PR_NETADDR_SIZE(*raddr)); #ifdef _PR_INET6 if (AF_INET6 == *raddr->raw.family) *raddr->raw.family = PR_AF_INET6; #endif #ifdef _PR_NEED_SECRET_AF (*nd)->secret->af = sd->secret->af; #endif } } return rv; } #endif /* WINNT */ #ifdef WINNT PR_IMPLEMENT(void) PR_NTFast_UpdateAcceptContext(PRFileDesc *socket, PRFileDesc *acceptSocket) { _PR_MD_UPDATE_ACCEPT_CONTEXT( socket->secret->md.osfd, acceptSocket->secret->md.osfd); } #endif /* WINNT */ static PRInt32 PR_CALLBACK SocketSendFile( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (_PR_IO_PENDING(me)) { PR_SetError(PR_IO_PENDING_ERROR, 0); return -1; } /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } #if defined(WINNT) rv = _PR_MD_SENDFILE(sd, sfd, flags, timeout); if ((rv >= 0) && (flags == PR_TRANSMITFILE_CLOSE_SOCKET)) { /* * This should be kept the same as SocketClose, except * that _PR_MD_CLOSE_SOCKET(sd->secret->md.osfd) should * not be called because the socket will be recycled. */ PR_FreeFileDesc(sd); } #else rv = PR_EmulateSendFile(sd, sfd, flags, timeout); #endif /* WINNT */ return rv; } static PRInt32 PR_CALLBACK SocketTransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRSendFileData sfd; sfd.fd = fd; sfd.file_offset = 0; sfd.file_nbytes = 0; sfd.header = headers; sfd.hlen = hlen; sfd.trailer = NULL; sfd.tlen = 0; return(SocketSendFile(sd, &sfd, flags, timeout)); } static PRStatus PR_CALLBACK SocketGetName(PRFileDesc *fd, PRNetAddr *addr) { PRInt32 result; PRUint32 addrlen; addrlen = sizeof(PRNetAddr); result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen); if (result < 0) { return PR_FAILURE; } #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE); return PR_SUCCESS; } static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr) { PRInt32 result; PRUint32 addrlen; addrlen = sizeof(PRNetAddr); result = _PR_MD_GETPEERNAME(fd, addr, &addrlen); if (result < 0) { return PR_FAILURE; } #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE); return PR_SUCCESS; } static PRInt16 PR_CALLBACK SocketPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { *out_flags = 0; return in_flags; } /* SocketPoll */ static PRIOMethods tcpMethods = { PR_DESC_SOCKET_TCP, SocketClose, SocketRead, SocketWrite, SocketAvailable, SocketAvailable64, SocketSync, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, SocketWritev, SocketConnect, SocketAccept, SocketBind, SocketListen, SocketShutdown, SocketRecv, SocketSend, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, SocketPoll, SocketAcceptRead, SocketTransmitFile, SocketGetName, SocketGetPeerName, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, _PR_SocketGetSocketOption, _PR_SocketSetSocketOption, SocketSendFile, SocketConnectContinue, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRIOMethods udpMethods = { PR_DESC_SOCKET_UDP, SocketClose, SocketRead, SocketWrite, SocketAvailable, SocketAvailable64, SocketSync, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, SocketWritev, SocketConnect, (PRAcceptFN)_PR_InvalidDesc, SocketBind, SocketListen, SocketShutdown, SocketRecv, SocketSend, SocketRecvFrom, SocketSendTo, SocketPoll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, SocketGetName, SocketGetPeerName, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, _PR_SocketGetSocketOption, _PR_SocketSetSocketOption, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRIOMethods socketpollfdMethods = { (PRDescType) 0, (PRCloseFN)_PR_InvalidStatus, (PRReadFN)_PR_InvalidInt, (PRWriteFN)_PR_InvalidInt, (PRAvailableFN)_PR_InvalidInt, (PRAvailable64FN)_PR_InvalidInt64, (PRFsyncFN)_PR_InvalidStatus, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, SocketPoll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods() { return &tcpMethods; } PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods() { return &udpMethods; } static const PRIOMethods* PR_GetSocketPollFdMethods() { return &socketpollfdMethods; } /* PR_GetSocketPollFdMethods */ #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd); #if defined(_PR_INET6_PROBE) extern PRBool _pr_ipv6_is_present(void); PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket() { PROsfd osfd; osfd = _PR_MD_SOCKET(AF_INET6, SOCK_STREAM, 0); if (osfd != -1) { _PR_MD_CLOSE_SOCKET(osfd); return PR_TRUE; } return PR_FALSE; } #endif /* _PR_INET6_PROBE */ #endif PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { PROsfd osfd; PRFileDesc *fd; PRInt32 tmp_domain = domain; if (!_pr_initialized) _PR_ImplicitInitialization(); if (PR_AF_INET != domain && PR_AF_INET6 != domain #if defined(XP_UNIX) || defined(XP_OS2) && PR_AF_LOCAL != domain #endif ) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return NULL; } #if defined(_PR_INET6_PROBE) if (PR_AF_INET6 == domain) domain = _pr_ipv6_is_present() ? AF_INET6 : AF_INET; #elif defined(_PR_INET6) if (PR_AF_INET6 == domain) domain = AF_INET6; #else if (PR_AF_INET6 == domain) domain = AF_INET; #endif /* _PR_INET6 */ osfd = _PR_MD_SOCKET(domain, type, proto); if (osfd == -1) { return 0; } if (type == SOCK_STREAM) fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods()); else fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods()); /* * Make the sockets non-blocking */ if (fd != NULL) { _PR_MD_MAKE_NONBLOCK(fd); _PR_MD_INIT_FD_INHERITABLE(fd, PR_FALSE); #ifdef _PR_NEED_SECRET_AF fd->secret->af = domain; #endif #if defined(_PR_INET6_PROBE) || !defined(_PR_INET6) /* * For platforms with no support for IPv6 * create layered socket for IPv4-mapped IPv6 addresses */ if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) { if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) { PR_Close(fd); fd = NULL; } } #endif } else _PR_MD_CLOSE_SOCKET(osfd); return fd; } PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void) { PRInt32 domain = AF_INET; return PR_Socket(domain, SOCK_STREAM, 0); } PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void) { PRInt32 domain = AF_INET; return PR_Socket(domain, SOCK_DGRAM, 0); } PR_IMPLEMENT(PRFileDesc *) PR_OpenTCPSocket(PRIntn af) { return PR_Socket(af, SOCK_STREAM, 0); } PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af) { return PR_Socket(af, SOCK_DGRAM, 0); } PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *f[]) { #ifdef XP_UNIX PRInt32 rv, osfd[2]; if (!_pr_initialized) _PR_ImplicitInitialization(); rv = _PR_MD_SOCKETPAIR(AF_UNIX, SOCK_STREAM, 0, osfd); if (rv == -1) { return PR_FAILURE; } f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); if (!f[0]) { _PR_MD_CLOSE_SOCKET(osfd[0]); _PR_MD_CLOSE_SOCKET(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); if (!f[1]) { PR_Close(f[0]); _PR_MD_CLOSE_SOCKET(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } _PR_MD_MAKE_NONBLOCK(f[0]); _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); _PR_MD_MAKE_NONBLOCK(f[1]); _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); return PR_SUCCESS; #elif defined(WINNT) /* * A socket pair is often used for interprocess communication, * so we need to make sure neither socket is associated with * the I/O completion port; otherwise it can't be used by a * child process. * * The default implementation below cannot be used for NT * because PR_Accept would have associated the I/O completion * port with the listening and accepted sockets. */ SOCKET listenSock; SOCKET osfd[2]; struct sockaddr_in selfAddr, peerAddr; int addrLen; if (!_pr_initialized) _PR_ImplicitInitialization(); osfd[0] = osfd[1] = INVALID_SOCKET; listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock == INVALID_SOCKET) { goto failed; } selfAddr.sin_family = AF_INET; selfAddr.sin_port = 0; selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* BugZilla: 35408 */ addrLen = sizeof(selfAddr); if (bind(listenSock, (struct sockaddr *) &selfAddr, addrLen) == SOCKET_ERROR) { goto failed; } if (getsockname(listenSock, (struct sockaddr *) &selfAddr, &addrLen) == SOCKET_ERROR) { goto failed; } if (listen(listenSock, 5) == SOCKET_ERROR) { goto failed; } osfd[0] = socket(AF_INET, SOCK_STREAM, 0); if (osfd[0] == INVALID_SOCKET) { goto failed; } selfAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that connect returns * successfully as soon as the connect request is put * into the listen queue (but before accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (connect(osfd[0], (struct sockaddr *) &selfAddr, addrLen) == SOCKET_ERROR) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket osfd[0]. */ if (getsockname(osfd[0], (struct sockaddr *) &selfAddr, &addrLen) == SOCKET_ERROR) { goto failed; } osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen); if (osfd[1] == INVALID_SOCKET) { goto failed; } if (peerAddr.sin_port != selfAddr.sin_port) { /* the connection we accepted is not from osfd[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } closesocket(listenSock); f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods()); if (!f[0]) { closesocket(osfd[0]); closesocket(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } f[1] = PR_AllocFileDesc(osfd[1], PR_GetTCPMethods()); if (!f[1]) { PR_Close(f[0]); closesocket(osfd[1]); /* PR_AllocFileDesc() has invoked PR_SetError(). */ return PR_FAILURE; } _PR_MD_INIT_FD_INHERITABLE(f[0], PR_FALSE); _PR_MD_INIT_FD_INHERITABLE(f[1], PR_FALSE); return PR_SUCCESS; failed: if (listenSock != INVALID_SOCKET) { closesocket(listenSock); } if (osfd[0] != INVALID_SOCKET) { closesocket(osfd[0]); } if (osfd[1] != INVALID_SOCKET) { closesocket(osfd[1]); } return PR_FAILURE; #else /* not Unix or NT */ /* * default implementation */ PRFileDesc *listenSock; PRNetAddr selfAddr, peerAddr; PRUint16 port; f[0] = f[1] = NULL; listenSock = PR_NewTCPSocket(); if (listenSock == NULL) { goto failed; } PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */ if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } port = ntohs(selfAddr.inet.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { goto failed; } f[0] = PR_NewTCPSocket(); if (f[0] == NULL) { goto failed; } #ifdef _PR_CONNECT_DOES_NOT_BIND /* * If connect does not implicitly bind the socket (e.g., on * BeOS), we have to bind the socket so that we can get its * port with getsockname later. */ PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); if (PR_Bind(f[0], &selfAddr) == PR_FAILURE) { goto failed; } #endif PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that PR_Connect returns * successfully as soon as the connect request is put * into the listen queue (but before PR_Accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (PR_Connect(f[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket f[0]. */ if (PR_GetSockName(f[0], &selfAddr) == PR_FAILURE) { goto failed; } f[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT); if (f[1] == NULL) { goto failed; } if (peerAddr.inet.port != selfAddr.inet.port) { /* the connection we accepted is not from f[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } PR_Close(listenSock); return PR_SUCCESS; failed: if (listenSock) { PR_Close(listenSock); } if (f[0]) { PR_Close(f[0]); } if (f[1]) { PR_Close(f[1]); } return PR_FAILURE; #endif } PR_IMPLEMENT(PROsfd) PR_FileDesc2NativeHandle(PRFileDesc *fd) { if (fd) { fd = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); } if (!fd) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } return fd->secret->md.osfd; } PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PROsfd handle) { if (fd) fd->secret->md.osfd = handle; } /* ** Select compatibility ** */ PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set) { memset(set, 0, sizeof(PR_fd_set)); } PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set) { PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC ); set->harray[set->hsize++] = fh; } PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set) { PRUint32 index, index2; for (index = 0; indexhsize; index++) if (set->harray[index] == fh) { for (index2=index; index2 < (set->hsize-1); index2++) { set->harray[index2] = set->harray[index2+1]; } set->hsize--; break; } } PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set) { PRUint32 index; for (index = 0; indexhsize; index++) if (set->harray[index] == fh) { return 1; } return 0; } PR_IMPLEMENT(void) PR_FD_NSET(PROsfd fd, PR_fd_set *set) { PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC ); set->narray[set->nsize++] = fd; } PR_IMPLEMENT(void) PR_FD_NCLR(PROsfd fd, PR_fd_set *set) { PRUint32 index, index2; for (index = 0; indexnsize; index++) if (set->narray[index] == fd) { for (index2=index; index2 < (set->nsize-1); index2++) { set->narray[index2] = set->narray[index2+1]; } set->nsize--; break; } } PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PROsfd fd, PR_fd_set *set) { PRUint32 index; for (index = 0; indexnsize; index++) if (set->narray[index] == fd) { return 1; } return 0; } #if !defined(NEED_SELECT) #include "obsolete/probslet.h" #define PD_INCR 20 static PRPollDesc *_pr_setfd( PR_fd_set *set, PRInt16 flags, PRPollDesc *polldesc) { PRUintn fsidx, pdidx; PRPollDesc *poll = polldesc; if (NULL == set) return poll; /* First set the pr file handle osfds */ for (fsidx = 0; fsidx < set->hsize; fsidx++) { for (pdidx = 0; 1; pdidx++) { if ((PRFileDesc*)-1 == poll[pdidx].fd) { /* our vector is full - extend and condition it */ poll = (PRPollDesc*)PR_Realloc( poll, (pdidx + 1 + PD_INCR) * sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; memset( poll + pdidx * sizeof(PRPollDesc), 0, PD_INCR * sizeof(PRPollDesc)); poll[pdidx + PD_INCR].fd = (PRFileDesc*)-1; } if ((NULL == poll[pdidx].fd) || (poll[pdidx].fd == set->harray[fsidx])) { /* PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); */ /* either empty or prevously defined */ poll[pdidx].fd = set->harray[fsidx]; /* possibly redundant */ poll[pdidx].in_flags |= flags; /* possibly redundant */ break; } } } #if 0 /* Second set the native osfds */ for (fsidx = 0; fsidx < set->nsize; fsidx++) { for (pdidx = 0; ((PRFileDesc*)-1 != poll[pdidx].fd); pdidx++) { if ((PRFileDesc*)-1 == poll[pdidx].fd) { /* our vector is full - extend and condition it */ poll = PR_Realloc( poll, (pdidx + PD_INCR) * sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; memset( poll + pdidx * sizeof(PRPollDesc), 0, PD_INCR * sizeof(PRPollDesc)); poll[(pdidx + PD_INCR)].fd = (PRFileDesc*)-1; } if ((NULL == poll[pdidx].fd) || (poll[pdidx].fd == set->narray[fsidx])) { /* either empty or prevously defined */ poll[pdidx].fd = set->narray[fsidx]; PR_ASSERT(0 == (poll[pdidx].in_flags & flags)); poll[pdidx].in_flags |= flags; break; } } } #endif /* 0 */ return poll; out_of_memory: if (NULL != polldesc) PR_DELETE(polldesc); return NULL; } /* _pr_setfd */ #endif /* !defined(NEED_SELECT) */ PR_IMPLEMENT(PRInt32) PR_Select( PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, PR_fd_set *pr_ex, PRIntervalTime timeout) { #if !defined(NEED_SELECT) PRInt32 npds = 0; /* ** Find out how many fds are represented in the three lists. ** Then allocate a polling descriptor for the logical union ** (there can't be any overlapping) and call PR_Poll(). */ PRPollDesc *copy, *poll; static PRBool warning = PR_TRUE; if (warning) warning = _PR_Obsolete( "PR_Select()", "PR_Poll()"); /* try to get an initial guesss at how much space we need */ npds = 0; if ((NULL != pr_rd) && ((pr_rd->hsize + pr_rd->nsize - npds) > 0)) npds = pr_rd->hsize + pr_rd->nsize; if ((NULL != pr_wr) && ((pr_wr->hsize + pr_wr->nsize - npds) > 0)) npds = pr_wr->hsize + pr_wr->nsize; if ((NULL != pr_ex) && ((pr_ex->hsize + pr_ex->nsize - npds) > 0)) npds = pr_ex->hsize + pr_ex->nsize; if (0 == npds) { PR_Sleep(timeout); return 0; } copy = poll = (PRPollDesc*)PR_Calloc(npds + PD_INCR, sizeof(PRPollDesc)); if (NULL == poll) goto out_of_memory; poll[npds + PD_INCR - 1].fd = (PRFileDesc*)-1; poll = _pr_setfd(pr_rd, PR_POLL_READ, poll); if (NULL == poll) goto out_of_memory; poll = _pr_setfd(pr_wr, PR_POLL_WRITE, poll); if (NULL == poll) goto out_of_memory; poll = _pr_setfd(pr_ex, PR_POLL_EXCEPT, poll); if (NULL == poll) goto out_of_memory; unused = 0; while (NULL != poll[unused].fd && (PRFileDesc*)-1 != poll[unused].fd) { ++unused; } PR_ASSERT(unused > 0); npds = PR_Poll(poll, unused, timeout); if (npds > 0) { /* Copy the results back into the fd sets */ if (NULL != pr_rd) pr_rd->nsize = pr_rd->hsize = 0; if (NULL != pr_wr) pr_wr->nsize = pr_wr->hsize = 0; if (NULL != pr_ex) pr_ex->nsize = pr_ex->hsize = 0; for (copy = &poll[unused - 1]; copy >= poll; --copy) { if (copy->out_flags & PR_POLL_NVAL) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); npds = -1; break; } if (copy->out_flags & PR_POLL_READ) if (NULL != pr_rd) pr_rd->harray[pr_rd->hsize++] = copy->fd; if (copy->out_flags & PR_POLL_WRITE) if (NULL != pr_wr) pr_wr->harray[pr_wr->hsize++] = copy->fd; if (copy->out_flags & PR_POLL_EXCEPT) if (NULL != pr_ex) pr_ex->harray[pr_ex->hsize++] = copy->fd; } } PR_DELETE(poll); return npds; out_of_memory: PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; #endif /* !defined(NEED_SELECT) */ } nspr-4.11/nspr/pr/src/io/prstdio.c0000644000000000000000000000375312623070344015211 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* ** fprintf to a PRFileDesc */ PR_IMPLEMENT(PRUint32) PR_fprintf(PRFileDesc* fd, const char *fmt, ...) { va_list ap; PRUint32 rv; va_start(ap, fmt); rv = PR_vfprintf(fd, fmt, ap); va_end(ap); return rv; } PR_IMPLEMENT(PRUint32) PR_vfprintf(PRFileDesc* fd, const char *fmt, va_list ap) { /* XXX this could be better */ PRUint32 rv, len; char* msg = PR_vsmprintf(fmt, ap); if (NULL == msg) { return -1; } len = strlen(msg); #ifdef XP_OS2 /* * OS/2 really needs a \r for every \n. * In the future we should try to use scatter-gather instead of a * succession of PR_Write. */ if (isatty(PR_FileDesc2NativeHandle(fd))) { PRUint32 last = 0, idx; PRInt32 tmp; rv = 0; for (idx = 0; idx < len+1; idx++) { if ((idx - last > 0) && (('\n' == msg[idx]) || (idx == len))) { tmp = PR_Write(fd, msg + last, idx - last); if (tmp >= 0) { rv += tmp; } last = idx; } /* * if current character is \n, and * previous character isn't \r, and * next character isn't \r */ if (('\n' == msg[idx]) && ((0 == idx) || ('\r' != msg[idx-1])) && ('\r' != msg[idx+1])) { /* add extra \r */ tmp = PR_Write(fd, "\r", 1); if (tmp >= 0) { rv += tmp; } } } } else { rv = PR_Write(fd, msg, len); } #else rv = PR_Write(fd, msg, len); #endif PR_DELETE(msg); return rv; } nspr-4.11/nspr/pr/src/linking/.cvsignore0000644000000000000000000000001112623070344016365 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/linking/Makefile.in0000644000000000000000000000115412623070344016443 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = \ prlink.c \ $(NULL) TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/linking/prlink.c0000644000000000000000000013100512623070344016040 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #ifdef XP_BEOS #include #endif #if defined(XP_MACOSX) && defined(USE_MACH_DYLD) #include #include #endif #ifdef XP_UNIX #ifdef USE_DLFCN #include /* Define these on systems that don't have them. */ #ifndef RTLD_NOW #define RTLD_NOW 0 #endif #ifndef RTLD_LAZY #define RTLD_LAZY RTLD_NOW #endif #ifndef RTLD_GLOBAL #define RTLD_GLOBAL 0 #endif #ifndef RTLD_LOCAL #define RTLD_LOCAL 0 #endif #ifdef AIX #include #ifndef L_IGNOREUNLOAD /* AIX 4.3.3 does not have L_IGNOREUNLOAD. */ #define L_IGNOREUNLOAD 0x10000000 #endif #endif #ifdef OSF1 #include #include #endif #elif defined(USE_HPSHL) #include #elif defined(USE_MACH_DYLD) #include #endif #endif /* XP_UNIX */ #define _PR_DEFAULT_LD_FLAGS PR_LD_LAZY /* * On these platforms, symbols have a leading '_'. */ #if (defined(DARWIN) && defined(USE_MACH_DYLD)) \ || defined(XP_OS2) \ || ((defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)) #define NEED_LEADING_UNDERSCORE #endif #define PR_LD_PATHW 0x8000 /* for PR_LibSpec_PathnameU */ /************************************************************************/ struct PRLibrary { char* name; /* Our own copy of the name string */ PRLibrary* next; int refCount; const PRStaticLinkTable* staticTable; #ifdef XP_PC #ifdef XP_OS2 HMODULE dlh; #else HINSTANCE dlh; #endif #endif #if defined(XP_MACOSX) && defined(USE_MACH_DYLD) CFragConnectionID connection; CFBundleRef bundle; Ptr main; CFMutableDictionaryRef wrappers; const struct mach_header* image; #endif #ifdef XP_UNIX #if defined(USE_HPSHL) shl_t dlh; #elif defined(USE_MACH_DYLD) NSModule dlh; #else void* dlh; #endif #endif #ifdef XP_BEOS void* dlh; void* stub_dlh; #endif }; static PRLibrary *pr_loadmap; static PRLibrary *pr_exe_loadmap; static PRMonitor *pr_linker_lock; static char* _pr_currentLibPath = NULL; static PRLibrary *pr_LoadLibraryByPathname(const char *name, PRIntn flags); /************************************************************************/ #if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) #define ERR_STR_BUF_LENGTH 20 #endif static void DLLErrorInternal(PRIntn oserr) /* ** This whole function, and most of the code in this file, are run ** with a big hairy lock wrapped around it. Not the best of situations, ** but will eventually come up with the right answer. */ { const char *error = NULL; #ifdef USE_DLFCN error = dlerror(); /* $$$ That'll be wrong some of the time - AOF */ #elif defined(HAVE_STRERROR) error = strerror(oserr); /* this should be okay */ #else char errStrBuf[ERR_STR_BUF_LENGTH]; PR_snprintf(errStrBuf, sizeof(errStrBuf), "error %d", oserr); error = errStrBuf; #endif if (NULL != error) PR_SetErrorText(strlen(error), error); } /* DLLErrorInternal */ void _PR_InitLinker(void) { PRLibrary *lm = NULL; #if defined(XP_UNIX) void *h; #endif if (!pr_linker_lock) { pr_linker_lock = PR_NewNamedMonitor("linker-lock"); } PR_EnterMonitor(pr_linker_lock); #if defined(XP_PC) lm = PR_NEWZAP(PRLibrary); lm->name = strdup("Executable"); #if defined(XP_OS2) lm->dlh = NULLHANDLE; #else /* A module handle for the executable. */ lm->dlh = GetModuleHandle(NULL); #endif /* ! XP_OS2 */ lm->refCount = 1; lm->staticTable = NULL; pr_exe_loadmap = lm; pr_loadmap = lm; #elif defined(XP_UNIX) #ifdef HAVE_DLL #if defined(USE_DLFCN) && !defined(NO_DLOPEN_NULL) h = dlopen(0, RTLD_LAZY); if (!h) { char *error; DLLErrorInternal(_MD_ERRNO()); error = (char*)PR_MALLOC(PR_GetErrorTextLength()); (void) PR_GetErrorText(error); fprintf(stderr, "failed to initialize shared libraries [%s]\n", error); PR_DELETE(error); abort();/* XXX */ } #elif defined(USE_HPSHL) h = NULL; /* don't abort with this NULL */ #elif defined(USE_MACH_DYLD) || defined(NO_DLOPEN_NULL) h = NULL; /* XXXX toshok */ /* XXXX vlad */ #else #error no dll strategy #endif /* USE_DLFCN */ lm = PR_NEWZAP(PRLibrary); if (lm) { lm->name = strdup("a.out"); lm->refCount = 1; lm->dlh = h; lm->staticTable = NULL; } pr_exe_loadmap = lm; pr_loadmap = lm; #endif /* HAVE_DLL */ #endif /* XP_UNIX */ if (lm) { PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (init)", lm->name)); } PR_ExitMonitor(pr_linker_lock); } /* * _PR_ShutdownLinker does not unload the dlls loaded by the application * via calls to PR_LoadLibrary. Any dlls that still remain on the * pr_loadmap list when NSPR shuts down are application programming errors. * The only exception is pr_exe_loadmap, which was added to the list by * NSPR and hence should be cleaned up by NSPR. */ void _PR_ShutdownLinker(void) { /* FIXME: pr_exe_loadmap should be destroyed. */ PR_DestroyMonitor(pr_linker_lock); pr_linker_lock = NULL; if (_pr_currentLibPath) { free(_pr_currentLibPath); _pr_currentLibPath = NULL; } } /******************************************************************************/ PR_IMPLEMENT(PRStatus) PR_SetLibraryPath(const char *path) { PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); if (_pr_currentLibPath) { free(_pr_currentLibPath); } if (path) { _pr_currentLibPath = strdup(path); if (!_pr_currentLibPath) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); rv = PR_FAILURE; } } else { _pr_currentLibPath = 0; } PR_ExitMonitor(pr_linker_lock); return rv; } /* ** Return the library path for finding shared libraries. */ PR_IMPLEMENT(char *) PR_GetLibraryPath(void) { char *ev; char *copy = NULL; /* a copy of _pr_currentLibPath */ if (!_pr_initialized) _PR_ImplicitInitialization(); PR_EnterMonitor(pr_linker_lock); if (_pr_currentLibPath != NULL) { goto exit; } /* initialize pr_currentLibPath */ #ifdef XP_PC ev = getenv("LD_LIBRARY_PATH"); if (!ev) { ev = ".;\\lib"; } ev = strdup(ev); #endif #if defined(XP_UNIX) || defined(XP_BEOS) #if defined(USE_DLFCN) || defined(USE_MACH_DYLD) || defined(XP_BEOS) { char *p=NULL; int len; #ifdef XP_BEOS ev = getenv("LIBRARY_PATH"); if (!ev) { ev = "%A/lib:/boot/home/config/lib:/boot/beos/system/lib"; } #else ev = getenv("LD_LIBRARY_PATH"); if (!ev) { ev = "/usr/lib:/lib"; } #endif len = strlen(ev) + 1; /* +1 for the null */ p = (char*) malloc(len); if (p) { strcpy(p, ev); } /* if (p) */ ev = p; PR_LOG(_pr_io_lm, PR_LOG_NOTICE, ("linker path '%s'", ev)); } #else /* AFAIK there isn't a library path with the HP SHL interface --Rob */ ev = strdup(""); #endif #endif /* * If ev is NULL, we have run out of memory */ _pr_currentLibPath = ev; exit: if (_pr_currentLibPath) { copy = strdup(_pr_currentLibPath); } PR_ExitMonitor(pr_linker_lock); if (!copy) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return copy; } /* ** Build library name from path, lib and extensions */ PR_IMPLEMENT(char*) PR_GetLibraryName(const char *path, const char *lib) { char *fullname; #ifdef XP_PC if (strstr(lib, PR_DLL_SUFFIX) == NULL) { if (path) { fullname = PR_smprintf("%s\\%s%s", path, lib, PR_DLL_SUFFIX); } else { fullname = PR_smprintf("%s%s", lib, PR_DLL_SUFFIX); } } else { if (path) { fullname = PR_smprintf("%s\\%s", path, lib); } else { fullname = PR_smprintf("%s", lib); } } #endif /* XP_PC */ #if defined(XP_UNIX) || defined(XP_BEOS) if (strstr(lib, PR_DLL_SUFFIX) == NULL) { if (path) { fullname = PR_smprintf("%s/lib%s%s", path, lib, PR_DLL_SUFFIX); } else { fullname = PR_smprintf("lib%s%s", lib, PR_DLL_SUFFIX); } } else { if (path) { fullname = PR_smprintf("%s/%s", path, lib); } else { fullname = PR_smprintf("%s", lib); } } #endif /* XP_UNIX || XP_BEOS */ return fullname; } /* ** Free the memory allocated, for the caller, by PR_GetLibraryName */ PR_IMPLEMENT(void) PR_FreeLibraryName(char *mem) { PR_smprintf_free(mem); } static PRLibrary* pr_UnlockedFindLibrary(const char *name) { PRLibrary* lm = pr_loadmap; const char* np = strrchr(name, PR_DIRECTORY_SEPARATOR); np = np ? np + 1 : name; while (lm) { const char* cp = strrchr(lm->name, PR_DIRECTORY_SEPARATOR); cp = cp ? cp + 1 : lm->name; #ifdef WIN32 /* Windows DLL names are case insensitive... */ if (strcmpi(np, cp) == 0) #elif defined(XP_OS2) if (stricmp(np, cp) == 0) #else if (strcmp(np, cp) == 0) #endif { /* found */ lm->refCount++; PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("%s incr => %d (find lib)", lm->name, lm->refCount)); return lm; } lm = lm->next; } return NULL; } PR_IMPLEMENT(PRLibrary*) PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags) { if (flags == 0) { flags = _PR_DEFAULT_LD_FLAGS; } switch (libSpec.type) { case PR_LibSpec_Pathname: return pr_LoadLibraryByPathname(libSpec.value.pathname, flags); #ifdef WIN32 case PR_LibSpec_PathnameU: /* * cast to |char *| and set PR_LD_PATHW flag so that * it can be cast back to PRUnichar* in the callee. */ return pr_LoadLibraryByPathname((const char*) libSpec.value.pathname_u, flags | PR_LD_PATHW); #endif default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } } PR_IMPLEMENT(PRLibrary*) PR_LoadLibrary(const char *name) { PRLibSpec libSpec; libSpec.type = PR_LibSpec_Pathname; libSpec.value.pathname = name; return PR_LoadLibraryWithFlags(libSpec, 0); } #if defined(USE_MACH_DYLD) static NSModule pr_LoadMachDyldModule(const char *name) { NSObjectFileImage ofi; NSModule h = NULL; if (NSCreateObjectFileImageFromFile(name, &ofi) == NSObjectFileImageSuccess) { h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR); if (h == NULL) { NSLinkEditErrors linkEditError; int errorNum; const char *fileName; const char *errorString; NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString); PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("LoadMachDyldModule error %d:%d for file %s:\n%s", linkEditError, errorNum, fileName, errorString)); } if (NSDestroyObjectFileImage(ofi) == FALSE) { if (h) { (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE); h = NULL; } } } return h; } #endif #if defined(XP_MACOSX) && defined(USE_MACH_DYLD) /* ** macLibraryLoadProc is a function definition for a Mac shared library ** loading method. The "name" param is the same full or partial pathname ** that was passed to pr_LoadLibraryByPathName. The function must fill ** in the fields of "lm" which apply to its library type. Returns ** PR_SUCCESS if successful. */ typedef PRStatus (*macLibraryLoadProc)(const char *name, PRLibrary *lm); #ifdef __ppc__ /* ** CFM and its TVectors only exist on PowerPC. Other OS X architectures ** only use Mach-O as a native binary format. */ static void* TV2FP(CFMutableDictionaryRef dict, const char* name, void *tvp) { static uint32 glue[6] = { 0x3D800000, 0x618C0000, 0x800C0000, 0x804C0004, 0x7C0903A6, 0x4E800420 }; uint32* newGlue = NULL; if (tvp != NULL) { CFStringRef nameRef = CFStringCreateWithCString(NULL, name, kCFStringEncodingASCII); if (nameRef) { CFMutableDataRef glueData = (CFMutableDataRef) CFDictionaryGetValue(dict, nameRef); if (glueData == NULL) { glueData = CFDataCreateMutable(NULL, sizeof(glue)); if (glueData != NULL) { newGlue = (uint32*) CFDataGetMutableBytePtr(glueData); memcpy(newGlue, glue, sizeof(glue)); newGlue[0] |= ((UInt32)tvp >> 16); newGlue[1] |= ((UInt32)tvp & 0xFFFF); MakeDataExecutable(newGlue, sizeof(glue)); CFDictionaryAddValue(dict, nameRef, glueData); CFRelease(glueData); PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: created wrapper for CFM function %s().", name)); } } else { PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("TV2FP: found wrapper for CFM function %s().", name)); newGlue = (uint32*) CFDataGetMutableBytePtr(glueData); } CFRelease(nameRef); } } return newGlue; } static PRStatus pr_LoadViaCFM(const char *name, PRLibrary *lm) { OSErr err; Str255 errName; FSRef ref; FSSpec fileSpec; Boolean tempUnusedBool; /* * Make an FSSpec from the path name and call GetDiskFragment. */ /* Use direct conversion of POSIX path to FSRef to FSSpec. */ err = FSPathMakeRef((const UInt8*)name, &ref, NULL); if (err != noErr) return PR_FAILURE; err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &fileSpec, NULL); if (err != noErr) return PR_FAILURE; /* Resolve an alias if this was one */ err = ResolveAliasFile(&fileSpec, true, &tempUnusedBool, &tempUnusedBool); if (err != noErr) return PR_FAILURE; /* Finally, try to load the library */ err = GetDiskFragment(&fileSpec, 0, kCFragGoesToEOF, fileSpec.name, kLoadCFrag, &lm->connection, &lm->main, errName); if (err == noErr && lm->connection) { /* * if we're a mach-o binary, need to wrap all CFM function * pointers. need a hash-table of already seen function * pointers, etc. */ lm->wrappers = CFDictionaryCreateMutable(NULL, 16, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (lm->wrappers) { lm->main = TV2FP(lm->wrappers, "main", lm->main); } else err = memFullErr; } return (err == noErr) ? PR_SUCCESS : PR_FAILURE; } #endif /* __ppc__ */ /* ** Creates a CFBundleRef if the pathname refers to a Mac OS X bundle ** directory. The caller is responsible for calling CFRelease() to ** deallocate. */ static PRStatus pr_LoadCFBundle(const char *name, PRLibrary *lm) { CFURLRef bundleURL; CFBundleRef bundle = NULL; char pathBuf[PATH_MAX]; const char *resolvedPath; CFStringRef pathRef; /* Takes care of relative paths and symlinks */ resolvedPath = realpath(name, pathBuf); if (!resolvedPath) return PR_FAILURE; pathRef = CFStringCreateWithCString(NULL, pathBuf, kCFStringEncodingUTF8); if (pathRef) { bundleURL = CFURLCreateWithFileSystemPath(NULL, pathRef, kCFURLPOSIXPathStyle, true); if (bundleURL) { bundle = CFBundleCreate(NULL, bundleURL); CFRelease(bundleURL); } CFRelease(pathRef); } lm->bundle = bundle; return (bundle != NULL) ? PR_SUCCESS : PR_FAILURE; } static PRStatus pr_LoadViaDyld(const char *name, PRLibrary *lm) { lm->dlh = pr_LoadMachDyldModule(name); if (lm->dlh == NULL) { lm->image = NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING); if (lm->image == NULL) { NSLinkEditErrors linkEditError; int errorNum; const char *fileName; const char *errorString; NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString); PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("LoadMachDyldModule error %d:%d for file %s:\n%s", linkEditError, errorNum, fileName, errorString)); } } return (lm->dlh != NULL || lm->image != NULL) ? PR_SUCCESS : PR_FAILURE; } #endif /* XP_MACOSX && USE_MACH_DYLD */ /* ** Dynamically load a library. Only load libraries once, so scan the load ** map first. */ static PRLibrary* pr_LoadLibraryByPathname(const char *name, PRIntn flags) { PRLibrary *lm; PRLibrary* result = NULL; PRInt32 oserr; #ifdef WIN32 char utf8name_stack[MAX_PATH]; char *utf8name_malloc = NULL; char *utf8name = utf8name_stack; PRUnichar wname_stack[MAX_PATH]; PRUnichar *wname_malloc = NULL; PRUnichar *wname = wname_stack; int len; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); /* See if library is already loaded */ PR_EnterMonitor(pr_linker_lock); #ifdef WIN32 if (flags & PR_LD_PATHW) { /* cast back what's cast to |char *| for the argument passing. */ wname = (LPWSTR) name; } else { int wlen = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0); if (wlen > MAX_PATH) wname = wname_malloc = PR_Malloc(wlen * sizeof(PRUnichar)); if (wname == NULL || !MultiByteToWideChar(CP_ACP, 0, name, -1, wname, wlen)) { oserr = _MD_ERRNO(); goto unlock; } } len = WideCharToMultiByte(CP_UTF8, 0, wname, -1, NULL, 0, NULL, NULL); if (len > MAX_PATH) utf8name = utf8name_malloc = PR_Malloc(len); if (utf8name == NULL || !WideCharToMultiByte(CP_UTF8, 0, wname, -1, utf8name, len, NULL, NULL)) { oserr = _MD_ERRNO(); goto unlock; } /* the list of loaded library names are always kept in UTF-8 * on Win32 platforms */ result = pr_UnlockedFindLibrary(utf8name); #else result = pr_UnlockedFindLibrary(name); #endif if (result != NULL) goto unlock; lm = PR_NEWZAP(PRLibrary); if (lm == NULL) { oserr = _MD_ERRNO(); goto unlock; } lm->staticTable = NULL; #ifdef XP_OS2 /* Why isn't all this stuff in MD code?! */ { HMODULE h; UCHAR pszError[_MAX_PATH]; ULONG ulRc = NO_ERROR; ulRc = DosLoadModule(pszError, _MAX_PATH, (PSZ) name, &h); if (ulRc != NO_ERROR) { oserr = ulRc; PR_DELETE(lm); goto unlock; } lm->name = strdup(name); lm->dlh = h; lm->next = pr_loadmap; pr_loadmap = lm; } #endif /* XP_OS2 */ #ifdef WIN32 { HINSTANCE h; h = LoadLibraryExW(wname, NULL, (flags & PR_LD_ALT_SEARCH_PATH) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0); if (h == NULL) { oserr = _MD_ERRNO(); PR_DELETE(lm); goto unlock; } lm->name = strdup(utf8name); lm->dlh = h; lm->next = pr_loadmap; pr_loadmap = lm; } #endif /* WIN32 */ #if defined(XP_MACOSX) && defined(USE_MACH_DYLD) { int i; PRStatus status; static const macLibraryLoadProc loadProcs[] = { #ifdef __ppc__ pr_LoadViaDyld, pr_LoadCFBundle, pr_LoadViaCFM #else /* __ppc__ */ pr_LoadViaDyld, pr_LoadCFBundle #endif /* __ppc__ */ }; for (i = 0; i < sizeof(loadProcs) / sizeof(loadProcs[0]); i++) { if ((status = loadProcs[i](name, lm)) == PR_SUCCESS) break; } if (status != PR_SUCCESS) { oserr = cfragNoLibraryErr; PR_DELETE(lm); goto unlock; } lm->name = strdup(name); lm->next = pr_loadmap; pr_loadmap = lm; } #endif #if defined(XP_UNIX) && !(defined(XP_MACOSX) && defined(USE_MACH_DYLD)) #ifdef HAVE_DLL { #if defined(USE_DLFCN) #ifdef NTO /* Neutrino needs RTLD_GROUP to load Netscape plugins. (bug 71179) */ int dl_flags = RTLD_GROUP; #elif defined(AIX) /* AIX needs RTLD_MEMBER to load an archive member. (bug 228899) */ int dl_flags = RTLD_MEMBER; #else int dl_flags = 0; #endif void *h = NULL; if (flags & PR_LD_LAZY) { dl_flags |= RTLD_LAZY; } if (flags & PR_LD_NOW) { dl_flags |= RTLD_NOW; } if (flags & PR_LD_GLOBAL) { dl_flags |= RTLD_GLOBAL; } if (flags & PR_LD_LOCAL) { dl_flags |= RTLD_LOCAL; } #if defined(DARWIN) /* ensure the file exists if it contains a slash character i.e. path */ /* DARWIN's dlopen ignores the provided path and checks for the */ /* plain filename in DYLD_LIBRARY_PATH */ if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL || PR_Access(name, PR_ACCESS_EXISTS) == PR_SUCCESS) { h = dlopen(name, dl_flags); } #else h = dlopen(name, dl_flags); #endif #elif defined(USE_HPSHL) int shl_flags = 0; shl_t h; /* * Use the DYNAMIC_PATH flag only if 'name' is a plain file * name (containing no directory) to match the behavior of * dlopen(). */ if (strchr(name, PR_DIRECTORY_SEPARATOR) == NULL) { shl_flags |= DYNAMIC_PATH; } if (flags & PR_LD_LAZY) { shl_flags |= BIND_DEFERRED; } if (flags & PR_LD_NOW) { shl_flags |= BIND_IMMEDIATE; } /* No equivalent of PR_LD_GLOBAL and PR_LD_LOCAL. */ h = shl_load(name, shl_flags, 0L); #elif defined(USE_MACH_DYLD) NSModule h = pr_LoadMachDyldModule(name); #else #error Configuration error #endif if (!h) { oserr = _MD_ERRNO(); PR_DELETE(lm); goto unlock; } lm->name = strdup(name); lm->dlh = h; lm->next = pr_loadmap; pr_loadmap = lm; } #endif /* HAVE_DLL */ #endif /* XP_UNIX && !(XP_MACOSX && USE_MACH_DYLD) */ lm->refCount = 1; #ifdef XP_BEOS { image_info info; int32 cookie = 0; image_id imageid = B_ERROR; image_id stubid = B_ERROR; PRLibrary *p; for (p = pr_loadmap; p != NULL; p = p->next) { /* hopefully, our caller will always use the same string to refer to the same library */ if (strcmp(name, p->name) == 0) { /* we've already loaded this library */ imageid = info.id; lm->refCount++; break; } } if(imageid == B_ERROR) { /* it appears the library isn't yet loaded - load it now */ char stubName [B_PATH_NAME_LENGTH + 1]; /* the following is a work-around to a "bug" in the beos - the beos system loader allows only 32M (system-wide) to be used by code loaded as "add-ons" (code loaded through the 'load_add_on()' system call, which includes mozilla components), but allows 256M to be used by shared libraries. unfortunately, mozilla is too large to fit into the "add-on" space, so we must trick the loader into loading some of the components as shared libraries. this is accomplished by creating a "stub" add-on (an empty shared object), and linking it with the component (the actual .so file generated by the build process, without any modifications). when this stub is loaded by load_add_on(), the loader will automatically load the component into the shared library space. */ strcpy(stubName, name); strcat(stubName, ".stub"); /* first, attempt to load the stub (thereby loading the component as a shared library */ if ((stubid = load_add_on(stubName)) > B_ERROR) { /* the stub was loaded successfully. */ imageid = B_FILE_NOT_FOUND; cookie = 0; while (get_next_image_info(0, &cookie, &info) == B_OK) { const char *endOfSystemName = strrchr(info.name, '/'); const char *endOfPassedName = strrchr(name, '/'); if( 0 == endOfSystemName ) endOfSystemName = info.name; else endOfSystemName++; if( 0 == endOfPassedName ) endOfPassedName = name; else endOfPassedName++; if (strcmp(endOfSystemName, endOfPassedName) == 0) { /* this is the actual component - remember it */ imageid = info.id; break; } } } else { /* we failed to load the "stub" - try to load the component directly as an add-on */ stubid = B_ERROR; imageid = load_add_on(name); } } if (imageid <= B_ERROR) { oserr = imageid; PR_DELETE( lm ); goto unlock; } lm->name = strdup(name); lm->dlh = (void*)imageid; lm->stub_dlh = (void*)stubid; lm->next = pr_loadmap; pr_loadmap = lm; } #endif result = lm; /* success */ PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (load lib)", lm->name)); unlock: if (result == NULL) { PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr); DLLErrorInternal(oserr); /* sets error text */ } #ifdef WIN32 if (utf8name_malloc) PR_Free(utf8name_malloc); if (wname_malloc) PR_Free(wname_malloc); #endif PR_ExitMonitor(pr_linker_lock); return result; } /* ** Unload a shared library which was loaded via PR_LoadLibrary */ PR_IMPLEMENT(PRStatus) PR_UnloadLibrary(PRLibrary *lib) { int result = 0; PRStatus status = PR_SUCCESS; if (lib == 0) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } PR_EnterMonitor(pr_linker_lock); if (lib->refCount <= 0) { PR_ExitMonitor(pr_linker_lock); PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } if (--lib->refCount > 0) { PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("%s decr => %d", lib->name, lib->refCount)); goto done; } #ifdef XP_BEOS if(((image_id)lib->stub_dlh) == B_ERROR) unload_add_on( (image_id) lib->dlh ); else unload_add_on( (image_id) lib->stub_dlh); #endif #ifdef XP_UNIX #ifdef HAVE_DLL #ifdef USE_DLFCN result = dlclose(lib->dlh); #elif defined(USE_HPSHL) result = shl_unload(lib->dlh); #elif defined(USE_MACH_DYLD) if (lib->dlh) result = NSUnLinkModule(lib->dlh, NSUNLINKMODULE_OPTION_NONE) ? 0 : -1; #else #error Configuration error #endif #endif /* HAVE_DLL */ #endif /* XP_UNIX */ #ifdef XP_PC if (lib->dlh) { FreeLibrary((HINSTANCE)(lib->dlh)); lib->dlh = (HINSTANCE)NULL; } #endif /* XP_PC */ #if defined(XP_MACOSX) && defined(USE_MACH_DYLD) /* Close the connection */ if (lib->connection) CloseConnection(&(lib->connection)); if (lib->bundle) CFRelease(lib->bundle); if (lib->wrappers) CFRelease(lib->wrappers); /* No way to unload an image (lib->image) */ #endif /* unlink from library search list */ if (pr_loadmap == lib) pr_loadmap = pr_loadmap->next; else if (pr_loadmap != NULL) { PRLibrary* prev = pr_loadmap; PRLibrary* next = pr_loadmap->next; while (next != NULL) { if (next == lib) { prev->next = next->next; goto freeLib; } prev = next; next = next->next; } /* * fail (the library is not on the _pr_loadmap list), * but don't wipe out an error from dlclose/shl_unload. */ PR_NOT_REACHED("_pr_loadmap and lib->refCount inconsistent"); if (result == 0) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); status = PR_FAILURE; } } /* * We free the PRLibrary structure whether dlclose/shl_unload * succeeds or not. */ freeLib: PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Unloaded library %s", lib->name)); free(lib->name); lib->name = NULL; PR_DELETE(lib); if (result != 0) { PR_SetError(PR_UNLOAD_LIBRARY_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); status = PR_FAILURE; } done: PR_ExitMonitor(pr_linker_lock); return status; } static void* pr_FindSymbolInLib(PRLibrary *lm, const char *name) { void *f = NULL; #ifdef XP_OS2 int rc; #endif if (lm->staticTable != NULL) { const PRStaticLinkTable* tp; for (tp = lm->staticTable; tp->name; tp++) { if (strcmp(name, tp->name) == 0) { return (void*) tp->fp; } } /* ** If the symbol was not found in the static table then check if ** the symbol was exported in the DLL... Win16 only!! */ #if !defined(WIN16) && !defined(XP_BEOS) PR_SetError(PR_FIND_SYMBOL_ERROR, 0); return (void*)NULL; #endif } #ifdef XP_OS2 rc = DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); #if defined(NEED_LEADING_UNDERSCORE) /* * Older plugins (not built using GCC) will have symbols that are not * underscore prefixed. We check for that here. */ if (rc != NO_ERROR) { name++; DosQueryProcAddr(lm->dlh, 0, (PSZ) name, (PFN *) &f); } #endif #endif /* XP_OS2 */ #ifdef WIN32 f = GetProcAddress(lm->dlh, name); #endif /* WIN32 */ #if defined(XP_MACOSX) && defined(USE_MACH_DYLD) /* add this offset to skip the leading underscore in name */ #define SYM_OFFSET 1 if (lm->bundle) { CFStringRef nameRef = CFStringCreateWithCString(NULL, name + SYM_OFFSET, kCFStringEncodingASCII); if (nameRef) { f = CFBundleGetFunctionPointerForName(lm->bundle, nameRef); CFRelease(nameRef); } } if (lm->connection) { Ptr symAddr; CFragSymbolClass symClass; Str255 pName; PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Looking up symbol: %s", name + SYM_OFFSET)); c2pstrcpy(pName, name + SYM_OFFSET); f = (FindSymbol(lm->connection, pName, &symAddr, &symClass) == noErr) ? symAddr : NULL; #ifdef __ppc__ /* callers expect mach-o function pointers, so must wrap tvectors with glue. */ if (f && symClass == kTVectorCFragSymbol) { f = TV2FP(lm->wrappers, name + SYM_OFFSET, f); } #endif /* __ppc__ */ if (f == NULL && strcmp(name + SYM_OFFSET, "main") == 0) f = lm->main; } if (lm->image) { NSSymbol symbol; symbol = NSLookupSymbolInImage(lm->image, name, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); if (symbol != NULL) f = NSAddressOfSymbol(symbol); else f = NULL; } #undef SYM_OFFSET #endif /* XP_MACOSX && USE_MACH_DYLD */ #ifdef XP_BEOS if( B_NO_ERROR != get_image_symbol( (image_id)lm->dlh, name, B_SYMBOL_TYPE_TEXT, &f ) ) { f = NULL; } #endif #ifdef XP_UNIX #ifdef HAVE_DLL #ifdef USE_DLFCN f = dlsym(lm->dlh, name); #elif defined(USE_HPSHL) if (shl_findsym(&lm->dlh, name, TYPE_PROCEDURE, &f) == -1) { f = NULL; } #elif defined(USE_MACH_DYLD) if (lm->dlh) { NSSymbol symbol; symbol = NSLookupSymbolInModule(lm->dlh, name); if (symbol != NULL) f = NSAddressOfSymbol(symbol); else f = NULL; } #endif #endif /* HAVE_DLL */ #endif /* XP_UNIX */ if (f == NULL) { PR_SetError(PR_FIND_SYMBOL_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); } return f; } /* ** Called by class loader to resolve missing native's */ PR_IMPLEMENT(void*) PR_FindSymbol(PRLibrary *lib, const char *raw_name) { void *f = NULL; #if defined(NEED_LEADING_UNDERSCORE) char *name; #else const char *name; #endif /* ** Mangle the raw symbol name in any way that is platform specific. */ #if defined(NEED_LEADING_UNDERSCORE) /* Need a leading _ */ name = PR_smprintf("_%s", raw_name); #elif defined(AIX) /* ** AIX with the normal linker put's a "." in front of the symbol ** name. When use "svcc" and "svld" then the "." disappears. Go ** figure. */ name = raw_name; #else name = raw_name; #endif PR_EnterMonitor(pr_linker_lock); PR_ASSERT(lib != NULL); f = pr_FindSymbolInLib(lib, name); #if defined(NEED_LEADING_UNDERSCORE) PR_smprintf_free(name); #endif PR_ExitMonitor(pr_linker_lock); return f; } /* ** Return the address of the function 'raw_name' in the library 'lib' */ PR_IMPLEMENT(PRFuncPtr) PR_FindFunctionSymbol(PRLibrary *lib, const char *raw_name) { return ((PRFuncPtr) PR_FindSymbol(lib, raw_name)); } PR_IMPLEMENT(void*) PR_FindSymbolAndLibrary(const char *raw_name, PRLibrary* *lib) { void *f = NULL; #if defined(NEED_LEADING_UNDERSCORE) char *name; #else const char *name; #endif PRLibrary* lm; if (!_pr_initialized) _PR_ImplicitInitialization(); /* ** Mangle the raw symbol name in any way that is platform specific. */ #if defined(NEED_LEADING_UNDERSCORE) /* Need a leading _ */ name = PR_smprintf("_%s", raw_name); #elif defined(AIX) /* ** AIX with the normal linker put's a "." in front of the symbol ** name. When use "svcc" and "svld" then the "." disappears. Go ** figure. */ name = raw_name; #else name = raw_name; #endif PR_EnterMonitor(pr_linker_lock); /* search all libraries */ for (lm = pr_loadmap; lm != NULL; lm = lm->next) { f = pr_FindSymbolInLib(lm, name); if (f != NULL) { *lib = lm; lm->refCount++; PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("%s incr => %d (for %s)", lm->name, lm->refCount, name)); break; } } #if defined(NEED_LEADING_UNDERSCORE) PR_smprintf_free(name); #endif PR_ExitMonitor(pr_linker_lock); return f; } PR_IMPLEMENT(PRFuncPtr) PR_FindFunctionSymbolAndLibrary(const char *raw_name, PRLibrary* *lib) { return ((PRFuncPtr) PR_FindSymbolAndLibrary(raw_name, lib)); } /* ** Add a static library to the list of loaded libraries. If LoadLibrary ** is called with the name then we will pretend it was already loaded */ PR_IMPLEMENT(PRLibrary*) PR_LoadStaticLibrary(const char *name, const PRStaticLinkTable *slt) { PRLibrary *lm=NULL; PRLibrary* result = NULL; if (!_pr_initialized) _PR_ImplicitInitialization(); /* See if library is already loaded */ PR_EnterMonitor(pr_linker_lock); /* If the lbrary is already loaded, then add the static table information... */ result = pr_UnlockedFindLibrary(name); if (result != NULL) { PR_ASSERT( (result->staticTable == NULL) || (result->staticTable == slt) ); result->staticTable = slt; goto unlock; } /* Add library to list...Mark it static */ lm = PR_NEWZAP(PRLibrary); if (lm == NULL) goto unlock; lm->name = strdup(name); lm->refCount = 1; lm->dlh = pr_exe_loadmap ? pr_exe_loadmap->dlh : 0; lm->staticTable = slt; lm->next = pr_loadmap; pr_loadmap = lm; result = lm; /* success */ PR_ASSERT(lm->refCount == 1); PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("Loaded library %s (static lib)", lm->name)); unlock: PR_ExitMonitor(pr_linker_lock); return result; } PR_IMPLEMENT(char *) PR_GetLibraryFilePathname(const char *name, PRFuncPtr addr) { #if defined(USE_DLFCN) && defined(HAVE_DLADDR) Dl_info dli; char *result; if (dladdr((void *)addr, &dli) == 0) { PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); return NULL; } result = PR_Malloc(strlen(dli.dli_fname)+1); if (result != NULL) { strcpy(result, dli.dli_fname); } return result; #elif defined(USE_MACH_DYLD) char *result; const char *image_name; int i, count = _dyld_image_count(); for (i = 0; i < count; i++) { image_name = _dyld_get_image_name(i); if (strstr(image_name, name) != NULL) { result = PR_Malloc(strlen(image_name)+1); if (result != NULL) { strcpy(result, image_name); } return result; } } PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); return NULL; #elif defined(AIX) char *result; #define LD_INFO_INCREMENT 64 struct ld_info *info; unsigned int info_length = LD_INFO_INCREMENT * sizeof(struct ld_info); struct ld_info *infop; int loadflags = L_GETINFO | L_IGNOREUNLOAD; for (;;) { info = PR_Malloc(info_length); if (info == NULL) { return NULL; } /* If buffer is too small, loadquery fails with ENOMEM. */ if (loadquery(loadflags, info, info_length) != -1) { break; } /* * Calling loadquery when compiled for 64-bit with the * L_IGNOREUNLOAD flag can cause an invalid argument error * on AIX 5.1. Detect this error the first time that * loadquery is called, and try calling it again without * this flag set. */ if (errno == EINVAL && (loadflags & L_IGNOREUNLOAD)) { loadflags &= ~L_IGNOREUNLOAD; if (loadquery(loadflags, info, info_length) != -1) { break; } } PR_Free(info); if (errno != ENOMEM) { /* should not happen */ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); return NULL; } /* retry with a larger buffer */ info_length += LD_INFO_INCREMENT * sizeof(struct ld_info); } for (infop = info; ; infop = (struct ld_info *)((char *)infop + infop->ldinfo_next)) { unsigned long start = (unsigned long)infop->ldinfo_dataorg; unsigned long end = start + infop->ldinfo_datasize; if (start <= (unsigned long)addr && end > (unsigned long)addr) { result = PR_Malloc(strlen(infop->ldinfo_filename)+1); if (result != NULL) { strcpy(result, infop->ldinfo_filename); } break; } if (!infop->ldinfo_next) { PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); result = NULL; break; } } PR_Free(info); return result; #elif defined(OSF1) /* Contributed by Steve Streeter of HP */ ldr_process_t process, ldr_my_process(); ldr_module_t mod_id; ldr_module_info_t info; ldr_region_t regno; ldr_region_info_t reginfo; size_t retsize; int rv; char *result; /* Get process for which dynamic modules will be listed */ process = ldr_my_process(); /* Attach to process */ rv = ldr_xattach(process); if (rv) { /* should not happen */ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); return NULL; } /* Print information for list of modules */ mod_id = LDR_NULL_MODULE; for (;;) { /* Get information for the next module in the module list. */ ldr_next_module(process, &mod_id); if (ldr_inq_module(process, mod_id, &info, sizeof(info), &retsize) != 0) { /* No more modules */ break; } if (retsize < sizeof(info)) { continue; } /* * Get information for each region in the module and check if any * contain the address of this function. */ for (regno = 0; ; regno++) { if (ldr_inq_region(process, mod_id, regno, ®info, sizeof(reginfo), &retsize) != 0) { /* No more regions */ break; } if (((unsigned long)reginfo.lri_mapaddr <= (unsigned long)addr) && (((unsigned long)reginfo.lri_mapaddr + reginfo.lri_size) > (unsigned long)addr)) { /* Found it. */ result = PR_Malloc(strlen(info.lmi_name)+1); if (result != NULL) { strcpy(result, info.lmi_name); } return result; } } } PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); return NULL; #elif defined(HPUX) && defined(USE_HPSHL) int index; struct shl_descriptor desc; char *result; for (index = 0; shl_get_r(index, &desc) == 0; index++) { if (strstr(desc.filename, name) != NULL) { result = PR_Malloc(strlen(desc.filename)+1); if (result != NULL) { strcpy(result, desc.filename); } return result; } } /* * Since the index value of a library is decremented if * a library preceding it in the shared library search * list was unloaded, it is possible that we missed some * libraries as we went up the list. So we should go * down the list to be sure that we not miss anything. */ for (index--; index >= 0; index--) { if ((shl_get_r(index, &desc) == 0) && (strstr(desc.filename, name) != NULL)) { result = PR_Malloc(strlen(desc.filename)+1); if (result != NULL) { strcpy(result, desc.filename); } return result; } } PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, 0); return NULL; #elif defined(HPUX) && defined(USE_DLFCN) struct load_module_desc desc; char *result; const char *module_name; if (dlmodinfo((unsigned long)addr, &desc, sizeof desc, NULL, 0, 0) == 0) { PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); return NULL; } module_name = dlgetname(&desc, sizeof desc, NULL, 0, 0); if (module_name == NULL) { /* should not happen */ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); return NULL; } result = PR_Malloc(strlen(module_name)+1); if (result != NULL) { strcpy(result, module_name); } return result; #elif defined(WIN32) PRUnichar wname[MAX_PATH]; HMODULE handle = NULL; PRUnichar module_name[MAX_PATH]; int len; char *result; if (MultiByteToWideChar(CP_ACP, 0, name, -1, wname, MAX_PATH)) { handle = GetModuleHandleW(wname); } if (handle == NULL) { PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); return NULL; } if (GetModuleFileNameW(handle, module_name, MAX_PATH) == 0) { /* should not happen */ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); return NULL; } len = WideCharToMultiByte(CP_ACP, 0, module_name, -1, NULL, 0, NULL, NULL); if (len == 0) { _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); return NULL; } result = PR_Malloc(len * sizeof(PRUnichar)); if (result != NULL) { WideCharToMultiByte(CP_ACP, 0, module_name, -1, result, len, NULL, NULL); } return result; #elif defined(XP_OS2) HMODULE module = NULL; char module_name[_MAX_PATH]; char *result; APIRET ulrc = DosQueryModFromEIP(&module, NULL, 0, NULL, NULL, (ULONG) addr); if ((NO_ERROR != ulrc) || (NULL == module) ) { PR_SetError(PR_LIBRARY_NOT_LOADED_ERROR, _MD_ERRNO()); DLLErrorInternal(_MD_ERRNO()); return NULL; } ulrc = DosQueryModuleName(module, sizeof module_name, module_name); if (NO_ERROR != ulrc) { /* should not happen */ _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO()); return NULL; } result = PR_Malloc(strlen(module_name)+1); if (result != NULL) { strcpy(result, module_name); } return result; #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; #endif } nspr-4.11/nspr/pr/src/malloc/.cvsignore0000644000000000000000000000001112623070344016201 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/malloc/Makefile.in0000644000000000000000000000113312623070344016254 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ CSRCS = prmalloc.c prmem.c include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/malloc/prmalloc.c0000644000000000000000000006203012623070344016167 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /* ** We override malloc etc. on any platform which has preemption + ** nspr20 user level threads. When we're debugging, we can make our ** version of malloc fail occasionally. */ #ifdef _PR_OVERRIDE_MALLOC /* ** Thread safe version of malloc, calloc, realloc, free */ #include #ifdef DEBUG #define SANITY #define EXTRA_SANITY #else #undef SANITY #undef EXTRA_SANITY #endif /* Forward decls */ void *_PR_UnlockedMalloc(size_t size); void _PR_UnlockedFree(void *ptr); void *_PR_UnlockedRealloc(void *ptr, size_t size); void *_PR_UnlockedCalloc(size_t n, size_t elsize); /************************************************************************/ /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * */ /* * Defining SANITY will enable some checks which will tell you if the users * program did botch something */ /* * Defining EXTRA_SANITY will enable some checks which are mostly related * to internal conditions in malloc.c */ /* * Very verbose progress on stdout... */ #if 0 # define TRACE(foo) printf foo static int malloc_event; #else # define TRACE(foo) #endif /* XXX Pick a number, any number */ # define malloc_pagesize 4096UL # define malloc_pageshift 12UL #ifdef XP_UNIX #include #include #include #include #include #include #include #endif /* * This structure describes a page's worth of chunks. */ struct pginfo { struct pginfo *next; /* next on the free list */ char *page; /* Pointer to the page */ u_short size; /* size of this page's chunks */ u_short shift; /* How far to shift for this size chunks */ u_short free; /* How many free chunks */ u_short total; /* How many chunk */ u_long bits[1]; /* Which chunks are free */ }; struct pgfree { struct pgfree *next; /* next run of free pages */ struct pgfree *prev; /* prev run of free pages */ char *page; /* pointer to free pages */ char *end; /* pointer to end of free pages */ u_long size; /* number of bytes free */ }; /* * How many bits per u_long in the bitmap. * Change only if not 8 bits/byte */ #define MALLOC_BITS (8*sizeof(u_long)) /* * Magic values to put in the page_directory */ #define MALLOC_NOT_MINE ((struct pginfo*) 0) #define MALLOC_FREE ((struct pginfo*) 1) #define MALLOC_FIRST ((struct pginfo*) 2) #define MALLOC_FOLLOW ((struct pginfo*) 3) #define MALLOC_MAGIC ((struct pginfo*) 4) /* * Set to one when malloc_init has been called */ static unsigned initialized; /* * The size of a page. * Must be a integral multiplum of the granularity of mmap(2). * Your toes will curl if it isn't a power of two */ #define malloc_pagemask ((malloc_pagesize)-1) /* * The size of the largest chunk. * Half a page. */ #define malloc_maxsize ((malloc_pagesize)>>1) /* * malloc_pagesize == 1 << malloc_pageshift */ #ifndef malloc_pageshift static unsigned malloc_pageshift; #endif /* malloc_pageshift */ /* * The smallest allocation we bother about. * Must be power of two */ #ifndef malloc_minsize static unsigned malloc_minsize; #endif /* malloc_minsize */ /* * The largest chunk we care about. * Must be smaller than pagesize * Must be power of two */ #ifndef malloc_maxsize static unsigned malloc_maxsize; #endif /* malloc_maxsize */ #ifndef malloc_cache static unsigned malloc_cache; #endif /* malloc_cache */ /* * The offset from pagenumber to index into the page directory */ static u_long malloc_origo; /* * The last index in the page directory we care about */ static u_long last_index; /* * Pointer to page directory. * Allocated "as if with" malloc */ static struct pginfo **page_dir; /* * How many slots in the page directory */ static unsigned malloc_ninfo; /* * Free pages line up here */ static struct pgfree free_list; /* * Abort() if we fail to get VM ? */ static int malloc_abort; #ifdef SANITY /* * Are we trying to die ? */ static int suicide; #endif /* * dump statistics */ static int malloc_stats; /* * always realloc ? */ static int malloc_realloc; /* * my last break. */ static void *malloc_brk; /* * one location cache for free-list holders */ static struct pgfree *px; static int set_pgdir(void *ptr, struct pginfo *info); static int extend_page_directory(u_long index); #ifdef SANITY void malloc_dump(FILE *fd) { struct pginfo **pd; struct pgfree *pf; int j; pd = page_dir; /* print out all the pages */ for(j=0;j<=last_index;j++) { fprintf(fd,"%08lx %5d ",(j+malloc_origo) << malloc_pageshift,j); if (pd[j] == MALLOC_NOT_MINE) { for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++) ; j--; fprintf(fd,".. %5d not mine\n", j); } else if (pd[j] == MALLOC_FREE) { for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++) ; j--; fprintf(fd,".. %5d free\n", j); } else if (pd[j] == MALLOC_FIRST) { for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++) ; j--; fprintf(fd,".. %5d in use\n", j); } else if (pd[j] < MALLOC_MAGIC) { fprintf(fd,"(%p)\n", pd[j]); } else { fprintf(fd,"%p %d (of %d) x %d @ %p --> %p\n", pd[j],pd[j]->free, pd[j]->total, pd[j]->size, pd[j]->page, pd[j]->next); } } for(pf=free_list.next; pf; pf=pf->next) { fprintf(fd,"Free: @%p [%p...%p[ %ld ->%p <-%p\n", pf,pf->page,pf->end,pf->size,pf->prev,pf->next); if (pf == pf->next) { fprintf(fd,"Free_list loops.\n"); break; } } /* print out various info */ fprintf(fd,"Minsize\t%d\n",malloc_minsize); fprintf(fd,"Maxsize\t%ld\n",malloc_maxsize); fprintf(fd,"Pagesize\t%ld\n",malloc_pagesize); fprintf(fd,"Pageshift\t%ld\n",malloc_pageshift); fprintf(fd,"FirstPage\t%ld\n",malloc_origo); fprintf(fd,"LastPage\t%ld %lx\n",last_index+malloc_pageshift, (last_index + malloc_pageshift) << malloc_pageshift); fprintf(fd,"Break\t%ld\n",(u_long)sbrk(0) >> malloc_pageshift); } static void wrterror(char *fmt, ...) { char *q = "malloc() error: "; char buf[100]; va_list ap; suicide = 1; va_start(ap, fmt); PR_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); fputs(q, stderr); fputs(buf, stderr); malloc_dump(stderr); PR_Abort(); } static void wrtwarning(char *fmt, ...) { char *q = "malloc() warning: "; char buf[100]; va_list ap; va_start(ap, fmt); PR_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); fputs(q, stderr); fputs(buf, stderr); } #endif /* SANITY */ /* * Allocate a number of pages from the OS */ static caddr_t map_pages(int pages, int update) { caddr_t result,tail; result = ((caddr_t)sbrk(0)) + malloc_pagemask - 1; result = (caddr_t) ((u_long)result & ~malloc_pagemask); tail = result + (pages << malloc_pageshift); if (!brk(tail)) { last_index = ((u_long)tail >> malloc_pageshift) - malloc_origo -1; malloc_brk = tail; TRACE(("%6d S %p .. %p\n",malloc_event++, result, tail)); if (!update || last_index < malloc_ninfo || extend_page_directory(last_index)) return result; } TRACE(("%6d s %d %p %d\n",malloc_event++,pages,sbrk(0),errno)); #ifdef EXTRA_SANITY wrterror("map_pages fails\n"); #endif return 0; } #define set_bit(_pi,_bit) \ (_pi)->bits[(_bit)/MALLOC_BITS] |= 1L<<((_bit)%MALLOC_BITS) #define clr_bit(_pi,_bit) \ (_pi)->bits[(_bit)/MALLOC_BITS] &= ~(1L<<((_bit)%MALLOC_BITS)); #define tst_bit(_pi,_bit) \ ((_pi)->bits[(_bit)/MALLOC_BITS] & (1L<<((_bit)%MALLOC_BITS))) /* * Extend page directory */ static int extend_page_directory(u_long index) { struct pginfo **young, **old; int i; TRACE(("%6d E %lu\n",malloc_event++,index)); /* Make it this many pages */ i = index * sizeof *page_dir; i /= malloc_pagesize; i += 2; /* Get new pages, if you used this much mem you don't care :-) */ young = (struct pginfo**) map_pages(i,0); if (!young) return 0; /* Copy the old stuff */ memset(young, 0, i * malloc_pagesize); memcpy(young, page_dir, malloc_ninfo * sizeof *page_dir); /* register the new size */ malloc_ninfo = i * malloc_pagesize / sizeof *page_dir; /* swap the pointers */ old = page_dir; page_dir = young; /* Mark the pages */ index = ((u_long)young >> malloc_pageshift) - malloc_origo; page_dir[index] = MALLOC_FIRST; while (--i) { page_dir[++index] = MALLOC_FOLLOW; } /* Now free the old stuff */ _PR_UnlockedFree(old); return 1; } /* * Set entry in page directory. * Extend page directory if need be. */ static int set_pgdir(void *ptr, struct pginfo *info) { u_long index = ((u_long)ptr >> malloc_pageshift) - malloc_origo; if (index >= malloc_ninfo && !extend_page_directory(index)) return 0; page_dir[index] = info; return 1; } /* * Initialize the world */ static void malloc_init (void) { int i; char *p; TRACE(("%6d I\n",malloc_event++)); #ifdef DEBUG for (p=getenv("MALLOC_OPTIONS"); p && *p; p++) { switch (*p) { case 'a': malloc_abort = 0; break; case 'A': malloc_abort = 1; break; case 'd': malloc_stats = 0; break; case 'D': malloc_stats = 1; break; case 'r': malloc_realloc = 0; break; case 'R': malloc_realloc = 1; break; default: wrtwarning("Unknown chars in MALLOC_OPTIONS\n"); break; } } #endif #ifndef malloc_pagesize /* determine our pagesize */ malloc_pagesize = getpagesize(); #endif /* malloc_pagesize */ #ifndef malloc_pageshift /* determine how much we shift by to get there */ for (i = malloc_pagesize; i > 1; i >>= 1) malloc_pageshift++; #endif /* malloc_pageshift */ #ifndef malloc_cache malloc_cache = 50 << malloc_pageshift; #endif /* malloc_cache */ #ifndef malloc_minsize /* * find the smallest size allocation we will bother about. * this is determined as the smallest allocation that can hold * it's own pginfo; */ i = 2; for(;;) { int j; /* Figure out the size of the bits */ j = malloc_pagesize/i; j /= 8; if (j < sizeof(u_long)) j = sizeof (u_long); if (sizeof(struct pginfo) + j - sizeof (u_long) <= i) break; i += i; } malloc_minsize = i; #endif /* malloc_minsize */ /* Allocate one page for the page directory */ page_dir = (struct pginfo **) map_pages(1,0); #ifdef SANITY if (!page_dir) wrterror("fatal: my first mmap failed. (check limits ?)\n"); #endif /* * We need a maximum of malloc_pageshift buckets, steal these from the * front of the page_directory; */ malloc_origo = (u_long) page_dir >> malloc_pageshift; malloc_origo -= malloc_pageshift; /* Clear it */ memset(page_dir,0,malloc_pagesize); /* Find out how much it tells us */ malloc_ninfo = malloc_pagesize / sizeof *page_dir; /* Plug the page directory into itself */ i = set_pgdir(page_dir,MALLOC_FIRST); #ifdef SANITY if (!i) wrterror("fatal: couldn't set myself in the page directory\n"); #endif /* Been here, done that */ initialized++; } /* * Allocate a number of complete pages */ static void *malloc_pages(size_t size) { void *p,*delay_free = 0; int i; struct pgfree *pf; u_long index; /* How many pages ? */ size += (malloc_pagesize-1); size &= ~malloc_pagemask; p = 0; /* Look for free pages before asking for more */ for(pf = free_list.next; pf; pf = pf->next) { #ifdef EXTRA_SANITY if (pf->page == pf->end) wrterror("zero entry on free_list\n"); if (pf->page > pf->end) { TRACE(("%6d !s %p %p %p <%d>\n",malloc_event++, pf,pf->page,pf->end,__LINE__)); wrterror("sick entry on free_list\n"); } if ((void*)pf->page >= (void*)sbrk(0)) wrterror("entry on free_list past brk\n"); if (page_dir[((u_long)pf->page >> malloc_pageshift) - malloc_origo] != MALLOC_FREE) { TRACE(("%6d !f %p %p %p <%d>\n",malloc_event++, pf,pf->page,pf->end,__LINE__)); wrterror("non-free first page on free-list\n"); } if (page_dir[((u_long)pf->end >> malloc_pageshift) - 1 - malloc_origo] != MALLOC_FREE) wrterror("non-free last page on free-list\n"); #endif /* EXTRA_SANITY */ if (pf->size < size) continue; else if (pf->size == size) { p = pf->page; if (pf->next) pf->next->prev = pf->prev; pf->prev->next = pf->next; delay_free = pf; break; } else { p = pf->page; pf->page += size; pf->size -= size; break; } } #ifdef EXTRA_SANITY if (p && page_dir[((u_long)p >> malloc_pageshift) - malloc_origo] != MALLOC_FREE) { wrterror("allocated non-free page on free-list\n"); } #endif /* EXTRA_SANITY */ size >>= malloc_pageshift; /* Map new pages */ if (!p) p = map_pages(size,1); if (p) { /* Mark the pages in the directory */ index = ((u_long)p >> malloc_pageshift) - malloc_origo; page_dir[index] = MALLOC_FIRST; for (i=1;i> bits)+MALLOC_BITS-1) / MALLOC_BITS); if ((1<<(bits)) <= l+l) { bp = (struct pginfo *)pp; } else { bp = (struct pginfo *)_PR_UnlockedMalloc(l); } if (!bp) return 0; bp->size = (1<shift = bits; bp->total = bp->free = malloc_pagesize >> bits; bp->next = page_dir[bits]; bp->page = (char*)pp; i = set_pgdir(pp,bp); if (!i) return 0; /* We can safely assume that there is nobody in this chain */ page_dir[bits] = bp; /* set all valid bits in the bits */ k = bp->total; i = 0; /* for(;k-i >= MALLOC_BITS; i += MALLOC_BITS) bp->bits[i / MALLOC_BITS] = ~0; */ for(; i < k; i++) set_bit(bp,i); if (bp != pp) return 1; /* We may have used the first ones already */ for(i=0;l > 0;i++) { clr_bit(bp,i); bp->free--; bp->total--; l -= (1 << bits); } return 1; } /* * Allocate a fragment */ static void *malloc_bytes(size_t size) { size_t s; int j; struct pginfo *bp; int k; u_long *lp, bf; /* Don't bother with anything less than this */ if (size < malloc_minsize) { size = malloc_minsize; } /* Find the right bucket */ j = 1; s = size - 1; while (s >>= 1) { j++; } /* If it's empty, make a page more of that size chunks */ if (!page_dir[j] && !malloc_make_chunks(j)) return 0; /* Find first word of bitmap which isn't empty */ bp = page_dir[j]; for (lp = bp->bits; !*lp; lp++) ; /* Find that bit */ bf = *lp; k = 0; while ((bf & 1) == 0) { bf >>= 1; k++; } *lp ^= 1L<free--; if (!bp->free) { page_dir[j] = bp->next; bp->next = 0; } k += (lp - bp->bits)*MALLOC_BITS; return bp->page + (k << bp->shift); } void *_PR_UnlockedMalloc(size_t size) { void *result; /* Round up to a multiple of 8 bytes */ if (size & 7) { size = size + 8 - (size & 7); } if (!initialized) malloc_init(); #ifdef SANITY if (suicide) PR_Abort(); #endif if (size <= malloc_maxsize) result = malloc_bytes(size); else result = malloc_pages(size); #ifdef SANITY if (malloc_abort && !result) wrterror("malloc() returns NULL\n"); #endif TRACE(("%6d M %p %d\n",malloc_event++,result,size)); return result; } void *_PR_UnlockedMemalign(size_t alignment, size_t size) { void *result; /* * alignment has to be a power of 2 */ if ((size <= alignment) && (alignment <= malloc_maxsize)) size = alignment; else size += alignment - 1; /* Round up to a multiple of 8 bytes */ if (size & 7) { size = size + 8 - (size & 7); } if (!initialized) malloc_init(); #ifdef SANITY if (suicide) abort(); #endif if (size <= malloc_maxsize) result = malloc_bytes(size); else result = malloc_pages(size); #ifdef SANITY if (malloc_abort && !result) wrterror("malloc() returns NULL\n"); #endif TRACE(("%6d A %p %d\n",malloc_event++,result,size)); if ((u_long)result & (alignment - 1)) return ((void *)(((u_long)result + alignment) & ~(alignment - 1))); else return result; } void *_PR_UnlockedCalloc(size_t n, size_t nelem) { void *p; /* Compute total size and then round up to a double word amount */ n *= nelem; if (n & 7) { n = n + 8 - (n & 7); } /* Get the memory */ p = _PR_UnlockedMalloc(n); if (p) { /* Zero it */ memset(p, 0, n); } return p; } /* * Change an allocation's size */ void *_PR_UnlockedRealloc(void *ptr, size_t size) { void *p; u_long osize,page,index,tmp_index; struct pginfo **mp; if (!initialized) malloc_init(); #ifdef SANITY if (suicide) PR_Abort(); #endif /* used as free() */ TRACE(("%6d R %p %d\n",malloc_event++, ptr, size)); if (ptr && !size) { _PR_UnlockedFree(ptr); return _PR_UnlockedMalloc (1); } /* used as malloc() */ if (!ptr) { p = _PR_UnlockedMalloc(size); return p; } /* Find the page directory entry for the page in question */ page = (u_long)ptr >> malloc_pageshift; index = page - malloc_origo; /* * check if memory was allocated by memalign */ tmp_index = index; while (page_dir[tmp_index] == MALLOC_FOLLOW) tmp_index--; if (tmp_index != index) { /* * memalign-allocated memory */ index = tmp_index; page = index + malloc_origo; ptr = (void *) (page << malloc_pageshift); } TRACE(("%6d R2 %p %d\n",malloc_event++, ptr, size)); /* make sure it makes sense in some fashion */ if (index < malloc_pageshift || index > last_index) { #ifdef SANITY wrtwarning("junk pointer passed to realloc()\n"); #endif return 0; } /* find the size of that allocation, and see if we need to relocate */ mp = &page_dir[index]; if (*mp == MALLOC_FIRST) { osize = malloc_pagesize; while (mp[1] == MALLOC_FOLLOW) { osize += malloc_pagesize; mp++; } if (!malloc_realloc && size < osize && size > malloc_maxsize && size > (osize - malloc_pagesize)) { return ptr; } } else if (*mp >= MALLOC_MAGIC) { osize = (*mp)->size; if (!malloc_realloc && size < osize && (size > (*mp)->size/2 || (*mp)->size == malloc_minsize)) { return ptr; } } else { #ifdef SANITY wrterror("realloc() of wrong page.\n"); #endif } /* try to reallocate */ p = _PR_UnlockedMalloc(size); if (p) { /* copy the lesser of the two sizes */ if (osize < size) memcpy(p,ptr,osize); else memcpy(p,ptr,size); _PR_UnlockedFree(ptr); } #ifdef DEBUG else if (malloc_abort) wrterror("realloc() returns NULL\n"); #endif return p; } /* * Free a sequence of pages */ static void free_pages(char *ptr, u_long page, int index, struct pginfo *info) { int i; struct pgfree *pf,*pt; u_long l; char *tail; TRACE(("%6d FP %p %d\n",malloc_event++, ptr, page)); /* Is it free already ? */ if (info == MALLOC_FREE) { #ifdef SANITY wrtwarning("freeing free page at %p.\n", ptr); #endif return; } #ifdef SANITY /* Is it not the right place to begin ? */ if (info != MALLOC_FIRST) wrterror("freeing wrong page.\n"); /* Is this really a pointer to a page ? */ if ((u_long)ptr & malloc_pagemask) wrterror("freeing messed up page pointer.\n"); #endif /* Count how many pages it is anyway */ page_dir[index] = MALLOC_FREE; for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++) page_dir[index + i] = MALLOC_FREE; l = i << malloc_pageshift; tail = ptr+l; /* add to free-list */ if (!px) px = (struct pgfree*)_PR_UnlockedMalloc(sizeof *pt); /* XXX check success */ px->page = ptr; px->end = tail; px->size = l; if (!free_list.next) { px->next = free_list.next; px->prev = &free_list; free_list.next = px; pf = px; px = 0; } else { tail = ptr+l; for(pf = free_list.next; pf->next && pf->end < ptr; pf = pf->next) ; for(; pf; pf = pf->next) { if (pf->end == ptr ) { /* append to entry */ pf->end += l; pf->size += l; if (pf->next && pf->end == pf->next->page ) { pt = pf->next; pf->end = pt->end; pf->size += pt->size; pf->next = pt->next; if (pf->next) pf->next->prev = pf; _PR_UnlockedFree(pt); } } else if (pf->page == tail) { /* prepend to entry */ pf->size += l; pf->page = ptr; } else if (pf->page > ptr) { px->next = pf; px->prev = pf->prev; pf->prev = px; px->prev->next = px; pf = px; px = 0; } else if (!pf->next) { px->next = 0; px->prev = pf; pf->next = px; pf = px; px = 0; } else { continue; } break; } } if (!pf->next && pf->size > malloc_cache && pf->end == malloc_brk && malloc_brk == (void*)sbrk(0)) { pf->end = pf->page + malloc_cache; pf->size = malloc_cache; TRACE(("%6d U %p %d\n",malloc_event++,pf->end,pf->end - pf->page)); brk(pf->end); malloc_brk = pf->end; /* Find the page directory entry for the page in question */ page = (u_long)pf->end >> malloc_pageshift; index = page - malloc_origo; /* Now update the directory */ for(i=index;i <= last_index;) page_dir[i++] = MALLOC_NOT_MINE; last_index = index - 1; } } /* * Free a chunk, and possibly the page it's on, if the page becomes empty. */ static void free_bytes(void *ptr, u_long page, int index, struct pginfo *info) { int i; struct pginfo **mp; void *vp; /* Make sure that pointer is multiplum of chunk-size */ #ifdef SANITY if ((u_long)ptr & (info->size - 1)) wrterror("freeing messed up chunk pointer\n"); #endif /* Find the chunk number on the page */ i = ((u_long)ptr & malloc_pagemask) >> info->shift; /* See if it's free already */ if (tst_bit(info,i)) { #ifdef SANITY wrtwarning("freeing free chunk at %p\n", ptr); #endif return; } /* Mark it free */ set_bit(info,i); info->free++; /* If the page was full before, we need to put it on the queue now */ if (info->free == 1) { mp = page_dir + info->shift; while (*mp && (*mp)->next && (*mp)->next->page < info->page) mp = &(*mp)->next; info->next = *mp; *mp = info; return; } /* If this page isn't empty, don't do anything. */ if (info->free != info->total) return; /* We may want to keep at least one page of each size chunks around. */ mp = page_dir + info->shift; if (0 && (*mp == info) && !info->next) return; /* Find & remove this page in the queue */ while (*mp != info) { mp = &((*mp)->next); #ifdef EXTRA_SANITY if (!*mp) { TRACE(("%6d !q %p\n",malloc_event++,info)); wrterror("Not on queue\n"); } #endif } *mp = info->next; /* Free the page & the info structure if need be */ set_pgdir(info->page,MALLOC_FIRST); if((void*)info->page == (void*)info) { _PR_UnlockedFree(info->page); } else { vp = info->page; _PR_UnlockedFree(info); _PR_UnlockedFree(vp); } } void _PR_UnlockedFree(void *ptr) { u_long page; struct pginfo *info; int index, tmp_index; TRACE(("%6d F %p\n",malloc_event++,ptr)); /* This is legal */ if (!ptr) return; #ifdef SANITY /* There wouldn't be anything to free */ if (!initialized) { wrtwarning("free() called before malloc() ever got called\n"); return; } #endif #ifdef SANITY if (suicide) PR_Abort(); #endif /* Find the page directory entry for the page in question */ page = (u_long)ptr >> malloc_pageshift; index = page - malloc_origo; /* * check if memory was allocated by memalign */ tmp_index = index; while (page_dir[tmp_index] == MALLOC_FOLLOW) tmp_index--; if (tmp_index != index) { /* * memalign-allocated memory */ index = tmp_index; page = index + malloc_origo; ptr = (void *) (page << malloc_pageshift); } /* make sure it makes sense in some fashion */ if (index < malloc_pageshift) { #ifdef SANITY wrtwarning("junk pointer %p (low) passed to free()\n", ptr); #endif return; } if (index > last_index) { #ifdef SANITY wrtwarning("junk pointer %p (high) passed to free()\n", ptr); #endif return; } /* handle as page-allocation or chunk allocation */ info = page_dir[index]; if (info < MALLOC_MAGIC) free_pages((char*)ptr, page, index, info); else free_bytes(ptr,page,index,info); return; } #endif /* _PR_OVERRIDE_MALLOC */ nspr-4.11/nspr/pr/src/malloc/prmem.c0000644000000000000000000004236212623070344015504 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Thread safe versions of malloc, free, realloc, calloc and cfree. */ #include "primpl.h" #ifdef _PR_ZONE_ALLOCATOR /* ** The zone allocator code must use native mutexes and cannot ** use PRLocks because PR_NewLock calls PR_Calloc, resulting ** in cyclic dependency of initialization. */ #include union memBlkHdrUn; typedef struct MemoryZoneStr { union memBlkHdrUn *head; /* free list */ pthread_mutex_t lock; size_t blockSize; /* size of blocks on this free list */ PRUint32 locked; /* current state of lock */ PRUint32 contention; /* counter: had to wait for lock */ PRUint32 hits; /* allocated from free list */ PRUint32 misses; /* had to call malloc */ PRUint32 elements; /* on free list */ } MemoryZone; typedef union memBlkHdrUn { unsigned char filler[48]; /* fix the size of this beast */ struct memBlkHdrStr { union memBlkHdrUn *next; MemoryZone *zone; size_t blockSize; size_t requestedSize; PRUint32 magic; } s; } MemBlockHdr; #define MEM_ZONES 7 #define THREAD_POOLS 11 /* prime number for modulus */ #define ZONE_MAGIC 0x0BADC0DE static MemoryZone zones[MEM_ZONES][THREAD_POOLS]; static PRBool use_zone_allocator = PR_FALSE; static void pr_ZoneFree(void *ptr); void _PR_DestroyZones(void) { int i, j; if (!use_zone_allocator) return; for (j = 0; j < THREAD_POOLS; j++) { for (i = 0; i < MEM_ZONES; i++) { MemoryZone *mz = &zones[i][j]; pthread_mutex_destroy(&mz->lock); while (mz->head) { MemBlockHdr *hdr = mz->head; mz->head = hdr->s.next; /* unlink it */ free(hdr); mz->elements--; } } } use_zone_allocator = PR_FALSE; } /* ** pr_FindSymbolInProg ** ** Find the specified data symbol in the program and return ** its address. */ #ifdef HAVE_DLL #if defined(USE_DLFCN) && !defined(NO_DLOPEN_NULL) #include static void * pr_FindSymbolInProg(const char *name) { void *h; void *sym; h = dlopen(0, RTLD_LAZY); if (h == NULL) return NULL; sym = dlsym(h, name); (void)dlclose(h); return sym; } #elif defined(USE_HPSHL) #include static void * pr_FindSymbolInProg(const char *name) { shl_t h = NULL; void *sym; if (shl_findsym(&h, name, TYPE_DATA, &sym) == -1) return NULL; return sym; } #elif defined(USE_MACH_DYLD) || defined(NO_DLOPEN_NULL) static void * pr_FindSymbolInProg(const char *name) { /* FIXME: not implemented */ return NULL; } #else #error "The zone allocator is not supported on this platform" #endif #else /* !defined(HAVE_DLL) */ static void * pr_FindSymbolInProg(const char *name) { /* can't be implemented */ return NULL; } #endif /* HAVE_DLL */ void _PR_InitZones(void) { int i, j; char *envp; PRBool *sym; if ((sym = (PRBool *)pr_FindSymbolInProg("nspr_use_zone_allocator")) != NULL) { use_zone_allocator = *sym; } else if ((envp = getenv("NSPR_USE_ZONE_ALLOCATOR")) != NULL) { use_zone_allocator = (atoi(envp) == 1); } if (!use_zone_allocator) return; for (j = 0; j < THREAD_POOLS; j++) { for (i = 0; i < MEM_ZONES; i++) { MemoryZone *mz = &zones[i][j]; int rv = pthread_mutex_init(&mz->lock, NULL); PR_ASSERT(0 == rv); if (rv != 0) { goto loser; } mz->blockSize = 16 << ( 2 * i); } } return; loser: _PR_DestroyZones(); return; } PR_IMPLEMENT(void) PR_FPrintZoneStats(PRFileDesc *debug_out) { int i, j; for (j = 0; j < THREAD_POOLS; j++) { for (i = 0; i < MEM_ZONES; i++) { MemoryZone *mz = &zones[i][j]; MemoryZone zone = *mz; if (zone.elements || zone.misses || zone.hits) { PR_fprintf(debug_out, "pool: %d, zone: %d, size: %d, free: %d, hit: %d, miss: %d, contend: %d\n", j, i, zone.blockSize, zone.elements, zone.hits, zone.misses, zone.contention); } } } } static void * pr_ZoneMalloc(PRUint32 size) { void *rv; unsigned int zone; size_t blockSize; MemBlockHdr *mb, *mt; MemoryZone *mz; /* Always allocate a non-zero amount of bytes */ if (size < 1) { size = 1; } for (zone = 0, blockSize = 16; zone < MEM_ZONES; ++zone, blockSize <<= 2) { if (size <= blockSize) { break; } } if (zone < MEM_ZONES) { pthread_t me = pthread_self(); unsigned int pool = (PRUptrdiff)me % THREAD_POOLS; PRUint32 wasLocked; mz = &zones[zone][pool]; wasLocked = mz->locked; pthread_mutex_lock(&mz->lock); mz->locked = 1; if (wasLocked) mz->contention++; if (mz->head) { mb = mz->head; PR_ASSERT(mb->s.magic == ZONE_MAGIC); PR_ASSERT(mb->s.zone == mz); PR_ASSERT(mb->s.blockSize == blockSize); PR_ASSERT(mz->blockSize == blockSize); mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize); PR_ASSERT(mt->s.magic == ZONE_MAGIC); PR_ASSERT(mt->s.zone == mz); PR_ASSERT(mt->s.blockSize == blockSize); mz->hits++; mz->elements--; mz->head = mb->s.next; /* take off free list */ mz->locked = 0; pthread_mutex_unlock(&mz->lock); mt->s.next = mb->s.next = NULL; mt->s.requestedSize = mb->s.requestedSize = size; rv = (void *)(mb + 1); return rv; } mz->misses++; mz->locked = 0; pthread_mutex_unlock(&mz->lock); mb = (MemBlockHdr *)malloc(blockSize + 2 * (sizeof *mb)); if (!mb) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } mb->s.next = NULL; mb->s.zone = mz; mb->s.magic = ZONE_MAGIC; mb->s.blockSize = blockSize; mb->s.requestedSize = size; mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize); memcpy(mt, mb, sizeof *mb); rv = (void *)(mb + 1); return rv; } /* size was too big. Create a block with no zone */ blockSize = (size & 15) ? size + 16 - (size & 15) : size; mb = (MemBlockHdr *)malloc(blockSize + 2 * (sizeof *mb)); if (!mb) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } mb->s.next = NULL; mb->s.zone = NULL; mb->s.magic = ZONE_MAGIC; mb->s.blockSize = blockSize; mb->s.requestedSize = size; mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize); memcpy(mt, mb, sizeof *mb); rv = (void *)(mb + 1); return rv; } static void * pr_ZoneCalloc(PRUint32 nelem, PRUint32 elsize) { PRUint32 size = nelem * elsize; void *p = pr_ZoneMalloc(size); if (p) { memset(p, 0, size); } return p; } static void * pr_ZoneRealloc(void *oldptr, PRUint32 bytes) { void *rv; MemBlockHdr *mb; int ours; MemBlockHdr phony; if (!oldptr) return pr_ZoneMalloc(bytes); mb = (MemBlockHdr *)((char *)oldptr - (sizeof *mb)); if (mb->s.magic != ZONE_MAGIC) { /* Maybe this just came from ordinary malloc */ #ifdef DEBUG fprintf(stderr, "Warning: reallocing memory block %p from ordinary malloc\n", oldptr); #endif /* * We are going to realloc oldptr. If realloc succeeds, the * original value of oldptr will point to freed memory. So this * function must not fail after a successfull realloc call. We * must perform any operation that may fail before the realloc * call. */ rv = pr_ZoneMalloc(bytes); /* this may fail */ if (!rv) { return rv; } /* We don't know how big it is. But we can fix that. */ oldptr = realloc(oldptr, bytes); /* * If realloc returns NULL, this function loses the original * value of oldptr. This isn't a leak because the caller of * this function still has the original value of oldptr. */ if (!oldptr) { if (bytes) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); pr_ZoneFree(rv); return oldptr; } } phony.s.requestedSize = bytes; mb = &phony; ours = 0; } else { size_t blockSize = mb->s.blockSize; MemBlockHdr *mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize); PR_ASSERT(mt->s.magic == ZONE_MAGIC); PR_ASSERT(mt->s.zone == mb->s.zone); PR_ASSERT(mt->s.blockSize == blockSize); if (bytes <= blockSize) { /* The block is already big enough. */ mt->s.requestedSize = mb->s.requestedSize = bytes; return oldptr; } ours = 1; rv = pr_ZoneMalloc(bytes); if (!rv) { return rv; } } if (oldptr && mb->s.requestedSize) memcpy(rv, oldptr, mb->s.requestedSize); if (ours) pr_ZoneFree(oldptr); else if (oldptr) free(oldptr); return rv; } static void pr_ZoneFree(void *ptr) { MemBlockHdr *mb, *mt; MemoryZone *mz; size_t blockSize; PRUint32 wasLocked; if (!ptr) return; mb = (MemBlockHdr *)((char *)ptr - (sizeof *mb)); if (mb->s.magic != ZONE_MAGIC) { /* maybe this came from ordinary malloc */ #ifdef DEBUG fprintf(stderr, "Warning: freeing memory block %p from ordinary malloc\n", ptr); #endif free(ptr); return; } blockSize = mb->s.blockSize; mz = mb->s.zone; mt = (MemBlockHdr *)(((char *)(mb + 1)) + blockSize); PR_ASSERT(mt->s.magic == ZONE_MAGIC); PR_ASSERT(mt->s.zone == mz); PR_ASSERT(mt->s.blockSize == blockSize); if (!mz) { PR_ASSERT(blockSize > 65536); /* This block was not in any zone. Just free it. */ free(mb); return; } PR_ASSERT(mz->blockSize == blockSize); wasLocked = mz->locked; pthread_mutex_lock(&mz->lock); mz->locked = 1; if (wasLocked) mz->contention++; mt->s.next = mb->s.next = mz->head; /* put on head of list */ mz->head = mb; mz->elements++; mz->locked = 0; pthread_mutex_unlock(&mz->lock); } PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size) { if (!_pr_initialized) _PR_ImplicitInitialization(); return use_zone_allocator ? pr_ZoneMalloc(size) : malloc(size); } PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize) { if (!_pr_initialized) _PR_ImplicitInitialization(); return use_zone_allocator ? pr_ZoneCalloc(nelem, elsize) : calloc(nelem, elsize); } PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size) { if (!_pr_initialized) _PR_ImplicitInitialization(); return use_zone_allocator ? pr_ZoneRealloc(ptr, size) : realloc(ptr, size); } PR_IMPLEMENT(void) PR_Free(void *ptr) { if (use_zone_allocator) pr_ZoneFree(ptr); else free(ptr); } #else /* !defined(_PR_ZONE_ALLOCATOR) */ /* ** The PR_Malloc, PR_Calloc, PR_Realloc, and PR_Free functions simply ** call their libc equivalents now. This may seem redundant, but it ** ensures that we are calling into the same runtime library. On ** Win32, it is possible to have multiple runtime libraries (e.g., ** objects compiled with /MD and /MDd) in the same process, and ** they maintain separate heaps, which cannot be mixed. */ PR_IMPLEMENT(void *) PR_Malloc(PRUint32 size) { #if defined (WIN16) return PR_MD_malloc( (size_t) size); #else return malloc(size); #endif } PR_IMPLEMENT(void *) PR_Calloc(PRUint32 nelem, PRUint32 elsize) { #if defined (WIN16) return PR_MD_calloc( (size_t)nelem, (size_t)elsize ); #else return calloc(nelem, elsize); #endif } PR_IMPLEMENT(void *) PR_Realloc(void *ptr, PRUint32 size) { #if defined (WIN16) return PR_MD_realloc( ptr, (size_t) size); #else return realloc(ptr, size); #endif } PR_IMPLEMENT(void) PR_Free(void *ptr) { #if defined (WIN16) PR_MD_free( ptr ); #else free(ptr); #endif } #endif /* _PR_ZONE_ALLOCATOR */ /* ** Complexity alert! ** ** If malloc/calloc/free (etc.) were implemented to use pr lock's then ** the entry points could block when called if some other thread had the ** lock. ** ** Most of the time this isn't a problem. However, in the case that we ** are using the thread safe malloc code after PR_Init but before ** PR_AttachThread has been called (on a native thread that nspr has yet ** to be told about) we could get royally screwed if the lock was busy ** and we tried to context switch the thread away. In this scenario ** PR_CURRENT_THREAD() == NULL ** ** To avoid this unfortunate case, we use the low level locking ** facilities for malloc protection instead of the slightly higher level ** locking. This makes malloc somewhat faster so maybe it's a good thing ** anyway. */ #ifdef _PR_OVERRIDE_MALLOC /* Imports */ extern void *_PR_UnlockedMalloc(size_t size); extern void *_PR_UnlockedMemalign(size_t alignment, size_t size); extern void _PR_UnlockedFree(void *ptr); extern void *_PR_UnlockedRealloc(void *ptr, size_t size); extern void *_PR_UnlockedCalloc(size_t n, size_t elsize); static PRBool _PR_malloc_initialised = PR_FALSE; #ifdef _PR_PTHREADS static pthread_mutex_t _PR_MD_malloc_crustylock; #define _PR_Lock_Malloc() { \ if(PR_TRUE == _PR_malloc_initialised) { \ PRStatus rv; \ rv = pthread_mutex_lock(&_PR_MD_malloc_crustylock); \ PR_ASSERT(0 == rv); \ } #define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \ PRStatus rv; \ rv = pthread_mutex_unlock(&_PR_MD_malloc_crustylock); \ PR_ASSERT(0 == rv); \ } \ } #else /* _PR_PTHREADS */ static _MDLock _PR_MD_malloc_crustylock; #ifdef IRIX #define _PR_Lock_Malloc() { \ PRIntn _is; \ if(PR_TRUE == _PR_malloc_initialised) { \ if (_PR_MD_GET_ATTACHED_THREAD() && \ !_PR_IS_NATIVE_THREAD( \ _PR_MD_GET_ATTACHED_THREAD())) \ _PR_INTSOFF(_is); \ _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \ } #define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \ _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \ if (_PR_MD_GET_ATTACHED_THREAD() && \ !_PR_IS_NATIVE_THREAD( \ _PR_MD_GET_ATTACHED_THREAD())) \ _PR_INTSON(_is); \ } \ } #else /* IRIX */ #define _PR_Lock_Malloc() { \ PRIntn _is; \ if(PR_TRUE == _PR_malloc_initialised) { \ if (_PR_MD_CURRENT_THREAD() && \ !_PR_IS_NATIVE_THREAD( \ _PR_MD_CURRENT_THREAD())) \ _PR_INTSOFF(_is); \ _PR_MD_LOCK(&_PR_MD_malloc_crustylock); \ } #define _PR_Unlock_Malloc() if(PR_TRUE == _PR_malloc_initialised) { \ _PR_MD_UNLOCK(&_PR_MD_malloc_crustylock); \ if (_PR_MD_CURRENT_THREAD() && \ !_PR_IS_NATIVE_THREAD( \ _PR_MD_CURRENT_THREAD())) \ _PR_INTSON(_is); \ } \ } #endif /* IRIX */ #endif /* _PR_PTHREADS */ PR_IMPLEMENT(PRStatus) _PR_MallocInit(void) { PRStatus rv = PR_SUCCESS; if( PR_TRUE == _PR_malloc_initialised ) return PR_SUCCESS; #ifdef _PR_PTHREADS { int status; pthread_mutexattr_t mattr; status = _PT_PTHREAD_MUTEXATTR_INIT(&mattr); PR_ASSERT(0 == status); status = _PT_PTHREAD_MUTEX_INIT(_PR_MD_malloc_crustylock, mattr); PR_ASSERT(0 == status); status = _PT_PTHREAD_MUTEXATTR_DESTROY(&mattr); PR_ASSERT(0 == status); } #else /* _PR_PTHREADS */ _MD_NEW_LOCK(&_PR_MD_malloc_crustylock); #endif /* _PR_PTHREADS */ if( PR_SUCCESS == rv ) { _PR_malloc_initialised = PR_TRUE; } return rv; } void *malloc(size_t size) { void *p; _PR_Lock_Malloc(); p = _PR_UnlockedMalloc(size); _PR_Unlock_Malloc(); return p; } #if defined(IRIX) void *memalign(size_t alignment, size_t size) { void *p; _PR_Lock_Malloc(); p = _PR_UnlockedMemalign(alignment, size); _PR_Unlock_Malloc(); return p; } void *valloc(size_t size) { return(memalign(sysconf(_SC_PAGESIZE),size)); } #endif /* IRIX */ void free(void *ptr) { _PR_Lock_Malloc(); _PR_UnlockedFree(ptr); _PR_Unlock_Malloc(); } void *realloc(void *ptr, size_t size) { void *p; _PR_Lock_Malloc(); p = _PR_UnlockedRealloc(ptr, size); _PR_Unlock_Malloc(); return p; } void *calloc(size_t n, size_t elsize) { void *p; _PR_Lock_Malloc(); p = _PR_UnlockedCalloc(n, elsize); _PR_Unlock_Malloc(); return p; } void cfree(void *p) { _PR_Lock_Malloc(); _PR_UnlockedFree(p); _PR_Unlock_Malloc(); } void _PR_InitMem(void) { PRStatus rv; rv = _PR_MallocInit(); PR_ASSERT(PR_SUCCESS == rv); } #endif /* _PR_OVERRIDE_MALLOC */ nspr-4.11/nspr/pr/src/md/.cvsignore0000644000000000000000000000001112623070344015332 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/md/Makefile.in0000644000000000000000000000114112623070344015404 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk DIRS = $(PR_MD_ARCH_DIR) CSRCS = \ prosdep.c \ $(NULL) TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/md/beos/.cvsignore0000644000000000000000000000001112623070344016262 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/md/beos/Makefile.in0000644000000000000000000000115212623070344016336 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk include $(srcdir)/bsrcs.mk CSRCS += $(MDCSRCS) TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/md/beos/bcpu.c0000644000000000000000000000206712623070344015374 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" PR_EXTERN(void) _PR_MD_INIT_CPUS(); PR_EXTERN(void) _PR_MD_WAKEUP_CPUS(); PR_EXTERN(void) _PR_MD_START_INTERRUPTS(void); PR_EXTERN(void) _PR_MD_STOP_INTERRUPTS(void); PR_EXTERN(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void); PR_EXTERN(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void); PR_EXTERN(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void); PR_EXTERN(void) _PR_MD_CLOCK_INTERRUPT(void); PR_EXTERN(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone); PR_EXTERN(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts); PR_EXTERN(PRInt32) _PR_MD_GET_INTSOFF(void); PR_EXTERN(void) _PR_MD_SET_INTSOFF(PRInt32 _val); PR_EXTERN(_PRCPU*) _PR_MD_CURRENT_CPU(void); PR_EXTERN(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu); PR_EXTERN(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu); PR_EXTERN(PRInt32) _PR_MD_PAUSE_CPU(PRIntervalTime timeout); nspr-4.11/nspr/pr/src/md/beos/beos.c0000644000000000000000000001131312623070344015365 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include #include #include #include #include #include /* * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or * PRInt32* pointer to a _PRSockLen_t* pointer. */ #define _PRSockLen_t int /* ** Global lock variable used to bracket calls into rusty libraries that ** aren't thread safe (like libc, libX, etc). */ static PRLock *_pr_rename_lock = NULL; static PRMonitor *_pr_Xfe_mon = NULL; /* * Variables used by the GC code, initialized in _MD_InitSegs(). * _pr_zero_fd should be a static variable. Unfortunately, there is * still some Unix-specific code left in function PR_GrowSegment() * in file memory/prseg.c that references it, so it needs * to be a global variable for now. */ PRInt32 _pr_zero_fd = -1; static PRLock *_pr_md_lock = NULL; sigset_t timer_set; void _PR_UnixInit() { struct sigaction sigact; int rv; sigemptyset(&timer_set); sigact.sa_handler = SIG_IGN; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; rv = sigaction(SIGPIPE, &sigact, 0); PR_ASSERT(0 == rv); _pr_rename_lock = PR_NewLock(); PR_ASSERT(NULL != _pr_rename_lock); _pr_Xfe_mon = PR_NewMonitor(); PR_ASSERT(NULL != _pr_Xfe_mon); } /* *----------------------------------------------------------------------- * * PR_Now -- * * Returns the current time in microseconds since the epoch. * The epoch is midnight January 1, 1970 GMT. * The implementation is machine dependent. This is the Unix * implementation. * Cf. time_t time(time_t *tp) * *----------------------------------------------------------------------- */ PR_IMPLEMENT(PRTime) PR_Now(void) { struct timeval tv; PRInt64 s, us, s2us; GETTIMEOFDAY(&tv); LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, tv.tv_sec); LL_I2L(us, tv.tv_usec); LL_MUL(s, s, s2us); LL_ADD(s, s, us); return s; } PRIntervalTime _PR_UNIX_GetInterval() { struct timeval time; PRIntervalTime ticks; (void)GETTIMEOFDAY(&time); /* fallicy of course */ ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */ ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */ return ticks; } /* _PR_SUNOS_GetInterval */ PRIntervalTime _PR_UNIX_TicksPerSecond() { return 1000; /* this needs some work :) */ } /************************************************************************/ /* ** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread ** safe. Unfortunately, neither is mozilla. To make these programs work ** in a pre-emptive threaded environment, we need to use a lock. */ void PR_XLock() { PR_EnterMonitor(_pr_Xfe_mon); } void PR_XUnlock() { PR_ExitMonitor(_pr_Xfe_mon); } PRBool PR_XIsLocked() { return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE; } void PR_XWait(int ms) { PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms)); } void PR_XNotify(void) { PR_Notify(_pr_Xfe_mon); } void PR_XNotifyAll(void) { PR_NotifyAll(_pr_Xfe_mon); } #if !defined(BEOS) #ifdef HAVE_BSD_FLOCK #include PR_IMPLEMENT(PRStatus) _MD_LOCKFILE (PRInt32 f) { PRInt32 rv; rv = flock(f, LOCK_EX); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) _MD_TLOCKFILE (PRInt32 f) { PRInt32 rv; rv = flock(f, LOCK_EX|LOCK_NB); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) _MD_UNLOCKFILE (PRInt32 f) { PRInt32 rv; rv = flock(f, LOCK_UN); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } #else PR_IMPLEMENT(PRStatus) _MD_LOCKFILE (PRInt32 f) { PRInt32 rv; rv = lockf(f, F_LOCK, 0); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) _MD_TLOCKFILE (PRInt32 f) { PRInt32 rv; rv = lockf(f, F_TLOCK, 0); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) _MD_UNLOCKFILE (PRInt32 f) { PRInt32 rv; rv = lockf(f, F_ULOCK, 0); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); return PR_FAILURE; } #endif PR_IMPLEMENT(PRStatus) _MD_GETHOSTNAME (char *name, PRUint32 namelen) { PRIntn rv; rv = gethostname(name, namelen); if (0 == rv) { return PR_SUCCESS; } _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO()); return PR_FAILURE; } #endif nspr-4.11/nspr/pr/src/md/beos/beos_errors.c0000644000000000000000000007363212623070344016775 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prtypes.h" #include "md/_unix_errors.h" #include "prerror.h" #include void _MD_unix_map_opendir_error(int err) { switch (err) { case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EMFILE: PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err); break; case ENFILE: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_closedir_error(int err) { switch (err) { case EINVAL: case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_readdir_error(int err) { switch (err) { case 0: case ENOENT: PR_SetError(PR_NO_MORE_FILES_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #ifdef IRIX #ifdef IRIX5_3 #else case EDIRCORRUPTED: PR_SetError(PR_DIRECTORY_CORRUPTED_ERROR, err); break; #endif #endif #ifdef EOVERFLOW case EOVERFLOW: PR_SetError(PR_IO_ERROR, err); break; #endif case EINVAL: PR_SetError(PR_IO_ERROR, err); break; #ifdef EBADMSG case EBADMSG: PR_SetError(PR_IO_ERROR, err); break; #endif case EDEADLK: PR_SetError(PR_DEADLOCK_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case ENOLCK: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; #ifdef ENOLINK case ENOLINK: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; #endif case ENXIO: PR_SetError(PR_IO_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_unlink_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EBUSY: PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case EPERM: PR_SetError(PR_IS_DIRECTORY_ERROR, err); break; case EROFS: PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_stat_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; #ifdef EOVERFLOW case EOVERFLOW: PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_fstat_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case ETIMEDOUT: #ifdef ENOLINK case ENOLINK: #endif PR_SetError(PR_REMOTE_FILE_ERROR, err); break; #ifdef EOVERFLOW case EOVERFLOW: PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_rename_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EBUSY: PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err); break; #ifdef EDQUOT case EDQUOT: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; #endif case EEXIST: PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case EISDIR: PR_SetError(PR_IS_DIRECTORY_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENOSPC: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case EROFS: PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err); break; case EXDEV: PR_SetError(PR_NOT_SAME_DEVICE_ERROR, err); break; case EMLINK: PR_SetError(PR_MAX_DIRECTORY_ENTRIES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_access_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case EROFS: PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_mkdir_error(int err) { switch (err) { case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EEXIST: PR_SetError(PR_FILE_EXISTS_ERROR, err); break; case EROFS: PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case EMLINK: PR_SetError(PR_MAX_DIRECTORY_ENTRIES_ERROR, err); break; case ENOSPC: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; #ifdef EDQUOT case EDQUOT: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; #endif case EIO: PR_SetError(PR_IO_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_rmdir_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EBUSY: PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err); break; case EEXIST: PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINVAL: PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case EROFS: PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_read_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #ifdef EBADMSG case EBADMSG: PR_SetError(PR_IO_ERROR, err); break; #endif case EDEADLK: PR_SetError(PR_DEADLOCK_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_METHOD_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case ENOLCK: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ENXIO: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case EISDIR: PR_SetError(PR_IS_DIRECTORY_ERROR, err); break; case ECONNRESET: case EPIPE: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; #ifdef ENOLINK case ENOLINK: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_write_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EDEADLK: PR_SetError(PR_DEADLOCK_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EFBIG: PR_SetError(PR_FILE_TOO_BIG_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_METHOD_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case ENOLCK: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif case ENOSPC: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; case ENXIO: PR_SetError(PR_INVALID_METHOD_ERROR, err); break; case ERANGE: PR_SetError(PR_INVALID_METHOD_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case ECONNRESET: case EPIPE: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; #ifdef EDQUOT case EDQUOT: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; #endif #ifdef ENOLINK case ENOLINK: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_lseek_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ESPIPE: PR_SetError(PR_INVALID_METHOD_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_fsync_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #ifdef ENOLINK case ENOLINK: #endif case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_METHOD_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_close_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; #ifdef ENOLINK case ENOLINK: #endif case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_socket_error(int err) { switch (err) { case EPROTONOSUPPORT: PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err); break; case EMFILE: PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err); break; case ENFILE: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; #if !defined(SCO) case ENOBUFS: #endif /* !defined(SCO) */ case ENOMEM: #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_socketavailable_error(int err) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); } void _MD_unix_map_recv_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; case ECONNRESET: case EPIPE: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_recvfrom_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif case ECONNRESET: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_send_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif #if !defined(BEOS) case EMSGSIZE: #endif case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; #if !defined(SCO) case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif /* !defined(SCO) */ case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif case ECONNRESET: case EPIPE: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_sendto_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif #if !defined(BEOS) case EMSGSIZE: #endif case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; #if !defined(SCO) case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif /* !defined(SCO) */ case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif case ECONNRESET: case EPIPE: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_writev_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ECONNRESET: case EPIPE: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_accept_error(int err) { switch (err) { case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif #if !defined(BEOS) case EOPNOTSUPP: #endif case ENODEV: PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EMFILE: PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err); break; case ENFILE: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif #ifdef EPROTO case EPROTO: PR_SetError(PR_IO_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_connect_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EADDRNOTAVAIL: PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err); break; case EINPROGRESS: PR_SetError(PR_IN_PROGRESS_ERROR, err); break; case EALREADY: PR_SetError(PR_ALREADY_INITIATED_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case EAFNOSUPPORT: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_IO_TIMEOUT_ERROR, err); break; case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case ENETUNREACH: PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err); break; case EADDRINUSE: PR_SetError(PR_ADDRESS_IN_USE_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; /* * UNIX domain sockets are not supported in NSPR */ case EACCES: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case EIO: #if defined(UNIXWARE) /* * On some platforms, if we connect to a port on * the local host (the loopback address) that no * process is listening on, we get EIO instead * of ECONNREFUSED. */ PR_SetError(PR_CONNECT_REFUSED_ERROR, err); #else PR_SetError(PR_IO_ERROR, err); #endif break; case ELOOP: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; case ENOENT: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif case ENXIO: PR_SetError(PR_IO_ERROR, err); break; case EPROTOTYPE: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_bind_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EADDRNOTAVAIL: PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err); break; case EADDRINUSE: PR_SetError(PR_ADDRESS_IN_USE_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EINVAL: PR_SetError(PR_SOCKET_ADDRESS_IS_BOUND_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif /* * UNIX domain sockets are not supported in NSPR */ case EIO: case EISDIR: case ELOOP: case ENOENT: case ENOTDIR: case EROFS: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_listen_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif #if !defined(BEOS) case EOPNOTSUPP: PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_shutdown_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case ENOTCONN: PR_SetError(PR_NOT_CONNECTED_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; #ifdef ENOSR case ENOSR: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_socketpair_error(int err) { switch (err) { case EMFILE: PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ENOMEM: #ifdef ENOSR case ENOSR: #endif PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case EAFNOSUPPORT: case EPROTONOSUPPORT: #if !defined(BEOS) case EOPNOTSUPP: #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_getsockname_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #if !defined(SCO) case ENOBUFS: #endif /* !defined(SCO) */ case ENOMEM: #ifdef ENOSR case ENOSR: #endif PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_getpeername_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case ENOTCONN: PR_SetError(PR_NOT_CONNECTED_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #if !defined(SCO) case ENOBUFS: #endif /* !defined(SCO) */ case ENOMEM: #ifdef ENOSR case ENOSR: #endif PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_getsockopt_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case ENOPROTOOPT: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINVAL: PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err); break; case ENOMEM: #ifdef ENOSR case ENOSR: #endif PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_setsockopt_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; #if !defined(BEOS) case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #endif case ENOPROTOOPT: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINVAL: PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err); break; case ENOMEM: #ifdef ENOSR case ENOSR: #endif PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_open_error(int err) { switch (err) { case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EAGAIN: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case EBUSY: PR_SetError(PR_IO_ERROR, err); break; case EEXIST: PR_SetError(PR_FILE_EXISTS_ERROR, err); break; case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case EIO: PR_SetError(PR_IO_ERROR, err); break; case EISDIR: PR_SetError(PR_IS_DIRECTORY_ERROR, err); break; case ELOOP: PR_SetError(PR_LOOP_ERROR, err); break; case EMFILE: PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err); break; case ENAMETOOLONG: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ENFILE: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case ENODEV: case ENOENT: case ENXIO: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ENOMEM: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ENOSPC: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; #ifdef ENOSR case ENOSR: #endif PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ENOTDIR: PR_SetError(PR_NOT_DIRECTORY_ERROR, err); break; case EPERM: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_REMOTE_FILE_ERROR, err); break; case EROFS: PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_mmap_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EAGAIN: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ENOMEM: PR_SetError(PR_OUT_OF_MEMORY_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_gethostname_error(int err) { switch (err) { case EFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_select_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, err); break; case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_poll_error(int err) { PRErrorCode prerror; switch (err) { case EAGAIN: prerror = PR_INSUFFICIENT_RESOURCES_ERROR; break; case EINVAL: prerror = PR_INVALID_ARGUMENT_ERROR; break; case EFAULT: prerror = PR_ACCESS_FAULT_ERROR; break; default: prerror = PR_UNKNOWN_ERROR; break; } PR_SetError(prerror, err); } void _MD_unix_map_flock_error(int err) { switch (err) { case EBADF: case EINVAL: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EWOULDBLOCK: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_unix_map_lockf_error(int err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EACCES: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case EDEADLK: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } #ifdef HPUX11 void _MD_hpux_map_sendfile_error(int oserror) { PRErrorCode prerror; switch (oserror) { case ENOTSOCK: prerror = PR_NOT_SOCKET_ERROR; break; case EFAULT: prerror = PR_ACCESS_FAULT_ERROR; break; case ENOBUFS: prerror = PR_INSUFFICIENT_RESOURCES_ERROR; break; case EINVAL: prerror = PR_INVALID_ARGUMENT_ERROR; break; case ENOTCONN: prerror = PR_NOT_CONNECTED_ERROR; break; case EPIPE: prerror = PR_CONNECT_RESET_ERROR; break; case ENOMEM: prerror = PR_OUT_OF_MEMORY_ERROR; break; case EOPNOTSUPP: prerror = PR_NOT_TCP_SOCKET_ERROR; break; default: prerror = PR_UNKNOWN_ERROR; } PR_SetError(prerror, oserror); } #endif /* HPUX11 */ nspr-4.11/nspr/pr/src/md/beos/bfile.c0000644000000000000000000004551112623070344015525 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /* ** Global lock variable used to bracket calls into rusty libraries that ** aren't thread safe (like libc, libX, etc). */ static PRLock *_pr_rename_lock = NULL; void _MD_InitIO (void) { } PRStatus _MD_open_dir (_MDDir *md,const char *name) { int err; md->d = opendir(name); if (!md->d) { err = _MD_ERRNO(); _PR_MD_MAP_OPENDIR_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; } char* _MD_read_dir (_MDDir *md, PRIntn flags) { struct dirent *de; int err; for (;;) { /* * XXX: readdir() is not MT-safe */ _MD_ERRNO() = 0; de = readdir(md->d); if (!de) { err = _MD_ERRNO(); _PR_MD_MAP_READDIR_ERROR(err); return 0; } if ((flags & PR_SKIP_DOT) && (de->d_name[0] == '.') && (de->d_name[1] == 0)) continue; if ((flags & PR_SKIP_DOT_DOT) && (de->d_name[0] == '.') && (de->d_name[1] == '.') && (de->d_name[2] == 0)) continue; if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.')) continue; break; } return de->d_name; } PRInt32 _MD_close_dir (_MDDir *md) { int rv = 0, err; if (md->d) { rv = closedir(md->d); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_CLOSEDIR_ERROR(err); } } return(rv); } void _MD_make_nonblock (PRFileDesc *fd) { int blocking = 1; setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking)); } PRStatus _MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable) { int rv; rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC); if (-1 == rv) { PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); return PR_FAILURE; } return PR_SUCCESS; } void _MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported) { if (imported) { fd->secret->inheritable = _PR_TRI_UNKNOWN; } else { int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); if (flags == -1) { PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); return; } fd->secret->inheritable = (flags & FD_CLOEXEC) ? _PR_TRI_TRUE : _PR_TRI_FALSE; } } void _MD_query_fd_inheritable (PRFileDesc *fd) { int flags; PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); PR_ASSERT(-1 != flags); fd->secret->inheritable = (flags & FD_CLOEXEC) ? _PR_TRI_FALSE : _PR_TRI_TRUE; } PRInt32 _MD_open (const char *name, PRIntn flags, PRIntn mode) { PRInt32 osflags; PRInt32 rv, err; if (flags & PR_RDWR) { osflags = O_RDWR; } else if (flags & PR_WRONLY) { osflags = O_WRONLY; } else { osflags = O_RDONLY; } if (flags & PR_EXCL) osflags |= O_EXCL; if (flags & PR_APPEND) osflags |= O_APPEND; if (flags & PR_TRUNCATE) osflags |= O_TRUNC; if (flags & PR_SYNC) { /* Ummmm. BeOS doesn't appear to support sync in any way shape or form. */ return PR_NOT_IMPLEMENTED_ERROR; } /* ** On creations we hold the 'create' lock in order to enforce ** the semantics of PR_Rename. (see the latter for more details) */ if (flags & PR_CREATE_FILE) { osflags |= O_CREAT ; if (NULL !=_pr_rename_lock) PR_Lock(_pr_rename_lock); } rv = open(name, osflags, mode); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_OPEN_ERROR(err); } if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock)) PR_Unlock(_pr_rename_lock); return rv; } PRInt32 _MD_close_file (PRInt32 osfd) { PRInt32 rv, err; rv = close(osfd); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_CLOSE_ERROR(err); } return(rv); } PRInt32 _MD_read (PRFileDesc *fd, void *buf, PRInt32 amount) { PRInt32 rv, err; PRInt32 osfd = fd->secret->md.osfd; rv = read( osfd, buf, amount ); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_READ_ERROR(err); } return(rv); } PRInt32 _MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount) { PRInt32 rv, err; PRInt32 osfd = fd->secret->md.osfd; rv = write( osfd, buf, amount ); if( rv < 0 ) { err = _MD_ERRNO(); _PR_MD_MAP_WRITE_ERROR(err); } return( rv ); } #ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */ PRInt32 _MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { return PR_NOT_IMPLEMENTED_ERROR; } #endif PRInt32 _MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence) { PRInt32 rv, err; rv = lseek (fd->secret->md.osfd, offset, whence); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_LSEEK_ERROR(err); } return( rv ); } PRInt64 _MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence) { PRInt32 rv, err; /* According to the BeOS headers, lseek accepts a * variable of type off_t for the offset, and off_t * is defined to be a 64-bit value. So no special * cracking needs to be done on "offset". */ rv = lseek (fd->secret->md.osfd, offset, whence); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_LSEEK_ERROR(err); } return( rv ); } PRInt32 _MD_fsync (PRFileDesc *fd) { PRInt32 rv, err; rv = fsync(fd->secret->md.osfd); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_FSYNC_ERROR(err); } return(rv); } PRInt32 _MD_delete (const char *name) { PRInt32 rv, err; rv = unlink(name); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_UNLINK_ERROR(err); } return (rv); } PRInt32 _MD_getfileinfo (const char *fn, PRFileInfo *info) { struct stat sb; PRInt32 rv, err; PRInt64 s, s2us; rv = stat(fn, &sb); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_STAT_ERROR(err); } else if (info) { if (S_IFREG & sb.st_mode) info->type = PR_FILE_FILE; else if (S_IFDIR & sb.st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; /* Must truncate file size for the 32 bit version */ info->size = (sb.st_size & 0xffffffff); LL_I2L(s, sb.st_mtime); LL_I2L(s2us, PR_USEC_PER_SEC); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb.st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } return rv; } PRInt32 _MD_getfileinfo64 (const char *fn, PRFileInfo64 *info) { struct stat sb; PRInt32 rv, err; PRInt64 s, s2us; rv = stat(fn, &sb); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_STAT_ERROR(err); } else if (info) { if (S_IFREG & sb.st_mode) info->type = PR_FILE_FILE; else if (S_IFDIR & sb.st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; /* For the 64 bit version we can use * the native st_size without modification */ info->size = sb.st_size; LL_I2L(s, sb.st_mtime); LL_I2L(s2us, PR_USEC_PER_SEC); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb.st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } return rv; } PRInt32 _MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info) { struct stat sb; PRInt64 s, s2us; PRInt32 rv, err; rv = fstat(fd->secret->md.osfd, &sb); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_FSTAT_ERROR(err); } else if (info) { if (info) { if (S_IFREG & sb.st_mode) info->type = PR_FILE_FILE ; else if (S_IFDIR & sb.st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; /* Use lower 32 bits of file size */ info->size = ( sb.st_size & 0xffffffff); LL_I2L(s, sb.st_mtime); LL_I2L(s2us, PR_USEC_PER_SEC); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb.st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } } return rv; } PRInt32 _MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info) { struct stat sb; PRInt64 s, s2us; PRInt32 rv, err; rv = fstat(fd->secret->md.osfd, &sb); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_FSTAT_ERROR(err); } else if (info) { if (info) { if (S_IFREG & sb.st_mode) info->type = PR_FILE_FILE ; else if (S_IFDIR & sb.st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; info->size = sb.st_size; LL_I2L(s, sb.st_mtime); LL_I2L(s2us, PR_USEC_PER_SEC); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb.st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } } return rv; } PRInt32 _MD_rename (const char *from, const char *to) { PRInt32 rv = -1, err; /* ** This is trying to enforce the semantics of WINDOZE' rename ** operation. That means one is not allowed to rename over top ** of an existing file. Holding a lock across these two function ** and the open function is known to be a bad idea, but .... */ if (NULL != _pr_rename_lock) PR_Lock(_pr_rename_lock); if (0 == access(to, F_OK)) PR_SetError(PR_FILE_EXISTS_ERROR, 0); else { rv = rename(from, to); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_RENAME_ERROR(err); } } if (NULL != _pr_rename_lock) PR_Unlock(_pr_rename_lock); return rv; } PRInt32 _MD_access (const char *name, PRIntn how) { PRInt32 rv, err; int checkFlags; struct stat buf; switch (how) { case PR_ACCESS_WRITE_OK: checkFlags = S_IWUSR | S_IWGRP | S_IWOTH; break; case PR_ACCESS_READ_OK: checkFlags = S_IRUSR | S_IRGRP | S_IROTH; break; case PR_ACCESS_EXISTS: /* we don't need to examine st_mode. */ break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } rv = stat(name, &buf); if (rv == 0 && how != PR_ACCESS_EXISTS && (!(buf.st_mode & checkFlags))) { PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0); return -1; } if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_STAT_ERROR(err); } return(rv); } PRInt32 _MD_stat (const char *name, struct stat *buf) { return PR_NOT_IMPLEMENTED_ERROR; } PRInt32 _MD_mkdir (const char *name, PRIntn mode) { status_t rv; int err; /* ** This lock is used to enforce rename semantics as described ** in PR_Rename. Look there for more fun details. */ if (NULL !=_pr_rename_lock) PR_Lock(_pr_rename_lock); rv = mkdir(name, mode); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_MKDIR_ERROR(err); } if (NULL !=_pr_rename_lock) PR_Unlock(_pr_rename_lock); return rv; } PRInt32 _MD_rmdir (const char *name) { int rv, err; rv = rmdir(name); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_RMDIR_ERROR(err); } return rv; } PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { PRInt32 rv = 0; PRThread *me = _PR_MD_CURRENT_THREAD(); /* * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL(). */ fd_set rd, wt, ex; PRFileDesc *bottom; PRPollDesc *pd, *epd; PRInt32 maxfd = -1, ready, err; PRIntervalTime remaining, elapsed, start; struct timeval tv, *tvp = NULL; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (0 == npds) { PR_Sleep(timeout); return rv; } FD_ZERO(&rd); FD_ZERO(&wt); FD_ZERO(&ex); ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one's ready right now */ if (0 == ready) { /* * We will have to return without calling the * system poll/select function. So zero the * out_flags fields of all the poll descriptors * before this one. */ PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; pd->out_flags = out_flags_read | out_flags_write; } else { pd->out_flags = 0; /* pre-condition */ /* make sure this is an NSPR supported stack */ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { PRInt32 osfd = bottom->secret->md.osfd; if (osfd > maxfd) maxfd = osfd; if (in_flags_read & PR_POLL_READ) { pd->out_flags |= _PR_POLL_READ_SYS_READ; FD_SET(osfd, &rd); } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; FD_SET(osfd, &wt); } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; FD_SET(osfd, &rd); } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; FD_SET(osfd, &wt); } if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); } } else { if (0 == ready) { PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pd->out_flags = PR_POLL_NVAL; /* bogii */ } } } else { pd->out_flags = 0; } } if (0 != ready) return ready; /* no need to block */ remaining = timeout; start = PR_IntervalNow(); retry: if (timeout != PR_INTERVAL_NO_TIMEOUT) { PRInt32 ticksPerSecond = PR_TicksPerSecond(); tv.tv_sec = remaining / ticksPerSecond; tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); tvp = &tv; } ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp); if (ready == -1 && errno == EINTR) { if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; else { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) ready = 0; /* timed out */ else { remaining = timeout - elapsed; goto retry; } } } /* ** Now to unravel the select sets back into the client's poll ** descriptor list. Is this possibly an area for pissing away ** a few cycles or what? */ if (ready > 0) { ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { PRInt32 osfd; bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); osfd = bottom->secret->md.osfd; if (FD_ISSET(osfd, &rd)) { if (pd->out_flags & _PR_POLL_READ_SYS_READ) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) out_flags |= PR_POLL_WRITE; } if (FD_ISSET(osfd, &wt)) { if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) out_flags |= PR_POLL_WRITE; } if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; /* Workaround for nonblocking connects under net_server */ #ifndef BONE_VERSION if (out_flags) { /* check if it is a pending connect */ int i = 0, j = 0; PR_Lock( _connectLock ); for( i = 0; i < connectCount; i++ ) { if(connectList[i].osfd == osfd) { int connectError; int connectResult; connectResult = connect(connectList[i].osfd, &connectList[i].addr, connectList[i].addrlen); connectError = errno; if(connectResult < 0 ) { if(connectError == EINTR || connectError == EWOULDBLOCK || connectError == EINPROGRESS || connectError == EALREADY) { break; } } if(i == (connectCount - 1)) { connectList[i].osfd = -1; } else { for(j = i; j < connectCount; j++ ) { memcpy( &connectList[j], &connectList[j+1], sizeof(connectList[j])); } } connectCount--; bottom->secret->md.connectReturnValue = connectResult; bottom->secret->md.connectReturnError = connectError; bottom->secret->md.connectValueValid = PR_TRUE; break; } } PR_Unlock( _connectLock ); } #endif } pd->out_flags = out_flags; if (out_flags) ready++; } PR_ASSERT(ready > 0); } else if (ready < 0) { err = _MD_ERRNO(); if (err == EBADF) { /* Find the bad fds */ ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { pd->out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) { pd->out_flags = PR_POLL_NVAL; ready++; } } } PR_ASSERT(ready > 0); } else _PR_MD_MAP_SELECT_ERROR(err); } return ready; } /* _MD_pr_poll */ /* * File locking. */ PRStatus _MD_lockfile (PRInt32 osfd) { PRInt32 rv; struct flock linfo; linfo.l_type = linfo.l_whence = SEEK_SET; linfo.l_start = 0; linfo.l_len = 0; rv = fcntl(osfd, F_SETLKW, &linfo); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_tlockfile (PRInt32 osfd) { PRInt32 rv; struct flock linfo; linfo.l_type = linfo.l_whence = SEEK_SET; linfo.l_start = 0; linfo.l_len = 0; rv = fcntl(osfd, F_SETLK, &linfo); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_unlockfile (PRInt32 osfd) { PRInt32 rv; struct flock linfo; linfo.l_type = linfo.l_whence = SEEK_SET; linfo.l_start = 0; linfo.l_len = 0; rv = fcntl(osfd, F_UNLCK, &linfo); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } nspr-4.11/nspr/pr/src/md/beos/bmemory.c0000644000000000000000000000070112623070344016106 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" PR_EXTERN(void) _PR_MD_INIT_SEGS(void); PR_EXTERN(PRStatus) _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr); PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSegment *seg); nspr-4.11/nspr/pr/src/md/beos/bmisc.c0000644000000000000000000000326712623070344015543 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include PRLock *_connectLock = NULL; #ifndef BONE_VERSION /* Workaround for nonblocking connects under net_server */ PRUint32 connectCount = 0; ConnectListNode connectList[64]; #endif void _MD_cleanup_before_exit (void) { } void _MD_exit (PRIntn status) { exit(status); } void _MD_early_init (void) { } static PRLock *monitor = NULL; void _MD_final_init (void) { _connectLock = PR_NewLock(); PR_ASSERT(NULL != _connectLock); #ifndef BONE_VERSION /* Workaround for nonblocking connects under net_server */ connectCount = 0; #endif } void _MD_AtomicInit (void) { if (monitor == NULL) { monitor = PR_NewLock(); } } /* ** This is exceedingly messy. atomic_add returns the last value, NSPR expects the new value. ** We just add or subtract 1 from the result. The actual memory update is atomic. */ PRInt32 _MD_AtomicAdd( PRInt32 *ptr, PRInt32 val ) { return( ( atomic_add( (long *)ptr, val ) ) + val ); } PRInt32 _MD_AtomicIncrement( PRInt32 *val ) { return( ( atomic_add( (long *)val, 1 ) ) + 1 ); } PRInt32 _MD_AtomicDecrement( PRInt32 *val ) { return( ( atomic_add( (long *)val, -1 ) ) - 1 ); } PRInt32 _MD_AtomicSet( PRInt32 *val, PRInt32 newval ) { PRInt32 rv; if (!_pr_initialized) { _PR_ImplicitInitialization(); } PR_Lock(monitor); rv = *val; *val = newval; PR_Unlock(monitor); return rv; } nspr-4.11/nspr/pr/src/md/beos/bmmap.c0000644000000000000000000000170312623070344015533 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" PR_EXTERN(PRStatus) _PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } PR_EXTERN(PRInt32) _PR_MD_GET_MEM_MAP_ALIGNMENT(void) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return -1; } PR_EXTERN(void *) _PR_MD_MEM_MAP(PRFileMap *fmap, PRInt64 offset, PRUint32 len) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return 0; } PR_EXTERN(PRStatus) _PR_MD_MEM_UNMAP(void *addr, PRUint32 size) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } PR_EXTERN(PRStatus) _PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } nspr-4.11/nspr/pr/src/md/beos/bnet.c0000644000000000000000000006040612623070344015374 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include #include #include #include #include /* * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or * PRInt32* pointer to a _PRSockLen_t* pointer. */ #define _PRSockLen_t int /* ** Global lock variable used to bracket calls into rusty libraries that ** aren't thread safe (like libc, libX, etc). */ static PRLock *_pr_rename_lock = NULL; static PRMonitor *_pr_Xfe_mon = NULL; #define READ_FD 1 #define WRITE_FD 2 /* ** This is a support routine to handle "deferred" i/o on sockets. ** It uses "select", so it is subject to all of the BeOS limitations ** (only READ notification, only sockets) */ /* * socket_io_wait -- * * wait for socket i/o, periodically checking for interrupt * */ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout) { PRInt32 rv = -1; struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRInt32 syserror; fd_set rd_wr; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; FD_ZERO(&rd_wr); do { FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { #ifdef BONE_VERSION _PR_MD_MAP_SELECT_ERROR(syserror); #else if (syserror == EBADF) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF); } else { PR_SetError(PR_UNKNOWN_ERROR, syserror); } #endif break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; default: now = epoch = PR_IntervalNow(); remaining = timeout; FD_ZERO(&rd_wr); do { /* * We block in _MD_SELECT for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { tv.tv_usec = PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); } FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); /* * we don't consider EINTR a real error */ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { #ifdef BONE_VERSION _PR_MD_MAP_SELECT_ERROR(syserror); #else if (syserror == EBADF) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF); } else { PR_SetError(PR_UNKNOWN_ERROR, syserror); } #endif break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * We loop again if _MD_SELECT timed out or got interrupted * by a signal, and the timeout deadline has not passed yet. */ if (rv == 0 || (rv == -1 && syserror == EINTR)) { /* * If _MD_SELECT timed out, we know how much time * we spent in blocking, so we can avoid a * PR_IntervalNow() call. */ if (rv == 0) { if (wait_for_remaining) { now += remaining; } else { now += PR_SecondsToInterval(tv.tv_sec) + PR_MicrosecondsToInterval(tv.tv_usec); } } else { now = PR_IntervalNow(); } elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = timeout - elapsed; } } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; } return(rv); } PRInt32 _MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifndef BONE_VERSION if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) { _PR_MD_MAP_RECV_ERROR(EPIPE); return -1; } #endif #ifdef BONE_VERSION /* ** Gah, stupid hack. If reading a zero amount, instantly return success. ** BONE beta 6 returns EINVAL for reads of zero bytes, which parts of ** mozilla use to check for socket availability. */ if( 0 == amount ) return(0); #endif while ((rv = recv(osfd, buf, amount, flags)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } /* If socket was supposed to be blocking, wait a while for the condition to be satisfied. */ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else break; } if (rv < 0) { _PR_MD_MAP_RECV_ERROR(err); } done: return(rv); } PRInt32 _MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((*addrlen = PR_NETADDR_SIZE(addr)), ((rv = recvfrom(osfd, buf, amount, flags, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECVFROM_ERROR(err); } done: #ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv); } PRInt32 _MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifndef BONE_VERSION if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE) { _PR_MD_MAP_SEND_ERROR(EPIPE); return -1; } #endif while ((rv = send(osfd, buf, amount, flags)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } #ifndef BONE_VERSION if( _PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } /* in UNIX implementations, you could do a socket_io_wait here. * but since BeOS doesn't yet support WRITE notification in select, * you're spanked. */ snooze( 10000L ); continue; #else /* BONE_VERSION */ if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) goto done; #endif } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { continue; } else { break; } } #ifdef BONE_VERSION /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next writev() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { rv = -1; goto done; } } #endif /* BONE_VERSION */ if (rv < 0) { _PR_MD_MAP_SEND_ERROR(err); } #ifdef BONE_VERSION done: #endif return(rv); } PRInt32 _MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) &addrCopy, addrlen)) == -1) { #else while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) addr, addrlen)) == -1) { #endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } #ifdef BONE_VERSION if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) goto done; #endif } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_SENDTO_ERROR(err); } #ifdef BONE_VERSION done: #endif return(rv); } #ifdef BONE_VERSION PRInt32 _MD_writev( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 index, amount = 0; PRInt32 osfd = fd->secret->md.osfd; struct iovec osiov[PR_MAX_IOVECTOR_SIZE]; /* Ensured by PR_Writev */ PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE); /* * We can't pass iov to writev because PRIOVec and struct iovec * may not be binary compatible. Make osiov a copy of iov and * pass osiov to writev. */ for (index = 0; index < iov_size; index++) { osiov[index].iov_base = iov[index].iov_base; osiov[index].iov_len = iov[index].iov_len; } /* * Calculate the total number of bytes to be sent; needed for * optimization later. * We could avoid this if this number was passed in; but it is * probably not a big deal because iov_size is usually small (less than * 3) */ if (!fd->secret->nonblocking) { for (index=0; indexsecret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next writev() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { rv = -1; goto done; } } if (rv < 0) { _PR_MD_MAP_WRITEV_ERROR(err); } done: return(rv); } #endif /* BONE_VERSION */ PRInt32 _MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = accept(osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } /* If it's SUPPOSED to be a blocking thread, wait * a while to see if the triggering condition gets * satisfied. */ /* Assume that we're always using a native thread */ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) { continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_ACCEPT_ERROR(err); } else if (addr != NULL) { /* bug 134099 */ err = getpeername(rv, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); } done: #ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { /* Mask off the first byte of struct sockaddr (the length field) */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv); } PRInt32 _MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 osfd = fd->secret->md.osfd; #ifndef BONE_VERSION fd->secret->md.connectValueValid = PR_FALSE; #endif #ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; #endif /* (Copied from unix.c) * We initiate the connection setup by making a nonblocking connect() * call. If the connect() call fails, there are two cases we handle * specially: * 1. The connect() call was interrupted by a signal. In this case * we simply retry connect(). * 2. The NSPR socket is nonblocking and connect() fails with * EINPROGRESS. We first wait until the socket becomes writable. * Then we try to find out whether the connection setup succeeded * or failed. */ retry: #ifdef _PR_HAVE_SOCKADDR_LEN if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) { #else if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) { #endif err = _MD_ERRNO(); #ifndef BONE_VERSION fd->secret->md.connectReturnValue = rv; fd->secret->md.connectReturnError = err; fd->secret->md.connectValueValid = PR_TRUE; #endif if( err == EINTR ) { if( _PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } #ifndef BONE_VERSION snooze( 100000L ); #endif goto retry; } #ifndef BONE_VERSION if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) { /* ** There's no timeout on this connect, but that's not ** a big deal, since the connect times out anyways ** after 30 seconds. Just sleep for 1/10th of a second ** and retry until we go through or die. */ if( _PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } goto retry; } if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) { PR_Lock(_connectLock); if (connectCount < sizeof(connectList)/sizeof(connectList[0])) { connectList[connectCount].osfd = osfd; memcpy(&connectList[connectCount].addr, addr, addrlen); connectList[connectCount].addrlen = addrlen; connectList[connectCount].timeout = timeout; connectCount++; PR_Unlock(_connectLock); _PR_MD_MAP_CONNECT_ERROR(err); } else { PR_Unlock(_connectLock); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } return rv; } #else /* BONE_VERSION */ if(!fd->secret->nonblocking && (err == EINTR)) { rv = socket_io_wait(osfd, WRITE_FD, timeout); if (rv == -1) { return -1; } PR_ASSERT(rv == 1); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } err = _MD_beos_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return -1; } return 0; } #endif _PR_MD_MAP_CONNECT_ERROR(err); } return rv; } PRInt32 _MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv, err; #ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen); #else rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); #endif if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_BIND_ERROR(err); } return(rv); } PRInt32 _MD_listen (PRFileDesc *fd, PRIntn backlog) { PRInt32 rv, err; #ifndef BONE_VERSION /* Bug workaround! Setting listen to 0 on Be accepts no connections. ** On most UN*Xes this sets the default. */ if( backlog == 0 ) backlog = 5; #endif rv = listen(fd->secret->md.osfd, backlog); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_LISTEN_ERROR(err); } return(rv); } PRInt32 _MD_shutdown (PRFileDesc *fd, PRIntn how) { PRInt32 rv, err; #ifndef BONE_VERSION if (how == PR_SHUTDOWN_SEND) fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE; else if (how == PR_SHUTDOWN_RCV) fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ; else if (how == PR_SHUTDOWN_BOTH) { fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ); } return 0; #else /* BONE_VERSION */ rv = shutdown(fd->secret->md.osfd, how); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SHUTDOWN_ERROR(err); } return(rv); #endif } PRInt32 _MD_socketpair (int af, int type, int flags, PRInt32 *osfd) { return PR_NOT_IMPLEMENTED_ERROR; } PRInt32 _MD_close_socket (PRInt32 osfd) { #ifdef BONE_VERSION close( osfd ); #else closesocket( osfd ); #endif } PRStatus _MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 rv, err; rv = getsockname(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); #ifdef _PR_HAVE_SOCKADDR_LEN if (rv == 0) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 rv, err; rv = getpeername(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); #ifdef _PR_HAVE_SOCKADDR_LEN if (rv == 0) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETPEERNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_getsockopt (PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) { PRInt32 rv, err; rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_setsockopt (PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen) { PRInt32 rv, err; rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRInt32 _MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { return PR_NOT_IMPLEMENTED_ERROR; } #ifndef BONE_VERSION PRInt32 _MD_socket (int af, int type, int flags) { PRInt32 osfd, err; osfd = socket( af, type, 0 ); if( -1 == osfd ) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKET_ERROR( err ); } return( osfd ); } #else PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { PRInt32 osfd, err; osfd = socket(domain, type, proto); if (osfd == -1) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKET_ERROR(err); } return(osfd); } #endif PRInt32 _MD_socketavailable (PRFileDesc *fd) { #ifdef BONE_VERSION PRInt32 result; if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) { _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO()); return -1; } return result; #else return PR_NOT_IMPLEMENTED_ERROR; #endif } PRInt32 _MD_get_socket_error (void) { return PR_NOT_IMPLEMENTED_ERROR; } PRStatus _MD_gethostname (char *name, PRUint32 namelen) { PRInt32 rv, err; rv = gethostname(name, namelen); if (rv == 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETHOSTNAME_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; } #ifndef BONE_VERSION PRInt32 _MD_beos_get_nonblocking_connect_error(PRFileDesc *fd) { int rv; int flags = 0; rv = recv(fd->secret->md.osfd, NULL, 0, flags); PR_ASSERT(-1 == rv || 0 == rv); if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) { return errno; } return 0; /* no error */ } #else PRInt32 _MD_beos_get_nonblocking_connect_error(int osfd) { return PR_NOT_IMPLEMENTED_ERROR; // int err; // _PRSockLen_t optlen = sizeof(err); // if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) { // return errno; // } else { // return err; // } } #endif /* BONE_VERSION */ nspr-4.11/nspr/pr/src/md/beos/bproc.c0000644000000000000000000001153712623070344015552 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #define _PR_SIGNALED_EXITSTATUS 256 PRProcess* _MD_create_process (const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { PRProcess *process; int nEnv, idx; char *const *childEnvp; char **newEnvp = NULL; int flags; PRBool found = PR_FALSE; process = PR_NEW(PRProcess); if (!process) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } childEnvp = envp; if (attr && attr->fdInheritBuffer) { if (NULL == childEnvp) { childEnvp = environ; } for (nEnv = 0; childEnvp[nEnv]; nEnv++) { } newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *)); if (NULL == newEnvp) { PR_DELETE(process); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } for (idx = 0; idx < nEnv; idx++) { newEnvp[idx] = childEnvp[idx]; if (!found && !strncmp(newEnvp[idx], "NSPR_INHERIT_FDS=", 17)) { newEnvp[idx] = attr->fdInheritBuffer; found = PR_TRUE; } } if (!found) { newEnvp[idx++] = attr->fdInheritBuffer; } newEnvp[idx] = NULL; childEnvp = newEnvp; } process->md.pid = fork(); if ((pid_t) -1 == process->md.pid) { PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno); PR_DELETE(process); if (newEnvp) { PR_DELETE(newEnvp); } return NULL; } else if (0 == process->md.pid) { /* the child process */ /* * If the child process needs to exit, it must call _exit(). * Do not call exit(), because exit() will flush and close * the standard I/O file descriptors, and hence corrupt * the parent process's standard I/O data structures. */ if (attr) { /* the osfd's to redirect stdin, stdout, and stderr to */ int in_osfd = -1, out_osfd = -1, err_osfd = -1; if (attr->stdinFd && attr->stdinFd->secret->md.osfd != 0) { in_osfd = attr->stdinFd->secret->md.osfd; if (dup2(in_osfd, 0) != 0) { _exit(1); /* failed */ } flags = fcntl(0, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(0, F_SETFL, flags & ~O_NONBLOCK); } } if (attr->stdoutFd && attr->stdoutFd->secret->md.osfd != 1) { out_osfd = attr->stdoutFd->secret->md.osfd; if (dup2(out_osfd, 1) != 1) { _exit(1); /* failed */ } flags = fcntl(1, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(1, F_SETFL, flags & ~O_NONBLOCK); } } if (attr->stderrFd && attr->stderrFd->secret->md.osfd != 2) { err_osfd = attr->stderrFd->secret->md.osfd; if (dup2(err_osfd, 2) != 2) { _exit(1); /* failed */ } flags = fcntl(2, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(2, F_SETFL, flags & ~O_NONBLOCK); } } if (in_osfd != -1) { close(in_osfd); } if (out_osfd != -1 && out_osfd != in_osfd) { close(out_osfd); } if (err_osfd != -1 && err_osfd != in_osfd && err_osfd != out_osfd) { close(err_osfd); } if (attr->currentDirectory) { if (chdir(attr->currentDirectory) < 0) { _exit(1); /* failed */ } } } if (childEnvp) { (void)execve(path, argv, childEnvp); } else { /* Inherit the environment of the parent. */ (void)execv(path, argv); } /* Whoops! It returned. That's a bad sign. */ _exit(1); } if (newEnvp) { PR_DELETE(newEnvp); } return process; } PRStatus _MD_detach_process (PRProcess *process) { /* If we kept a process table like unix does, * we'd remove the entry here. * Since we dont', just delete the process variable */ PR_DELETE(process); return PR_SUCCESS; } PRStatus _MD_wait_process (PRProcess *process, PRInt32 *exitCode) { PRStatus retVal = PR_SUCCESS; int ret, status; /* Ignore interruptions */ do { ret = waitpid(process->md.pid, &status, 0); } while (ret == -1 && errno == EINTR); /* * waitpid() cannot return 0 because we did not invoke it * with the WNOHANG option. */ PR_ASSERT(0 != ret); if (ret < 0) { PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); return PR_FAILURE; } /* If child process exited normally, return child exit code */ if (WIFEXITED(status)) { *exitCode = WEXITSTATUS(status); } else { PR_ASSERT(WIFSIGNALED(status)); *exitCode = _PR_SIGNALED_EXITSTATUS; } PR_DELETE(process); return PR_SUCCESS; } PRStatus _MD_kill_process (PRProcess *process) { PRErrorCode prerror; PRInt32 oserror; if (kill(process->md.pid, SIGKILL) == 0) { return PR_SUCCESS; } oserror = errno; switch (oserror) { case EPERM: prerror = PR_NO_ACCESS_RIGHTS_ERROR; break; case ESRCH: prerror = PR_INVALID_ARGUMENT_ERROR; break; default: prerror = PR_UNKNOWN_ERROR; break; } PR_SetError(prerror, oserror); return PR_FAILURE; } nspr-4.11/nspr/pr/src/md/beos/brng.c0000644000000000000000000000176012623070344015372 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include "primpl.h" extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size ) { struct timeval tv; int n = 0; int s; GETTIMEOFDAY(&tv); if ( size > 0 ) { s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec)); size -= s; n += s; } if ( size > 0 ) { s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec)); size -= s; n += s; } return n; } /* end _PR_MD_GetRandomNoise() */ nspr-4.11/nspr/pr/src/md/beos/bseg.c0000644000000000000000000000100012623070344015345 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" PR_IMPLEMENT(void) _MD_init_segs (void) { } PR_IMPLEMENT(PRStatus) _MD_alloc_segment (PRSegment *seg, PRUint32 size, void *vaddr) { return PR_NOT_IMPLEMENTED_ERROR; } PR_IMPLEMENT(void) _MD_free_segment (PRSegment *seg) { } nspr-4.11/nspr/pr/src/md/beos/bsrcs.mk0000644000000000000000000000107312623070344015740 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # this file lists the source files to be compiled (used in Makefile) and # then enumerated as object files (in objs.mk) for inclusion in the NSPR # shared library MDCSRCS = \ beos.c \ beos_errors.c \ bfile.c \ bmisc.c \ bnet.c \ bproc.c \ brng.c \ bseg.c \ btime.c \ bmmap.c \ $(NULL) nspr-4.11/nspr/pr/src/md/beos/btime.c0000644000000000000000000000160212623070344015535 0ustar 00000000000000/* -*- Mode: C++; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include static bigtime_t start; PRTime _MD_now (void) { return (PRTime)real_time_clock_usecs(); } void _MD_interval_init (void) { /* grab the base interval time */ start = real_time_clock_usecs(); } PRIntervalTime _MD_get_interval (void) { return( (PRIntervalTime) real_time_clock_usecs() / 10 ); #if 0 /* return the number of tens of microseconds that have elapsed since we were initialized */ bigtime_t now = real_time_clock_usecs(); now -= start; now /= 10; return (PRIntervalTime)now; #endif } PRIntervalTime _MD_interval_per_sec (void) { return 100000L; } nspr-4.11/nspr/pr/src/md/beos/objs.mk0000644000000000000000000000064712623070344015567 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # This makefile appends to the variable OBJS the platform-dependent # object modules that will be part of the nspr20 library. include $(srcdir)/md/beos/bsrcs.mk OBJS += $(MDCSRCS:%.c=md/beos/$(OBJDIR)/%.$(OBJ_SUFFIX)) nspr-4.11/nspr/pr/src/md/os2/.cvsignore0000644000000000000000000000001112623070344016035 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/md/os2/Makefile.in0000644000000000000000000000151612623070344016115 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifeq ($(OS_TARGET), OS2) CSRCS = \ os2misc.c \ os2sem.c \ os2inrval.c \ os2gc.c \ os2thred.c \ os2io.c \ os2cv.c \ os2sock.c \ os2_errors.c \ os2poll.c \ os2rng.c \ $(NULL) endif ASFILES = os2emx.s os2vaclegacy.s TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/md/os2/objs.mk0000644000000000000000000000130012623070344015325 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # This makefile appends to the variable OBJS the platform-dependent # object modules that will be part of the nspr20 library. CSRCS = \ os2io.c \ os2sock.c \ os2thred.c \ os2cv.c \ os2gc.c \ os2misc.c \ os2inrval.c \ os2sem.c \ os2_errors.c \ os2poll.c \ os2rng.c \ $(NULL) ASFILES = os2emx.s os2vaclegacy.s OBJS += $(addprefix md/os2/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \ $(addprefix md/os2/$(OBJDIR)/,$(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))) nspr-4.11/nspr/pr/src/md/os2/os2_errors.c0000644000000000000000000006053212623070344016316 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prerror.h" #include "primpl.h" void _MD_os2_map_default_error(PRInt32 err) { switch (err) { case EWOULDBLOCK: PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case EMSGSIZE: case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ERROR_NETNAME_DELETED: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_opendir_error(PRInt32 err) { switch (err) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_ADDRESS: case ERROR_INVALID_ACCESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_INVALID_NAME: case ERROR_INVALID_PARAMETER: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ERROR_TOO_MANY_OPEN_FILES: case ERROR_NOT_DOS_DISK: case ERROR_NOT_READY: case ERROR_OPEN_FAILED: case ERROR_PATH_BUSY: case ERROR_CANNOT_MAKE: PR_SetError(PR_IO_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_DEVICE_IN_USE: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_FILENAME_EXCED_RANGE: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_SHARING_BUFFER_EXCEEDED: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_closedir_error(PRInt32 err) { switch (err) { case ERROR_FILE_NOT_FOUND: case ERROR_ACCESS_DENIED: case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_readdir_error(PRInt32 err) { switch (err) { case ERROR_NO_MORE_FILES: PR_SetError(PR_NO_MORE_FILES_ERROR, err); break; case ERROR_FILE_NOT_FOUND: case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_NOT_DOS_DISK: case ERROR_LOCK_VIOLATION: case ERROR_BROKEN_PIPE: case ERROR_NOT_READY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_delete_error(PRInt32 err) { switch (err) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_ACCESS_DENIED: case ERROR_WRITE_PROTECT: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_LOCKED: case ERROR_SHARING_VIOLATION: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } /* The error code for stat() is in errno. */ void _MD_os2_map_stat_error(PRInt32 err) { switch (err) { case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); } } void _MD_os2_map_fstat_error(PRInt32 err) { switch (err) { case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_LOCKED: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_rename_error(PRInt32 err) { switch (err) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_INVALID_NAME: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_DRIVE_LOCKED: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_FILENAME_EXCED_RANGE: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: PR_SetError(PR_FILE_EXISTS_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } /* The error code for access() is in errno. */ void _MD_os2_map_access_error(PRInt32 err) { switch (err) { case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); } } void _MD_os2_map_mkdir_error(PRInt32 err) { switch (err) { case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: PR_SetError(PR_FILE_EXISTS_ERROR, err); break; case ERROR_FILE_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_INVALID_NAME: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_DRIVE_LOCKED: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_FILENAME_EXCED_RANGE: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ERROR_TOO_MANY_OPEN_FILES: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_DISK_FULL: case ERROR_HANDLE_DISK_FULL: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; case ERROR_WRITE_PROTECT: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_rmdir_error(PRInt32 err) { switch (err) { case ERROR_FILE_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_INVALID_NAME: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_DRIVE_LOCKED: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_FILENAME_EXCED_RANGE: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ERROR_TOO_MANY_OPEN_FILES: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_WRITE_PROTECT: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_read_error(PRInt32 err) { switch (err) { case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_LOCKED: case ERROR_SHARING_VIOLATION: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_NETNAME_DELETED: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_transmitfile_error(PRInt32 err) { switch (err) { case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_LOCKED: case ERROR_SHARING_VIOLATION: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_FILENAME_EXCED_RANGE: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ERROR_TOO_MANY_OPEN_FILES: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_write_error(PRInt32 err) { switch (err) { case ERROR_ACCESS_DENIED: case ERROR_WRITE_PROTECT: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_LOCKED: case ERROR_SHARING_VIOLATION: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: case ERROR_DISK_FULL: case ERROR_HANDLE_DISK_FULL: case ENOSPC: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; case ERROR_NETNAME_DELETED: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case EMSGSIZE: case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_lseek_error(PRInt32 err) { switch (err) { case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_SEEK_ON_DEVICE: PR_SetError(PR_IO_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_fsync_error(PRInt32 err) { switch (err) { case ERROR_ACCESS_DENIED: case ERROR_WRITE_PROTECT: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_DISK_FULL: case ERROR_HANDLE_DISK_FULL: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_close_error(PRInt32 err) { switch (err) { case ERROR_INVALID_HANDLE: case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_NOT_READY: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_socket_error(PRInt32 err) { switch (err) { case EPROTONOSUPPORT: PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_recv_error(PRInt32 err) { switch (err) { case EWOULDBLOCK: PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ERROR_NETNAME_DELETED: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_recvfrom_error(PRInt32 err) { switch (err) { case EWOULDBLOCK: PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ERROR_NETNAME_DELETED: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_send_error(PRInt32 err) { switch (err) { case EWOULDBLOCK: PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case EMSGSIZE: case EINVAL: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ERROR_NETNAME_DELETED: PR_SetError(PR_CONNECT_RESET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_sendto_error(PRInt32 err) { _MD_os2_map_default_error(err); } void _MD_os2_map_writev_error(int err) { _MD_os2_map_default_error(err); } void _MD_os2_map_accept_error(PRInt32 err) { _MD_os2_map_default_error(err); } void _MD_os2_map_acceptex_error(PRInt32 err) { switch (err) { case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } /* * An error code of 0 means that the nonblocking connect succeeded. */ int _MD_os2_get_nonblocking_connect_error(int osfd) { int err; int len = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == -1) { return sock_errno(); } else { return err; } } void _MD_os2_map_connect_error(PRInt32 err) { switch (err) { case EWOULDBLOCK: PR_SetError(PR_WOULD_BLOCK_ERROR, err); break; case EINPROGRESS: PR_SetError(PR_IN_PROGRESS_ERROR, err); break; case EALREADY: case EINVAL: PR_SetError(PR_ALREADY_INITIATED_ERROR, err); break; case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case EADDRNOTAVAIL: PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case EAFNOSUPPORT: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; case ETIMEDOUT: PR_SetError(PR_IO_TIMEOUT_ERROR, err); break; case ECONNREFUSED: PR_SetError(PR_CONNECT_REFUSED_ERROR, err); break; case ENETUNREACH: PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err); break; case EADDRINUSE: PR_SetError(PR_ADDRESS_IN_USE_ERROR, err); break; case EISCONN: PR_SetError(PR_IS_CONNECTED_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_bind_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case EADDRNOTAVAIL: PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err); break; case EADDRINUSE: PR_SetError(PR_ADDRESS_IN_USE_ERROR, err); break; case EACCES: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case EINVAL: PR_SetError(PR_SOCKET_ADDRESS_IS_BOUND_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_listen_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case EOPNOTSUPP: PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_shutdown_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case ENOTCONN: PR_SetError(PR_NOT_CONNECTED_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_socketpair_error(PRInt32 err) { switch (err) { case ENOMEM: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case EAFNOSUPPORT: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; case EPROTONOSUPPORT: PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err); break; case EOPNOTSUPP: PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err); break; case EPROTOTYPE: PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err); break; default: _MD_os2_map_default_error(err); return; } } void _MD_os2_map_getsockname_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_getpeername_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case ENOTCONN: PR_SetError(PR_NOT_CONNECTED_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ENOBUFS: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_getsockopt_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case ENOPROTOOPT: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case EINVAL: PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_setsockopt_error(PRInt32 err) { switch (err) { case EBADF: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ENOTSOCK: PR_SetError(PR_NOT_SOCKET_ERROR, err); break; case ENOPROTOOPT: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case EINVAL: PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_open_error(PRInt32 err) { switch (err) { case ERROR_ALREADY_EXISTS: case ERROR_FILE_EXISTS: PR_SetError(PR_FILE_EXISTS_ERROR, err); break; case ERROR_FILE_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_INVALID_NAME: PR_SetError(PR_INVALID_ARGUMENT_ERROR, err); break; case ERROR_NOT_READY: case ERROR_OPEN_FAILED: case ERROR_PATH_BUSY: PR_SetError(PR_IO_ERROR, err); break; case ERROR_DRIVE_LOCKED: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_FILENAME_EXCED_RANGE: PR_SetError(PR_NAME_TOO_LONG_ERROR, err); break; case ERROR_TOO_MANY_OPEN_FILES: PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err); break; case ERROR_PATH_NOT_FOUND: PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; case ERROR_DISK_FULL: case ERROR_HANDLE_DISK_FULL: PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err); break; case ERROR_WRITE_PROTECT: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_gethostname_error(PRInt32 err) { switch (err) { #ifdef SOCEFAULT case SOCEFAULT: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; #endif case ENETDOWN: case EINPROGRESS: default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } void _MD_os2_map_select_error(PRInt32 err) { PRErrorCode prerror; switch (err) { /* * OS/2 select() only works on sockets. So in this * context, ENOTSOCK is equivalent to EBADF on Unix. */ case ENOTSOCK: prerror = PR_BAD_DESCRIPTOR_ERROR; break; case EINVAL: prerror = PR_INVALID_ARGUMENT_ERROR; break; #ifdef SOCEFAULT case SOCEFAULT: prerror = PR_ACCESS_FAULT_ERROR; break; #endif default: prerror = PR_UNKNOWN_ERROR; } PR_SetError(prerror, err); } void _MD_os2_map_lockf_error(PRInt32 err) { switch (err) { case ERROR_ACCESS_DENIED: PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err); break; case ERROR_INVALID_HANDLE: PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); break; case ERROR_INVALID_ADDRESS: PR_SetError(PR_ACCESS_FAULT_ERROR, err); break; case ERROR_DRIVE_LOCKED: case ERROR_LOCKED: case ERROR_SHARING_VIOLATION: PR_SetError(PR_FILE_IS_LOCKED_ERROR, err); break; case ERROR_NOT_ENOUGH_MEMORY: case ERROR_MORE_DATA: PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err); break; default: PR_SetError(PR_UNKNOWN_ERROR, err); break; } } nspr-4.11/nspr/pr/src/md/os2/os2cv.c0000644000000000000000000002361512623070344015254 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * os2cv.c -- OS/2 Machine-Dependent Code for Condition Variables * * We implement our own condition variable wait queue. Each thread * has a semaphore object (thread->md.blocked_sema) to block on while * waiting on a condition variable. * * We use a deferred condition notify algorithm. When PR_NotifyCondVar * or PR_NotifyAllCondVar is called, the condition notifies are simply * recorded in the _MDLock structure. We defer the condition notifies * until right after we unlock the lock. This way the awakened threads * have a better chance to reaquire the lock. */ #include "primpl.h" /* * AddThreadToCVWaitQueueInternal -- * * Add the thread to the end of the condition variable's wait queue. * The CV's lock must be locked when this function is called. */ static void AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv) { PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL) || (cv->waitTail == NULL && cv->waitHead == NULL)); cv->nwait += 1; thred->md.inCVWaitQueue = PR_TRUE; thred->md.next = NULL; thred->md.prev = cv->waitTail; if (cv->waitHead == NULL) { cv->waitHead = thred; } else { cv->waitTail->md.next = thred; } cv->waitTail = thred; } /* * md_UnlockAndPostNotifies -- * * Unlock the lock, and then do the deferred condition notifies. * If waitThred and waitCV are not NULL, waitThred is added to * the wait queue of waitCV before the lock is unlocked. * * This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK, * the two places where a lock is unlocked. */ void md_UnlockAndPostNotifies( _MDLock *lock, PRThread *waitThred, _MDCVar *waitCV) { PRIntn index; _MDNotified post; _MDNotified *notified, *prev = NULL; /* * Time to actually notify any conditions that were affected * while the lock was held. Get a copy of the list that's in * the lock structure and then zero the original. If it's * linked to other such structures, we own that storage. */ post = lock->notified; /* a safe copy; we own the lock */ #if defined(DEBUG) memset(&lock->notified, 0, sizeof(_MDNotified)); /* reset */ #else lock->notified.length = 0; /* these are really sufficient */ lock->notified.link = NULL; #endif /* * Figure out how many threads we need to wake up. */ notified = &post; /* this is where we start */ do { for (index = 0; index < notified->length; ++index) { _MDCVar *cv = notified->cv[index].cv; PRThread *thred; int i; /* Fast special case: no waiting threads */ if (cv->waitHead == NULL) { notified->cv[index].notifyHead = NULL; continue; } /* General case */ if (-1 == notified->cv[index].times) { /* broadcast */ thred = cv->waitHead; while (thred != NULL) { thred->md.inCVWaitQueue = PR_FALSE; thred = thred->md.next; } notified->cv[index].notifyHead = cv->waitHead; cv->waitHead = cv->waitTail = NULL; cv->nwait = 0; } else { thred = cv->waitHead; i = notified->cv[index].times; while (thred != NULL && i > 0) { thred->md.inCVWaitQueue = PR_FALSE; thred = thred->md.next; i--; } notified->cv[index].notifyHead = cv->waitHead; cv->waitHead = thred; if (cv->waitHead == NULL) { cv->waitTail = NULL; } else { if (cv->waitHead->md.prev != NULL) { cv->waitHead->md.prev->md.next = NULL; cv->waitHead->md.prev = NULL; } } cv->nwait -= notified->cv[index].times - i; } } notified = notified->link; } while (NULL != notified); if (waitThred) { AddThreadToCVWaitQueueInternal(waitThred, waitCV); } /* Release the lock before notifying */ DosReleaseMutexSem(lock->mutex); notified = &post; /* this is where we start */ do { for (index = 0; index < notified->length; ++index) { PRThread *thred; PRThread *next; thred = notified->cv[index].notifyHead; while (thred != NULL) { BOOL rv; next = thred->md.next; thred->md.prev = thred->md.next = NULL; rv = DosPostEventSem(thred->md.blocked_sema); PR_ASSERT(rv == NO_ERROR); thred = next; } } prev = notified; notified = notified->link; if (&post != prev) PR_DELETE(prev); } while (NULL != notified); } /* * Notifies just get posted to the protecting mutex. The * actual notification is done when the lock is released so that * MP systems don't contend for a lock that they can't have. */ static void md_PostNotifyToCvar(_MDCVar *cvar, _MDLock *lock, PRBool broadcast) { PRIntn index = 0; _MDNotified *notified = &lock->notified; while (1) { for (index = 0; index < notified->length; ++index) { if (notified->cv[index].cv == cvar) { if (broadcast) { notified->cv[index].times = -1; } else if (-1 != notified->cv[index].times) { notified->cv[index].times += 1; } return; } } /* if not full, enter new CV in this array */ if (notified->length < _MD_CV_NOTIFIED_LENGTH) break; /* if there's no link, create an empty array and link it */ if (NULL == notified->link) { notified->link = PR_NEWZAP(_MDNotified); } notified = notified->link; } /* A brand new entry in the array */ notified->cv[index].times = (broadcast) ? -1 : 1; notified->cv[index].cv = cvar; notified->length += 1; } /* * _PR_MD_NEW_CV() -- Creating new condition variable * ... Solaris uses cond_init() in similar function. * * returns: -1 on failure * 0 when it succeeds. * */ PRInt32 _PR_MD_NEW_CV(_MDCVar *cv) { cv->magic = _MD_MAGIC_CV; /* * The waitHead, waitTail, and nwait fields are zeroed * when the PRCondVar structure is created. */ return 0; } void _PR_MD_FREE_CV(_MDCVar *cv) { cv->magic = (PRUint32)-1; return; } /* * _PR_MD_WAIT_CV() -- Wait on condition variable */ void _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout ) { PRThread *thred = _PR_MD_CURRENT_THREAD(); ULONG rv, count; ULONG msecs = (timeout == PR_INTERVAL_NO_TIMEOUT) ? SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(timeout); /* * If we have pending notifies, post them now. */ if (0 != lock->notified.length) { md_UnlockAndPostNotifies(lock, thred, cv); } else { AddThreadToCVWaitQueueInternal(thred, cv); DosReleaseMutexSem(lock->mutex); } /* Wait for notification or timeout; don't really care which */ rv = DosWaitEventSem(thred->md.blocked_sema, msecs); if (rv == NO_ERROR) { DosResetEventSem(thred->md.blocked_sema, &count); } DosRequestMutexSem((lock->mutex), SEM_INDEFINITE_WAIT); PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT); if(rv == ERROR_TIMEOUT) { if (thred->md.inCVWaitQueue) { PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL) || (cv->waitTail == NULL && cv->waitHead == NULL)); cv->nwait -= 1; thred->md.inCVWaitQueue = PR_FALSE; if (cv->waitHead == thred) { cv->waitHead = thred->md.next; if (cv->waitHead == NULL) { cv->waitTail = NULL; } else { cv->waitHead->md.prev = NULL; } } else { PR_ASSERT(thred->md.prev != NULL); thred->md.prev->md.next = thred->md.next; if (thred->md.next != NULL) { thred->md.next->md.prev = thred->md.prev; } else { PR_ASSERT(cv->waitTail == thred); cv->waitTail = thred->md.prev; } } thred->md.next = thred->md.prev = NULL; } else { /* * This thread must have been notified, but the * SemRelease call happens after SemRequest * times out. Wait on the semaphore again to make it * non-signaled. We assume this wait won't take long. */ rv = DosWaitEventSem(thred->md.blocked_sema, SEM_INDEFINITE_WAIT); if (rv == NO_ERROR) { DosResetEventSem(thred->md.blocked_sema, &count); } PR_ASSERT(rv == NO_ERROR); } } PR_ASSERT(thred->md.inCVWaitQueue == PR_FALSE); return; } /* --- end _PR_MD_WAIT_CV() --- */ void _PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock) { md_PostNotifyToCvar(cv, lock, PR_FALSE); return; } PRStatus _PR_MD_NEW_LOCK(_MDLock *lock) { DosCreateMutexSem(0, &(lock->mutex), 0, 0); (lock)->notified.length=0; (lock)->notified.link=NULL; return PR_SUCCESS; } void _PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock) { md_PostNotifyToCvar(cv, lock, PR_TRUE); return; } void _PR_MD_UNLOCK(_MDLock *lock) { if (0 != lock->notified.length) { md_UnlockAndPostNotifies(lock, NULL, NULL); } else { DosReleaseMutexSem(lock->mutex); } } nspr-4.11/nspr/pr/src/md/os2/os2emx.s0000644000000000000000000000350312623070344015447 0ustar 00000000000000/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- / / This Source Code Form is subject to the terms of the Mozilla Public / License, v. 2.0. If a copy of the MPL was not distributed with this / file, You can obtain one at http://mozilla.org/MPL/2.0/. / PRInt32 __PR_MD_ATOMIC_INCREMENT(PRInt32 *val) / / Atomically increment the integer pointed to by 'val' and return / the result of the increment. / .text .globl __PR_MD_ATOMIC_INCREMENT .align 4 __PR_MD_ATOMIC_INCREMENT: movl 4(%esp), %ecx movl $1, %eax lock xaddl %eax, (%ecx) incl %eax ret / PRInt32 __PR_MD_ATOMIC_DECREMENT(PRInt32 *val) / / Atomically decrement the integer pointed to by 'val' and return / the result of the decrement. / .text .globl __PR_MD_ATOMIC_DECREMENT .align 4 __PR_MD_ATOMIC_DECREMENT: movl 4(%esp), %ecx movl $-1, %eax lock xaddl %eax, (%ecx) decl %eax ret / PRInt32 __PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) / / Atomically set the integer pointed to by 'val' to the new / value 'newval' and return the old value. / / An alternative implementation: / .text / .globl __PR_MD_ATOMIC_SET / .align 4 /__PR_MD_ATOMIC_SET: / movl 4(%esp), %ecx / movl 8(%esp), %edx / movl (%ecx), %eax /retry: / lock / cmpxchgl %edx, (%ecx) / jne retry / ret / .text .globl __PR_MD_ATOMIC_SET .align 4 __PR_MD_ATOMIC_SET: movl 4(%esp), %ecx movl 8(%esp), %eax xchgl %eax, (%ecx) ret / PRInt32 __PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) / / Atomically add 'val' to the integer pointed to by 'ptr' / and return the result of the addition. / .text .globl __PR_MD_ATOMIC_ADD .align 4 __PR_MD_ATOMIC_ADD: movl 4(%esp), %ecx movl 8(%esp), %eax movl %eax, %edx lock xaddl %eax, (%ecx) addl %edx, %eax ret nspr-4.11/nspr/pr/src/md/os2/os2gc.c0000644000000000000000000000332712623070344015233 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * GC related routines * */ #include "primpl.h" PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { CONTEXTRECORD context; context.ContextFlags = CONTEXT_INTEGER; if (_PR_IS_NATIVE_THREAD(t)) { context.ContextFlags |= CONTEXT_CONTROL; if (QueryThreadContext(t->md.handle, CONTEXT_CONTROL, &context)) { t->md.gcContext[0] = context.ctx_RegEax; t->md.gcContext[1] = context.ctx_RegEbx; t->md.gcContext[2] = context.ctx_RegEcx; t->md.gcContext[3] = context.ctx_RegEdx; t->md.gcContext[4] = context.ctx_RegEsi; t->md.gcContext[5] = context.ctx_RegEdi; t->md.gcContext[6] = context.ctx_RegEsp; t->md.gcContext[7] = context.ctx_RegEbp; *np = PR_NUM_GCREGS; } else { PR_ASSERT(0);/* XXX */ } } return (PRWord *)&t->md.gcContext; } /* This function is not used right now, but is left as a reference. * If you ever need to get the fiberID from the currently running fiber, * this is it. */ void * GetMyFiberID() { void *fiberData = 0; /* A pointer to our tib entry is found at FS:[18] * At offset 10h is the fiberData pointer. The context of the * fiber is stored in there. */ #ifdef HAVE_ASM __asm { mov EDX, FS:[18h] mov EAX, DWORD PTR [EDX+10h] mov [fiberData], EAX } #endif return fiberData; } nspr-4.11/nspr/pr/src/md/os2/os2inrval.c0000644000000000000000000000406612623070344016136 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * OS/2 interval timers * */ #include "primpl.h" static PRBool useHighResTimer = PR_FALSE; PRIntervalTime _os2_ticksPerSec = -1; PRIntn _os2_bitShift = 0; PRInt32 _os2_highMask = 0; void _PR_MD_INTERVAL_INIT() { char *envp; ULONG timerFreq; APIRET rc; if ((envp = getenv("NSPR_OS2_NO_HIRES_TIMER")) != NULL) { if (atoi(envp) == 1) return; } timerFreq = 0; /* OS/2 high-resolution timer frequency in Hz */ rc = DosTmrQueryFreq(&timerFreq); if (NO_ERROR == rc) { useHighResTimer = PR_TRUE; PR_ASSERT(timerFreq != 0); while (timerFreq > PR_INTERVAL_MAX) { timerFreq >>= 1; _os2_bitShift++; _os2_highMask = (_os2_highMask << 1)+1; } _os2_ticksPerSec = timerFreq; PR_ASSERT(_os2_ticksPerSec > PR_INTERVAL_MIN); } } PRIntervalTime _PR_MD_GET_INTERVAL() { if (useHighResTimer) { QWORD timestamp; PRInt32 top; APIRET rc = DosTmrQueryTime(×tamp); if (NO_ERROR != rc) { return -1; } /* Sadly, nspr requires the interval to range from 1000 ticks per * second to only 100000 ticks per second. DosTmrQueryTime is too * high resolution... */ top = timestamp.ulHi & _os2_highMask; top = top << (32 - _os2_bitShift); timestamp.ulLo = timestamp.ulLo >> _os2_bitShift; timestamp.ulLo = timestamp.ulLo + top; return (PRUint32)timestamp.ulLo; } else { ULONG msCount = -1; DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &msCount, sizeof(msCount)); return msCount; } } PRIntervalTime _PR_MD_INTERVAL_PER_SEC() { if (useHighResTimer) { return _os2_ticksPerSec; } else { return 1000; } } nspr-4.11/nspr/pr/src/md/os2/os2io.c0000644000000000000000000005651612623070344015261 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* OS2 IO module * * Assumes synchronous I/O. * */ #include "primpl.h" #include "prio.h" #include #include #include #include #include #include struct _MDLock _pr_ioq_lock; static PRBool isWSEB = PR_FALSE; /* whether we are using an OS/2 kernel that supports large files */ typedef APIRET (*DosOpenLType)(PSZ pszFileName, PHFILE pHf, PULONG pulAction, LONGLONG cbFile, ULONG ulAttribute, ULONG fsOpenFlags, ULONG fsOpenMode, PEAOP2 peaop2); typedef APIRET (*DosSetFileLocksLType)(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock, ULONG timeout, ULONG flags); typedef APIRET (*DosSetFilePtrLType)(HFILE hFile, LONGLONG ib, ULONG method, PLONGLONG ibActual); DosOpenLType myDosOpenL; DosSetFileLocksLType myDosSetFileLocksL; DosSetFilePtrLType myDosSetFilePtrL; void _PR_MD_INIT_IO() { APIRET rc; HMODULE module; sock_init(); rc = DosLoadModule(NULL, 0, "DOSCALL1", &module); if (rc != NO_ERROR) { return; } rc = DosQueryProcAddr(module, 981, NULL, (PFN*) &myDosOpenL); if (rc != NO_ERROR) { return; } rc = DosQueryProcAddr(module, 986, NULL, (PFN*) &myDosSetFileLocksL); if (rc != NO_ERROR) { return; } rc = DosQueryProcAddr(module, 988, NULL, (PFN*) &myDosSetFilePtrL); if (rc != NO_ERROR) { return; } isWSEB = PR_TRUE; } PRStatus _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PRInt32 rv; ULONG count; PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks); rv = DosWaitEventSem(thread->md.blocked_sema, msecs); DosResetEventSem(thread->md.blocked_sema, &count); switch(rv) { case NO_ERROR: return PR_SUCCESS; break; case ERROR_TIMEOUT: _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { ; } else { if (thread->wait.cvar != NULL) { thread->wait.cvar = NULL; _PR_THREAD_UNLOCK(thread); } else { /* The CVAR was notified just as the timeout * occurred. This led to us being notified twice. * call SemRequest() to clear the semaphore. */ _PR_THREAD_UNLOCK(thread); rv = DosWaitEventSem(thread->md.blocked_sema, 0); DosResetEventSem(thread->md.blocked_sema, &count); PR_ASSERT(rv == NO_ERROR); } } return PR_SUCCESS; break; default: break; } return PR_FAILURE; } PRStatus _PR_MD_WAKEUP_WAITER(PRThread *thread) { if ( _PR_IS_NATIVE_THREAD(thread) ) { if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR) return PR_FAILURE; else return PR_SUCCESS; } } /* --- FILE IO ----------------------------------------------------------- */ /* * _PR_MD_OPEN() -- Open a file * * returns: a fileHandle * * The NSPR open flags (osflags) are translated into flags for OS/2 * * Mode seems to be passed in as a unix style file permissions argument * as in 0666, in the case of opening the logFile. * */ PRInt32 _PR_MD_OPEN(const char *name, PRIntn osflags, int mode) { HFILE file; PRInt32 access = OPEN_SHARE_DENYNONE; PRInt32 flags = 0L; APIRET rc = 0; PRUword actionTaken; #ifdef MOZ_OS2_HIGH_MEMORY /* * All the pointer arguments (&file, &actionTaken and name) have to be in * low memory for DosOpen to use them. * The following moves name to low memory. */ if ((ULONG)name >= 0x20000000) { size_t len = strlen(name) + 1; char *copy = (char *)alloca(len); memcpy(copy, name, len); name = copy; } #endif if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH; if (osflags & PR_RDONLY) access |= OPEN_ACCESS_READONLY; else if (osflags & PR_WRONLY) access |= OPEN_ACCESS_WRITEONLY; else if(osflags & PR_RDWR) access |= OPEN_ACCESS_READWRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) { flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS; } else if (osflags & PR_CREATE_FILE) { if (osflags & PR_TRUNCATE) flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS; else flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; } else { if (osflags & PR_TRUNCATE) flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS; else flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; } do { if (isWSEB) { rc = myDosOpenL((char*)name, &file, /* file handle if successful */ &actionTaken, /* reason for failure */ 0, /* initial size of new file */ FILE_NORMAL, /* file system attributes */ flags, /* Open flags */ access, /* Open mode and rights */ 0); /* OS/2 Extended Attributes */ } else { rc = DosOpen((char*)name, &file, /* file handle if successful */ &actionTaken, /* reason for failure */ 0, /* initial size of new file */ FILE_NORMAL, /* file system attributes */ flags, /* Open flags */ access, /* Open mode and rights */ 0); /* OS/2 Extended Attributes */ }; if (rc == ERROR_TOO_MANY_OPEN_FILES) { ULONG CurMaxFH = 0; LONG ReqCount = 20; APIRET rc2; rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH); if (rc2 != NO_ERROR) { break; } } } while (rc == ERROR_TOO_MANY_OPEN_FILES); if (rc != NO_ERROR) { _PR_MD_MAP_OPEN_ERROR(rc); return -1; } return (PRInt32)file; } PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) { ULONG bytes; int rv; rv = DosRead((HFILE)fd->secret->md.osfd, (PVOID)buf, len, &bytes); if (rv != NO_ERROR) { /* ERROR_HANDLE_EOF can only be returned by async io */ PR_ASSERT(rv != ERROR_HANDLE_EOF); if (rv == ERROR_BROKEN_PIPE) return 0; else { _PR_MD_MAP_READ_ERROR(rv); return -1; } } return (PRInt32)bytes; } PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) { PRInt32 bytes; int rv; rv = DosWrite((HFILE)fd->secret->md.osfd, (PVOID)buf, len, (PULONG)&bytes); if (rv != NO_ERROR) { _PR_MD_MAP_WRITE_ERROR(rv); return -1; } if (len != bytes) { rv = ERROR_DISK_FULL; _PR_MD_MAP_WRITE_ERROR(rv); return -1; } return bytes; } /* --- end _PR_MD_WRITE() --- */ PRInt32 _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) { PRInt32 rv; PRUword newLocation; rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation); if (rv != NO_ERROR) { _PR_MD_MAP_LSEEK_ERROR(rv); return -1; } else return newLocation; } PRInt64 _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) { #ifdef NO_LONG_LONG PRInt64 result; PRInt32 rv, low = offset.lo, hi = offset.hi; PRUword newLocation; rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation); rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation); if (rv != NO_ERROR) { _PR_MD_MAP_LSEEK_ERROR(rv); hi = newLocation = -1; } result.lo = newLocation; result.hi = hi; return result; #else PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32); PRUint64 rv; PRUint32 newLocation, uhi; PRUint64 newLocationL; switch (whence) { case PR_SEEK_SET: where = FILE_BEGIN; break; case PR_SEEK_CUR: where = FILE_CURRENT; break; case PR_SEEK_END: where = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (isWSEB) { rc = myDosSetFilePtrL((HFILE)fd->secret->md.osfd, offset, where, (PLONGLONG)&newLocationL); } else { rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation); } if (rc != NO_ERROR) { _PR_MD_MAP_LSEEK_ERROR(rc); return -1; } if (isWSEB) { return newLocationL; } uhi = (PRUint32)hi; PR_ASSERT((PRInt32)uhi >= 0); rv = uhi; PR_ASSERT((PRInt64)rv >= 0); rv = (rv << 32); PR_ASSERT((PRInt64)rv >= 0); rv += newLocation; PR_ASSERT((PRInt64)rv >= 0); return (PRInt64)rv; #endif } PRInt32 _PR_MD_FSYNC(PRFileDesc *fd) { PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd); if (rc != NO_ERROR) { if (rc != ERROR_ACCESS_DENIED) { _PR_MD_MAP_FSYNC_ERROR(rc); return -1; } } return 0; } PRInt32 _MD_CloseFile(PRInt32 osfd) { PRInt32 rv; rv = DosClose((HFILE)osfd); if (rv != NO_ERROR) _PR_MD_MAP_CLOSE_ERROR(rv); return rv; } /* --- DIR IO ------------------------------------------------------------ */ #define GetFileFromDIR(d) (isWSEB?(d)->d_entry.large.achName:(d)->d_entry.small.achName) #define GetFileAttr(d) (isWSEB?(d)->d_entry.large.attrFile:(d)->d_entry.small.attrFile) void FlipSlashes(char *cp, int len) { while (--len >= 0) { if (cp[0] == '/') { cp[0] = PR_DIRECTORY_SEPARATOR; } cp++; } } /* ** ** Local implementations of standard Unix RTL functions which are not provided ** by the VAC RTL. ** */ PRInt32 _PR_MD_CLOSE_DIR(_MDDir *d) { PRInt32 rc; if ( d ) { rc = DosFindClose(d->d_hdl); if(rc == NO_ERROR){ d->magic = (PRUint32)-1; return PR_SUCCESS; } else { _PR_MD_MAP_CLOSEDIR_ERROR(rc); return PR_FAILURE; } } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } PRStatus _PR_MD_OPEN_DIR(_MDDir *d, const char *name) { char filename[ CCHMAXPATH ]; PRUword numEntries, rc; numEntries = 1; PR_snprintf(filename, CCHMAXPATH, "%s%s%s", name, PR_DIRECTORY_SEPARATOR_STR, "*.*"); FlipSlashes( filename, strlen(filename) ); d->d_hdl = HDIR_CREATE; if (isWSEB) { rc = DosFindFirst( filename, &d->d_hdl, FILE_DIRECTORY | FILE_HIDDEN, &(d->d_entry.large), sizeof(d->d_entry.large), &numEntries, FIL_STANDARDL); } else { rc = DosFindFirst( filename, &d->d_hdl, FILE_DIRECTORY | FILE_HIDDEN, &(d->d_entry.small), sizeof(d->d_entry.small), &numEntries, FIL_STANDARD); } if ( rc != NO_ERROR ) { _PR_MD_MAP_OPENDIR_ERROR(rc); return PR_FAILURE; } d->firstEntry = PR_TRUE; d->magic = _MD_MAGIC_DIR; return PR_SUCCESS; } char * _PR_MD_READ_DIR(_MDDir *d, PRIntn flags) { PRUword numFiles = 1; BOOL rv; char *fileName; USHORT fileAttr; if ( d ) { while (1) { if (d->firstEntry) { d->firstEntry = PR_FALSE; rv = NO_ERROR; } else { rv = DosFindNext(d->d_hdl, &(d->d_entry), sizeof(d->d_entry), &numFiles); } if (rv != NO_ERROR) { break; } fileName = GetFileFromDIR(d); fileAttr = GetFileAttr(d); if ( (flags & PR_SKIP_DOT) && (fileName[0] == '.') && (fileName[1] == '\0')) continue; if ( (flags & PR_SKIP_DOT_DOT) && (fileName[0] == '.') && (fileName[1] == '.') && (fileName[2] == '\0')) continue; /* * XXX * Is this the correct definition of a hidden file on OS/2? */ if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN)) return fileName; else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN)) continue; return fileName; } PR_ASSERT(NO_ERROR != rv); _PR_MD_MAP_READDIR_ERROR(rv); return NULL; } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } PRInt32 _PR_MD_DELETE(const char *name) { PRInt32 rc = DosDelete((char*)name); if(rc == NO_ERROR) { return 0; } else { _PR_MD_MAP_DELETE_ERROR(rc); return -1; } } PRInt32 _PR_MD_STAT(const char *fn, struct stat *info) { PRInt32 rv; char filename[CCHMAXPATH]; PR_snprintf(filename, CCHMAXPATH, "%s", fn); FlipSlashes(filename, strlen(filename)); rv = _stat((char*)filename, info); if (-1 == rv) { /* * Check for MSVC runtime library _stat() bug. * (It's really a bug in FindFirstFile().) * If a pathname ends in a backslash or slash, * e.g., c:\temp\ or c:/temp/, _stat() will fail. * Note: a pathname ending in a slash (e.g., c:/temp/) * can be handled by _stat() on NT but not on Win95. * * We remove the backslash or slash at the end and * try again. * * Not sure if this happens on OS/2 or not, * but it doesn't hurt to be careful. */ int len = strlen(fn); if (len > 0 && len <= _MAX_PATH && (fn[len - 1] == '\\' || fn[len - 1] == '/')) { char newfn[_MAX_PATH + 1]; strcpy(newfn, fn); newfn[len - 1] = '\0'; rv = _stat(newfn, info); } } if (-1 == rv) { _PR_MD_MAP_STAT_ERROR(errno); } return rv; } PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info) { struct stat sb; PRInt32 rv; PRInt64 s, s2us; if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) { if (info) { if (S_IFREG & sb.st_mode) info->type = PR_FILE_FILE ; else if (S_IFDIR & sb.st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; info->size = sb.st_size; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, sb.st_mtime); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb.st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } } return rv; } PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) { PRFileInfo info32; PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32); if (rv != 0) { return rv; } info->type = info32.type; LL_UI2L(info->size,info32.size); info->modifyTime = info32.modifyTime; info->creationTime = info32.creationTime; if (isWSEB) { APIRET rc ; FILESTATUS3L fstatus; rc = DosQueryPathInfo(fn, FIL_STANDARDL, &fstatus, sizeof(fstatus)); if (NO_ERROR != rc) { _PR_MD_MAP_OPEN_ERROR(rc); return -1; } if (! (fstatus.attrFile & FILE_DIRECTORY)) { info->size = fstatus.cbFile; } } return rv; } PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info) { /* For once, the VAC compiler/library did a nice thing. * The file handle used by the C runtime is the same one * returned by the OS when you call DosOpen(). This means * that you can take an OS HFILE and use it with C file * functions. The only caveat is that you have to call * _setmode() first to initialize some junk. This is * immensely useful because I did not have a clue how to * implement this function otherwise. The windows folks * took the source from the Microsoft C library source, but * IBM wasn't kind enough to ship the source with VAC. * On second thought, the needed function could probably * be gotten from the OS/2 GNU library source, but the * point is now moot. */ struct stat hinfo; PRInt64 s, s2us; _setmode(fd->secret->md.osfd, O_BINARY); if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) { _PR_MD_MAP_FSTAT_ERROR(errno); return -1; } if (hinfo.st_mode & S_IFDIR) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_FILE; info->size = hinfo.st_size; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, hinfo.st_mtime); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, hinfo.st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; return 0; } PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info) { PRFileInfo info32; PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32); if (0 == rv) { info->type = info32.type; LL_UI2L(info->size,info32.size); info->modifyTime = info32.modifyTime; info->creationTime = info32.creationTime; } if (isWSEB) { APIRET rc ; FILESTATUS3L fstatus; rc = DosQueryFileInfo(fd->secret->md.osfd, FIL_STANDARDL, &fstatus, sizeof(fstatus)); if (NO_ERROR != rc) { _PR_MD_MAP_OPEN_ERROR(rc); return -1; } if (! (fstatus.attrFile & FILE_DIRECTORY)) { info->size = fstatus.cbFile; } } return rv; } PRInt32 _PR_MD_RENAME(const char *from, const char *to) { PRInt32 rc; /* Does this work with dot-relative pathnames? */ if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) { return 0; } else { _PR_MD_MAP_RENAME_ERROR(rc); return -1; } } PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how) { PRInt32 rv; switch (how) { case PR_ACCESS_WRITE_OK: rv = access(name, 02); break; case PR_ACCESS_READ_OK: rv = access(name, 04); break; case PR_ACCESS_EXISTS: return access(name, 00); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (rv < 0) _PR_MD_MAP_ACCESS_ERROR(errno); return rv; } PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode) { PRInt32 rc; /* XXXMB - how to translate the "mode"??? */ if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) { return 0; } else { _PR_MD_MAP_MKDIR_ERROR(rc); return -1; } } PRInt32 _PR_MD_RMDIR(const char *name) { PRInt32 rc; if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) { return 0; } else { _PR_MD_MAP_RMDIR_ERROR(rc); return -1; } } PRStatus _PR_MD_LOCKFILE(PRInt32 f) { PRInt32 rv; FILELOCK lock, unlock; FILELOCKL lockL, unlockL; lock.lOffset = 0; lockL.lOffset = 0; lock.lRange = 0xffffffff; lockL.lRange = 0xffffffffffffffff; unlock.lOffset = 0; unlock.lRange = 0; unlockL.lOffset = 0; unlockL.lRange = 0; /* * loop trying to DosSetFileLocks(), * pause for a few miliseconds when can't get the lock * and try again */ for( rv = FALSE; rv == FALSE; /* do nothing */ ) { if (isWSEB) { rv = myDosSetFileLocksL( (HFILE) f, &unlockL, &lockL, 0, 0); } else { rv = DosSetFileLocks( (HFILE) f, &unlock, &lock, 0, 0); } if ( rv != NO_ERROR ) { DosSleep( 50 ); /* Sleep() a few milisecs and try again. */ } } /* end for() */ return PR_SUCCESS; } /* end _PR_MD_LOCKFILE() */ PRStatus _PR_MD_TLOCKFILE(PRInt32 f) { return _PR_MD_LOCKFILE(f); } /* end _PR_MD_TLOCKFILE() */ PRStatus _PR_MD_UNLOCKFILE(PRInt32 f) { PRInt32 rv; FILELOCK lock, unlock; FILELOCKL lockL, unlockL; lock.lOffset = 0; lockL.lOffset = 0; lock.lRange = 0; lockL.lRange = 0; unlock.lOffset = 0; unlockL.lOffset = 0; unlock.lRange = 0xffffffff; unlockL.lRange = 0xffffffffffffffff; if (isWSEB) { rv = myDosSetFileLocksL( (HFILE) f, &unlockL, &lockL, 0, 0); } else { rv = DosSetFileLocks( (HFILE) f, &unlock, &lock, 0, 0); } if ( rv != NO_ERROR ) { return PR_SUCCESS; } else { return PR_FAILURE; } } /* end _PR_MD_UNLOCKFILE() */ PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) { APIRET rc = 0; ULONG flags; switch (fd->methods->file_type) { case PR_DESC_PIPE: case PR_DESC_FILE: rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags); if (rc != NO_ERROR) { PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); return PR_FAILURE; } if (inheritable) flags &= ~OPEN_FLAGS_NOINHERIT; else flags |= OPEN_FLAGS_NOINHERIT; /* Mask off flags DosSetFHState don't want. */ flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags); if (rc != NO_ERROR) { PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); return PR_FAILURE; } break; case PR_DESC_LAYERED: /* what to do here? */ PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/); return PR_FAILURE; case PR_DESC_SOCKET_TCP: case PR_DESC_SOCKET_UDP: /* These are global on OS/2. */ break; } return PR_SUCCESS; } void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported) { /* XXX this function needs to be implemented */ fd->secret->inheritable = _PR_TRI_UNKNOWN; } void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd) { /* XXX this function needs to be reviewed */ ULONG flags; PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) { if (flags & OPEN_FLAGS_NOINHERIT) { fd->secret->inheritable = _PR_TRI_FALSE; } else { fd->secret->inheritable = _PR_TRI_TRUE; } } } nspr-4.11/nspr/pr/src/md/os2/os2misc.c0000644000000000000000000004031212623070344015570 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * os2misc.c * */ #ifdef MOZ_OS2_HIGH_MEMORY /* os2safe.h has to be included before os2.h, needed for high mem */ #include #endif #include #include "primpl.h" extern int _CRT_init(void); extern void _CRT_term(void); extern void __ctordtorInit(int flag); extern void __ctordtorTerm(int flag); char * _PR_MD_GET_ENV(const char *name) { return getenv(name); } PRIntn _PR_MD_PUT_ENV(const char *name) { return putenv(name); } /* ************************************************************************** ************************************************************************** ** ** Date and time routines ** ************************************************************************** ************************************************************************** */ #include /* *----------------------------------------------------------------------- * * PR_Now -- * * Returns the current time in microseconds since the epoch. * The epoch is midnight January 1, 1970 GMT. * The implementation is machine dependent. This is the * implementation for OS/2. * Cf. time_t time(time_t *tp) * *----------------------------------------------------------------------- */ PR_IMPLEMENT(PRTime) PR_Now(void) { PRInt64 s, ms, ms2us, s2us; struct timeb b; ftime(&b); LL_I2L(ms2us, PR_USEC_PER_MSEC); LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, b.time); LL_I2L(ms, b.millitm); LL_MUL(ms, ms, ms2us); LL_MUL(s, s, s2us); LL_ADD(s, s, ms); return s; } /* *********************************************************************** *********************************************************************** * * Process creation routines * *********************************************************************** *********************************************************************** */ /* * Assemble the command line by concatenating the argv array. * Special characters intentionally do not get escaped, and it is * expected that the caller wraps arguments in quotes if needed * (e.g. for filename with spaces). * * On success, this function returns 0 and the resulting command * line is returned in *cmdLine. On failure, it returns -1. */ static int assembleCmdLine(char *const *argv, char **cmdLine) { char *const *arg; int cmdLineSize; /* * Find out how large the command line buffer should be. */ cmdLineSize = 1; /* final null */ for (arg = argv+1; *arg; arg++) { cmdLineSize += strlen(*arg) + 1; /* space in between */ } *cmdLine = PR_MALLOC(cmdLineSize); if (*cmdLine == NULL) { return -1; } (*cmdLine)[0] = '\0'; for (arg = argv+1; *arg; arg++) { if (arg > argv +1) { strcat(*cmdLine, " "); } strcat(*cmdLine, *arg); } return 0; } /* * Assemble the environment block by concatenating the envp array * (preserving the terminating null byte in each array element) * and adding a null byte at the end. * * Returns 0 on success. The resulting environment block is returned * in *envBlock. Note that if envp is NULL, a NULL pointer is returned * in *envBlock. Returns -1 on failure. */ static int assembleEnvBlock(char **envp, char **envBlock) { char *p; char *q; char **env; char *curEnv; char *cwdStart, *cwdEnd; int envBlockSize; PPIB ppib = NULL; PTIB ptib = NULL; if (envp == NULL) { *envBlock = NULL; return 0; } if(DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) return -1; curEnv = ppib->pib_pchenv; cwdStart = curEnv; while (*cwdStart) { if (cwdStart[0] == '=' && cwdStart[1] != '\0' && cwdStart[2] == ':' && cwdStart[3] == '=') { break; } cwdStart += strlen(cwdStart) + 1; } cwdEnd = cwdStart; if (*cwdEnd) { cwdEnd += strlen(cwdEnd) + 1; while (*cwdEnd) { if (cwdEnd[0] != '=' || cwdEnd[1] == '\0' || cwdEnd[2] != ':' || cwdEnd[3] != '=') { break; } cwdEnd += strlen(cwdEnd) + 1; } } envBlockSize = cwdEnd - cwdStart; for (env = envp; *env; env++) { envBlockSize += strlen(*env) + 1; } envBlockSize++; p = *envBlock = PR_MALLOC(envBlockSize); if (p == NULL) { return -1; } q = cwdStart; while (q < cwdEnd) { *p++ = *q++; } for (env = envp; *env; env++) { q = *env; while (*q) { *p++ = *q++; } *p++ = '\0'; } *p = '\0'; return 0; } /* * For qsort. We sort (case-insensitive) the environment strings * before generating the environment block. */ static int compare(const void *arg1, const void *arg2) { return stricmp(* (char**)arg1, * (char**)arg2); } PRProcess * _PR_CreateOS2Process( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { PRProcess *proc = NULL; char *cmdLine = NULL; char **newEnvp = NULL; char *envBlock = NULL; STARTDATA startData = {0}; APIRET rc; ULONG ulAppType = 0; PID pid = 0; char *pszComSpec; char pszEXEName[CCHMAXPATH] = ""; char pszFormatString[CCHMAXPATH]; char pszObjectBuffer[CCHMAXPATH]; char *pszFormatResult = NULL; /* * Variables for DosExecPgm */ char szFailed[CCHMAXPATH]; char *pszCmdLine = NULL; RESULTCODES procInfo; HFILE hStdIn = 0, hStdOut = 0, hStdErr = 0; HFILE hStdInSave = -1, hStdOutSave = -1, hStdErrSave = -1; proc = PR_NEW(PRProcess); if (!proc) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } if (assembleCmdLine(argv, &cmdLine) == -1) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } #ifdef MOZ_OS2_HIGH_MEMORY /* * DosQueryAppType() fails if path (the char* in the first argument) is in * high memory. If that is the case, the following moves it to low memory. */ if ((ULONG)path >= 0x20000000) { size_t len = strlen(path) + 1; char *copy = (char *)alloca(len); memcpy(copy, path, len); path = copy; } #endif if (envp == NULL) { newEnvp = NULL; } else { int i; int numEnv = 0; while (envp[numEnv]) { numEnv++; } newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *)); for (i = 0; i <= numEnv; i++) { newEnvp[i] = envp[i]; } qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare); } if (assembleEnvBlock(newEnvp, &envBlock) == -1) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } rc = DosQueryAppType(path, &ulAppType); if (rc != NO_ERROR) { char *pszDot = strrchr(path, '.'); if (pszDot) { /* If it is a CMD file, launch the users command processor */ if (!stricmp(pszDot, ".cmd")) { rc = DosScanEnv("COMSPEC", (PSZ *)&pszComSpec); if (!rc) { strcpy(pszFormatString, "/C %s %s"); strcpy(pszEXEName, pszComSpec); ulAppType = FAPPTYP_WINDOWCOMPAT; } } } } if (ulAppType == 0) { PR_SetError(PR_UNKNOWN_ERROR, 0); goto errorExit; } if ((ulAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) { startData.SessionType = SSF_TYPE_PM; } else if (ulAppType & FAPPTYP_WINDOWCOMPAT) { startData.SessionType = SSF_TYPE_WINDOWABLEVIO; } else { startData.SessionType = SSF_TYPE_DEFAULT; } if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL)) { strcpy(pszEXEName, "WINOS2.COM"); startData.SessionType = PROG_31_STDSEAMLESSVDM; strcpy(pszFormatString, "/3 %s %s"); } startData.InheritOpt = SSF_INHERTOPT_SHELL; if (pszEXEName[0]) { pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine)); sprintf(pszFormatResult, pszFormatString, path, cmdLine); startData.PgmInputs = pszFormatResult; } else { strcpy(pszEXEName, path); startData.PgmInputs = cmdLine; } startData.PgmName = pszEXEName; startData.Length = sizeof(startData); startData.Related = SSF_RELATED_INDEPENDENT; startData.ObjectBuffer = pszObjectBuffer; startData.ObjectBuffLen = CCHMAXPATH; startData.Environment = envBlock; if (attr) { /* On OS/2, there is really no way to pass file handles for stdin, * stdout, and stderr to a new process. Instead, we can make it * a child process and make the given file handles a copy of our * stdin, stdout, and stderr. The child process then inherits * ours, and we set ours back. Twisted and gross I know. If you * know a better way, please use it. */ if (attr->stdinFd) { hStdIn = 0; DosDupHandle(hStdIn, &hStdInSave); DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn); } if (attr->stdoutFd) { hStdOut = 1; DosDupHandle(hStdOut, &hStdOutSave); DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut); } if (attr->stderrFd) { hStdErr = 2; DosDupHandle(hStdErr, &hStdErrSave); DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr); } /* * Build up the Command Line for DosExecPgm */ pszCmdLine = PR_MALLOC(strlen(pszEXEName) + strlen(startData.PgmInputs) + 3); sprintf(pszCmdLine, "%s%c%s%c", pszEXEName, '\0', startData.PgmInputs, '\0'); rc = DosExecPgm(szFailed, CCHMAXPATH, EXEC_ASYNCRESULT, pszCmdLine, envBlock, &procInfo, pszEXEName); PR_DELETE(pszCmdLine); /* Restore our old values. Hope this works */ if (hStdInSave != -1) { DosDupHandle(hStdInSave, &hStdIn); DosClose(hStdInSave); } if (hStdOutSave != -1) { DosDupHandle(hStdOutSave, &hStdOut); DosClose(hStdOutSave); } if (hStdErrSave != -1) { DosDupHandle(hStdErrSave, &hStdErr); DosClose(hStdErrSave); } if (rc != NO_ERROR) { /* XXX what error code? */ PR_SetError(PR_UNKNOWN_ERROR, rc); goto errorExit; } proc->md.pid = procInfo.codeTerminate; } else { /* * If no STDIN/STDOUT redirection is not needed, use DosStartSession * to create a new, independent session */ rc = DosStartSession(&startData, &ulAppType, &pid); if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) { PR_SetError(PR_UNKNOWN_ERROR, rc); goto errorExit; } proc->md.pid = pid; } if (pszFormatResult) { PR_DELETE(pszFormatResult); } PR_DELETE(cmdLine); if (newEnvp) { PR_DELETE(newEnvp); } if (envBlock) { PR_DELETE(envBlock); } return proc; errorExit: if (cmdLine) { PR_DELETE(cmdLine); } if (newEnvp) { PR_DELETE(newEnvp); } if (envBlock) { PR_DELETE(envBlock); } if (proc) { PR_DELETE(proc); } return NULL; } /* _PR_CreateOS2Process */ PRStatus _PR_DetachOS2Process(PRProcess *process) { /* On OS/2, a process is either created as a child or not. * You can't 'detach' it later on. */ PR_DELETE(process); return PR_SUCCESS; } /* * XXX: This will currently only work on a child process. */ PRStatus _PR_WaitOS2Process(PRProcess *process, PRInt32 *exitCode) { ULONG ulRetVal; RESULTCODES results; PID pidEnded = 0; ulRetVal = DosWaitChild(DCWA_PROCESS, DCWW_WAIT, &results, &pidEnded, process->md.pid); if (ulRetVal != NO_ERROR) { printf("\nDosWaitChild rc = %lu\n", ulRetVal); PR_SetError(PR_UNKNOWN_ERROR, ulRetVal); return PR_FAILURE; } PR_DELETE(process); return PR_SUCCESS; } PRStatus _PR_KillOS2Process(PRProcess *process) { ULONG ulRetVal; if ((ulRetVal = DosKillProcess(DKP_PROCESS, process->md.pid)) == NO_ERROR) { return PR_SUCCESS; } PR_SetError(PR_UNKNOWN_ERROR, ulRetVal); return PR_FAILURE; } PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen) { PRIntn rv; rv = gethostname(name, (PRInt32) namelen); if (0 == rv) { return PR_SUCCESS; } _PR_MD_MAP_GETHOSTNAME_ERROR(sock_errno()); return PR_FAILURE; } void _PR_MD_WAKEUP_CPUS( void ) { return; } /* ********************************************************************** * * Memory-mapped files * * A credible emulation of memory-mapped i/o on OS/2 would require * an exception-handler on each thread that might access the mapped * memory. In the Mozilla environment, that would be impractical. * Instead, the following simulates those modes which don't modify * the mapped file. It reads the entire mapped file segment at once * when MemMap is called, and frees it on MemUnmap. CreateFileMap * only does sanity-checks, while CloseFileMap does almost nothing. * ********************************************************************** */ PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) { PRFileInfo64 info; /* assert on PR_PROT_READWRITE which modifies the underlying file */ PR_ASSERT(fmap->prot == PR_PROT_READONLY || fmap->prot == PR_PROT_WRITECOPY); if (fmap->prot != PR_PROT_READONLY && fmap->prot != PR_PROT_WRITECOPY) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } if (PR_GetOpenFileInfo64(fmap->fd, &info) == PR_FAILURE) { return PR_FAILURE; } /* reject zero-byte mappings & zero-byte files */ if (!size || !info.size) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } /* file size rounded up to the next page boundary */ fmap->md.maxExtent = (info.size + 0xfff) & ~(0xfff); return PR_SUCCESS; } PRInt32 _MD_GetMemMapAlignment(void) { /* OS/2 pages are 4k */ return 0x1000; } void * _MD_MemMap(PRFileMap *fmap, PROffset64 offset, PRUint32 len) { PRUint32 rv; void *addr; /* prevent mappings beyond EOF + remainder of page */ if (offset + len > fmap->md.maxExtent) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } if (PR_Seek64(fmap->fd, offset, PR_SEEK_SET) == -1) { return NULL; } /* try for high memory, fall back to low memory if hi-mem fails */ rv = DosAllocMem(&addr, len, OBJ_ANY | PAG_COMMIT | PAG_READ | PAG_WRITE); if (rv) { rv = DosAllocMem(&addr, len, PAG_COMMIT | PAG_READ | PAG_WRITE); if (rv) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, rv); return NULL; } } if (PR_Read(fmap->fd, addr, len) == -1) { DosFreeMem(addr); return NULL; } /* don't permit writes if readonly */ if (fmap->prot == PR_PROT_READONLY) { rv = DosSetMem(addr, len, PAG_READ); if (rv) { DosFreeMem(addr); PR_SetError(PR_UNKNOWN_ERROR, rv); return NULL; } } return addr; } PRStatus _MD_MemUnmap(void *addr, PRUint32 len) { PRUint32 rv; /* we just have to trust that addr & len are those used by MemMap */ rv = DosFreeMem(addr); if (rv) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, rv); return PR_FAILURE; } return PR_SUCCESS; } PRStatus _MD_CloseFileMap(PRFileMap *fmap) { /* nothing to do except free the PRFileMap struct */ PR_Free(fmap); return PR_SUCCESS; } nspr-4.11/nspr/pr/src/md/os2/os2poll.c0000644000000000000000000002365312623070344015614 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file implements _PR_MD_PR_POLL for OS/2. */ #include /* For timeval. */ #include "primpl.h" #ifndef BSD_SELECT /* Utility functions called when using OS/2 select */ PRBool IsSocketSet( PRInt32 osfd, int* socks, int start, int count ) { int i; PRBool isSet = PR_FALSE; for( i = start; i < start+count; i++ ) { if( socks[i] == osfd ) isSet = PR_TRUE; } return isSet; } #endif PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { #ifdef BSD_SELECT fd_set rd, wt, ex; #else int rd, wt, ex; int* socks; unsigned long msecs; int i, j; #endif PRFileDesc *bottom; PRPollDesc *pd, *epd; PRInt32 maxfd = -1, ready, err; PRIntervalTime remaining, elapsed, start; #ifdef BSD_SELECT struct timeval tv, *tvp = NULL; FD_ZERO(&rd); FD_ZERO(&wt); FD_ZERO(&ex); #else rd = 0; wt = 0; ex = 0; socks = (int) PR_MALLOC( npds * 3 * sizeof(int) ); if (!socks) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } #endif ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one's ready right now */ if (0 == ready) { /* * We will have to return without calling the * system poll/select function. So zero the * out_flags fields of all the poll descriptors * before this one. */ PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; pd->out_flags = out_flags_read | out_flags_write; } else { pd->out_flags = 0; /* pre-condition */ /* make sure this is an NSPR supported stack */ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { PRInt32 osfd = bottom->secret->md.osfd; if (osfd > maxfd) maxfd = osfd; if (in_flags_read & PR_POLL_READ) { pd->out_flags |= _PR_POLL_READ_SYS_READ; #ifdef BSD_SELECT FD_SET(osfd, &rd); #else socks[rd] = osfd; rd++; #endif } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; #ifdef BSD_SELECT FD_SET(osfd, &wt); #else socks[npds+wt] = osfd; wt++; #endif } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; #ifdef BSD_SELECT FD_SET(osfd, &rd); #else socks[rd] = osfd; rd++; #endif } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; #ifdef BSD_SELECT FD_SET(osfd, &wt); #else socks[npds+wt] = osfd; wt++; #endif } if (pd->in_flags & PR_POLL_EXCEPT) { #ifdef BSD_SELECT FD_SET(osfd, &ex); #else socks[npds*2+ex] = osfd; ex++; #endif } } } else { if (0 == ready) { PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pd->out_flags = PR_POLL_NVAL; /* bogii */ } } } else { pd->out_flags = 0; } } if (0 != ready) { #ifndef BSD_SELECT PR_Free(socks); #endif return ready; /* no need to block */ } remaining = timeout; start = PR_IntervalNow(); retry: #ifdef BSD_SELECT if (timeout != PR_INTERVAL_NO_TIMEOUT) { PRInt32 ticksPerSecond = PR_TicksPerSecond(); tv.tv_sec = remaining / ticksPerSecond; tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); tvp = &tv; } ready = bsdselect(maxfd + 1, &rd, &wt, &ex, tvp); #else switch (timeout) { case PR_INTERVAL_NO_WAIT: msecs = 0; break; case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break; default: msecs = PR_IntervalToMilliseconds(remaining); } /* compact array */ for( i = rd, j = npds; j < npds+wt; i++,j++ ) socks[i] = socks[j]; for( i = rd+wt, j = npds*2; j < npds*2+ex; i++,j++ ) socks[i] = socks[j]; ready = os2_select(socks, rd, wt, ex, msecs); #endif if (ready == -1 && errno == EINTR) { if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; else { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) ready = 0; /* timed out */ else { remaining = timeout - elapsed; goto retry; } } } /* ** Now to unravel the select sets back into the client's poll ** descriptor list. Is this possibly an area for pissing away ** a few cycles or what? */ if (ready > 0) { ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { PRInt32 osfd; bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); osfd = bottom->secret->md.osfd; #ifdef BSD_SELECT if (FD_ISSET(osfd, &rd)) #else if( IsSocketSet(osfd, socks, 0, rd) ) #endif { if (pd->out_flags & _PR_POLL_READ_SYS_READ) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) out_flags |= PR_POLL_WRITE; } #ifdef BSD_SELECT if (FD_ISSET(osfd, &wt)) #else if( IsSocketSet(osfd, socks, rd, wt) ) #endif { if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) out_flags |= PR_POLL_WRITE; } #ifdef BSD_SELECT if (FD_ISSET(osfd, &ex)) #else if( IsSocketSet(osfd, socks, rd+wt, ex) ) #endif { out_flags |= PR_POLL_EXCEPT; } } pd->out_flags = out_flags; if (out_flags) ready++; } PR_ASSERT(ready > 0); } else if (ready < 0) { err = _MD_ERRNO(); if (err == EBADF) { /* Find the bad fds */ int optval; int optlen = sizeof(optval); ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { pd->out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) == -1) { PR_ASSERT(sock_errno() == ENOTSOCK); if (sock_errno() == ENOTSOCK) { pd->out_flags = PR_POLL_NVAL; ready++; } } } } PR_ASSERT(ready > 0); } else _PR_MD_MAP_SELECT_ERROR(err); } #ifndef BSD_SELECT PR_Free(socks); #endif return ready; } nspr-4.11/nspr/pr/src/md/os2/os2rng.c0000644000000000000000000000343712623070344015432 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #define INCL_DOS #define INCL_DOSERRORS #include #include #include #include "primpl.h" static BOOL clockTickTime(unsigned long *phigh, unsigned long *plow) { APIRET rc = NO_ERROR; QWORD qword = {0,0}; rc = DosTmrQueryTime(&qword); if (rc != NO_ERROR) return FALSE; *phigh = qword.ulHi; *plow = qword.ulLo; return TRUE; } extern PRSize _PR_MD_GetRandomNoise(void *buf, PRSize size ) { unsigned long high = 0; unsigned long low = 0; clock_t val = 0; int n = 0; int nBytes = 0; time_t sTime; if (size <= 0) return 0; clockTickTime(&high, &low); /* get the maximally changing bits first */ nBytes = sizeof(low) > size ? size : sizeof(low); memcpy(buf, &low, nBytes); n += nBytes; size -= nBytes; if (size <= 0) return n; nBytes = sizeof(high) > size ? size : sizeof(high); memcpy(((char *)buf) + n, &high, nBytes); n += nBytes; size -= nBytes; if (size <= 0) return n; /* get the number of milliseconds that have elapsed since application started */ val = clock(); nBytes = sizeof(val) > size ? size : sizeof(val); memcpy(((char *)buf) + n, &val, nBytes); n += nBytes; size -= nBytes; if (size <= 0) return n; /* get the time in seconds since midnight Jan 1, 1970 */ time(&sTime); nBytes = sizeof(sTime) > size ? size : sizeof(sTime); memcpy(((char *)buf) + n, &sTime, nBytes); n += nBytes; return n; } nspr-4.11/nspr/pr/src/md/os2/os2sem.c0000644000000000000000000000224112623070344015420 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * OS/2-specific semaphore handling code. * */ #include "primpl.h" void _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value) { int rv; /* Our Sems don't support a value > 1 */ PR_ASSERT(value <= 1); rv = DosCreateEventSem(NULL, &md->sem, 0, 0); PR_ASSERT(rv == NO_ERROR); } void _PR_MD_DESTROY_SEM(_MDSemaphore *md) { int rv; rv = DosCloseEventSem(md->sem); PR_ASSERT(rv == NO_ERROR); } PRStatus _PR_MD_TIMED_WAIT_SEM(_MDSemaphore *md, PRIntervalTime ticks) { int rv; rv = DosWaitEventSem(md->sem, PR_IntervalToMilliseconds(ticks)); if (rv == NO_ERROR) return PR_SUCCESS; else return PR_FAILURE; } PRStatus _PR_MD_WAIT_SEM(_MDSemaphore *md) { return _PR_MD_TIMED_WAIT_SEM(md, PR_INTERVAL_NO_TIMEOUT); } void _PR_MD_POST_SEM(_MDSemaphore *md) { int rv; rv = DosPostEventSem(md->sem); PR_ASSERT(rv == NO_ERROR); } nspr-4.11/nspr/pr/src/md/os2/os2sock.c0000644000000000000000000004504012623070344015577 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* OS/2 Sockets module * */ /*Note from DSR111297 - it should be noted that there are two flavors of select() on OS/2 */ /*There is standard BSD (which is kind of slow) and a new flavor of select() that takes */ /*an integer list of sockets, the number of read sockets, write sockets, except sockets, and */ /*a millisecond count for timeout. In the interest of performance I have choosen the OS/2 */ /*specific version of select(). See OS/2 TCP/IP Programmer's Toolkit for more info. */ #include "primpl.h" #include /* For timeval. */ #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 #define READ_FD 1 #define WRITE_FD 2 /* --- SOCKET IO --------------------------------------------------------- */ PRInt32 _PR_MD_SOCKET(int domain, int type, int flags) { PRInt32 osfd, err; osfd = socket(domain, type, flags); if (osfd == -1) { err = sock_errno(); _PR_MD_MAP_SOCKET_ERROR(err); } return(osfd); } /* ** _MD_CloseSocket() -- Close a socket ** */ PRInt32 _MD_CloseSocket(PRInt32 osfd) { PRInt32 rv, err; rv = soclose(osfd); if (rv == -1) { err = sock_errno(); _PR_MD_MAP_CLOSE_ERROR(err); } return rv; } PRInt32 _MD_SocketAvailable(PRFileDesc *fd) { PRInt32 result; if (so_ioctl(fd->secret->md.osfd, FIONREAD, (char *) &result, sizeof(result)) < 0) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, sock_errno()); return -1; } return result; } static PRInt32 socket_io_wait( PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout ) { PRInt32 rv = -1; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRInt32 syserror; #ifdef BSD_SELECT struct timeval tv; fd_set rd_wr; #else int socks[1]; long lTimeout; #endif switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ #ifdef BSD_SELECT tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; FD_ZERO(&rd_wr); do { FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); #else lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; do { socks[0] = osfd; if (fd_type == READ_FD) rv = os2_select(socks, 1, 0, 0, lTimeout); else rv = os2_select(socks, 0, 1, 0, lTimeout); #endif if (rv == -1 && (syserror = sock_errno()) != EINTR) { _PR_MD_MAP_SELECT_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; default: now = epoch = PR_IntervalNow(); remaining = timeout; #ifdef BSD_SELECT FD_ZERO(&rd_wr); #endif do { /* * We block in select for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ #ifdef BSD_SELECT wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { tv.tv_usec = PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); } FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = bsdselect(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = bsdselect(osfd + 1, NULL, &rd_wr, NULL, &tv); #else wait_for_remaining = PR_TRUE; lTimeout = PR_IntervalToMilliseconds(remaining); if (lTimeout > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { wait_for_remaining = PR_FALSE; lTimeout = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; } socks[0] = osfd; if (fd_type == READ_FD) rv = os2_select(socks, 1, 0, 0, lTimeout); else rv = os2_select(socks, 0, 1, 0, lTimeout); #endif /* * we don't consider EINTR a real error */ if (rv == -1 && (syserror = sock_errno()) != EINTR) { _PR_MD_MAP_SELECT_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * We loop again if select timed out or got interrupted * by a signal, and the timeout deadline has not passed yet. */ if (rv == 0 || (rv == -1 && syserror == EINTR)) { /* * If select timed out, we know how much time * we spent in blocking, so we can avoid a * PR_IntervalNow() call. */ if (rv == 0) { if (wait_for_remaining) { now += remaining; } else { #ifdef BSD_SELECT now += PR_SecondsToInterval(tv.tv_sec) + PR_MicrosecondsToInterval(tv.tv_usec); #else now += PR_MillisecondsToInterval(lTimeout); #endif } } else { now = PR_IntervalNow(); } elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = timeout - elapsed; } } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; } return(rv); } PRInt32 _MD_Accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = accept(osfd, (struct sockaddr*) addr, (int*)addrlen)) == -1) { err = sock_errno(); if ((err == EWOULDBLOCK) || (err == ECONNABORTED)) { if (fd->secret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_ACCEPT_ERROR(err); } done: return(rv); } PRInt32 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 osfd = fd->secret->md.osfd; PRNetAddr addrCopy = *addr; /* Work around a bug in OS/2 where connect * modifies the sockaddr structure. * See Bugzilla bug 100776. */ /* * We initiate the connection setup by making a nonblocking connect() * call. If the connect() call fails, there are two cases we handle * specially: * 1. The connect() call was interrupted by a signal. In this case * we simply retry connect(). * 2. The NSPR socket is nonblocking and connect() fails with * EINPROGRESS. We first wait until the socket becomes writable. * Then we try to find out whether the connection setup succeeded * or failed. */ retry: if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) { err = sock_errno(); if (err == EINTR) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } goto retry; } if (!fd->secret->nonblocking && (err == EINPROGRESS)) { /* * socket_io_wait() may return -1 or 1. */ rv = socket_io_wait(osfd, WRITE_FD, timeout); if (rv == -1) { return -1; } PR_ASSERT(rv == 1); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } err = _MD_os2_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return -1; } return 0; } _PR_MD_MAP_CONNECT_ERROR(err); } return rv; } /* _MD_connect */ PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv, err; rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); if (rv < 0) { err = sock_errno(); _PR_MD_MAP_BIND_ERROR(err); } return(rv); } PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) { PRInt32 rv, err; rv = listen(fd->secret->md.osfd, backlog); if (rv < 0) { err = sock_errno(); _PR_MD_MAP_DEFAULT_ERROR(err); } return(rv); } PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = recv(osfd,buf,amount,flags)) == -1) { err = sock_errno(); if ((err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECV_ERROR(err); } done: return(rv); } PRInt32 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = send(osfd,buf,amount,flags)) == -1) { err = sock_errno(); if ((err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next send() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) { rv = -1; goto done; } } if (rv < 0) { _PR_MD_MAP_SEND_ERROR(err); } done: return(rv); } PRInt32 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) addr, addrlen)) == -1) { err = sock_errno(); if ((err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, WRITE_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_SENDTO_ERROR(err); } done: return(rv); } PRInt32 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while( (*addrlen = PR_NETADDR_SIZE(addr)), ((rv = recvfrom(osfd, buf, amount, flags, (struct sockaddr *) addr, (int *)addrlen)) == -1)) { err = sock_errno(); if ((err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECVFROM_ERROR(err); } done: return(rv); } PRInt32 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 index, amount = 0; PRInt32 osfd = fd->secret->md.osfd; struct iovec osiov[PR_MAX_IOVECTOR_SIZE]; /* Ensured by PR_Writev */ PR_ASSERT(iov_size <= PR_MAX_IOVECTOR_SIZE); /* * We can't pass iov to so_writev because PRIOVec and struct iovec * may not be binary compatible. Make osiov a copy of iov and * pass osiov to so_writev . */ for (index = 0; index < iov_size; index++) { osiov[index].iov_base = iov[index].iov_base; osiov[index].iov_len = iov[index].iov_len; } /* * Calculate the total number of bytes to be sent; needed for * optimization later. * We could avoid this if this number was passed in; but it is * probably not a big deal because iov_size is usually small (less than * 3) */ if (!fd->secret->nonblocking) { for (index=0; indexsecret->nonblocking) { break; } if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) goto done; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next writev() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { rv = -1; goto done; } } if (rv < 0) { _PR_MD_MAP_WRITEV_ERROR(err); } done: return(rv); } PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) { PRInt32 rv; rv = shutdown(fd->secret->md.osfd, how); if (rv < 0) _PR_MD_MAP_SHUTDOWN_ERROR(sock_errno()); return rv; } PRInt32 _PR_MD_SOCKETPAIR(int af, int type, int flags, PRInt32 *osfd) { PRInt32 rv, err; rv = socketpair(af, type, flags, osfd); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKETPAIR_ERROR(err); } return rv; } PRStatus _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 rv, err; rv = getsockname(fd->secret->md.osfd, (struct sockaddr *) addr, (int *)addrlen); if (rv < 0) { err = sock_errno(); _PR_MD_MAP_GETSOCKNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 rv, err; rv = getpeername(fd->secret->md.osfd, (struct sockaddr *) addr, (int *)addrlen); if (rv < 0) { err = sock_errno(); _PR_MD_MAP_GETPEERNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) { PRInt32 rv, err; rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (int *)optlen); if (rv < 0) { err = sock_errno(); _PR_MD_MAP_GETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen) { PRInt32 rv, err; rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); if (rv < 0) { err = sock_errno(); _PR_MD_MAP_SETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } void _MD_MakeNonblock(PRFileDesc *fd) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 err; PRUint32 one = 1; if (osfd <= 2) { /* Don't mess around with stdin, stdout or stderr */ return; } err = so_ioctl( osfd, FIONBIO, (char *) &one, sizeof(one)); if ( err != 0 ) { err = sock_errno(); _PR_MD_MAP_SOCKET_ERROR(err); } } nspr-4.11/nspr/pr/src/md/os2/os2thred.c0000644000000000000000000002176012623070344015751 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* for _beginthread() */ #include #include /* --- globals ------------------------------------------------ */ _NSPR_TLS* pThreadLocalStorage = 0; _PRInterruptTable _pr_interruptTable[] = { { 0 } }; APIRET (* APIENTRY QueryThreadContext)(TID, ULONG, PCONTEXTRECORD); void _PR_MD_ENSURE_TLS(void) { if(!pThreadLocalStorage) { /* Allocate thread local storage (TLS). Note, that only 32 bytes can * be allocated at a time. */ int rc = DosAllocThreadLocalMemory(sizeof(_NSPR_TLS) / 4, (PULONG*)&pThreadLocalStorage); PR_ASSERT(rc == NO_ERROR); memset(pThreadLocalStorage, 0, sizeof(_NSPR_TLS)); } } void _PR_MD_EARLY_INIT() { HMODULE hmod; if (DosLoadModule(NULL, 0, "DOSCALL1", &hmod) == 0) DosQueryProcAddr(hmod, 877, "DOSQUERYTHREADCONTEXT", (PFN *)&QueryThreadContext); } static void _pr_SetThreadMDHandle(PRThread *thread) { PTIB ptib; PPIB ppib; PRUword rc; rc = DosGetInfoBlocks(&ptib, &ppib); thread->md.handle = ptib->tib_ptib2->tib2_ultid; } /* On OS/2, some system function calls seem to change the FPU control word, * such that we crash with a floating underflow exception. The FIX_FPU() call * in jsnum.c does not always work, as sometimes FIX_FPU() is called BEFORE the * OS/2 system call that horks the FPU control word. So, we set an exception * handler that covers any floating point exceptions and resets the FPU CW to * the required value. */ static ULONG _System OS2_FloatExcpHandler(PEXCEPTIONREPORTRECORD p1, PEXCEPTIONREGISTRATIONRECORD p2, PCONTEXTRECORD p3, PVOID pv) { #ifdef DEBUG_pedemonte printf("Entering exception handler; ExceptionNum = %x\n", p1->ExceptionNum); switch(p1->ExceptionNum) { case XCPT_FLOAT_DENORMAL_OPERAND: printf("got XCPT_FLOAT_DENORMAL_OPERAND\n"); break; case XCPT_FLOAT_DIVIDE_BY_ZERO: printf("got XCPT_FLOAT_DIVIDE_BY_ZERO\n"); break; case XCPT_FLOAT_INEXACT_RESULT: printf("got XCPT_FLOAT_INEXACT_RESULT\n"); break; case XCPT_FLOAT_INVALID_OPERATION: printf("got XCPT_FLOAT_INVALID_OPERATION\n"); break; case XCPT_FLOAT_OVERFLOW: printf("got XCPT_FLOAT_OVERFLOW\n"); break; case XCPT_FLOAT_STACK_CHECK: printf("got XCPT_FLOAT_STACK_CHECK\n"); break; case XCPT_FLOAT_UNDERFLOW: printf("got XCPT_FLOAT_UNDERFLOW\n"); break; } #endif switch(p1->ExceptionNum) { case XCPT_FLOAT_DENORMAL_OPERAND: case XCPT_FLOAT_DIVIDE_BY_ZERO: case XCPT_FLOAT_INEXACT_RESULT: case XCPT_FLOAT_INVALID_OPERATION: case XCPT_FLOAT_OVERFLOW: case XCPT_FLOAT_STACK_CHECK: case XCPT_FLOAT_UNDERFLOW: { unsigned cw = p3->ctx_env[0]; if ((cw & MCW_EM) != MCW_EM) { /* Mask out all floating point exceptions */ p3->ctx_env[0] |= MCW_EM; /* Following two lines set precision to 53 bit mantissa. See jsnum.c */ p3->ctx_env[0] &= ~MCW_PC; p3->ctx_env[0] |= PC_53; return XCPT_CONTINUE_EXECUTION; } } } return XCPT_CONTINUE_SEARCH; } PR_IMPLEMENT(void) PR_OS2_SetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg) { /* setup the exception handler for the thread */ APIRET rv; excpreg->ExceptionHandler = OS2_FloatExcpHandler; excpreg->prev_structure = NULL; rv = DosSetExceptionHandler(excpreg); PR_ASSERT(rv == NO_ERROR); } PR_IMPLEMENT(void) PR_OS2_UnsetFloatExcpHandler(EXCEPTIONREGISTRATIONRECORD* excpreg) { /* unset exception handler */ APIRET rv = DosUnsetExceptionHandler(excpreg); PR_ASSERT(rv == NO_ERROR); } PRStatus _PR_MD_INIT_THREAD(PRThread *thread) { APIRET rv; if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) { _pr_SetThreadMDHandle(thread); } /* Create the blocking IO semaphore */ rv = DosCreateEventSem(NULL, &(thread->md.blocked_sema), 0, 0); return (rv == NO_ERROR) ? PR_SUCCESS : PR_FAILURE; } typedef struct param_store { void (*start)(void *); PRThread* thread; } PARAMSTORE; /* This is a small intermediate function that sets/unsets the exception handler before calling the initial thread function */ static void ExcpStartFunc(void* arg) { EXCEPTIONREGISTRATIONRECORD excpreg; PARAMSTORE params, *pParams = arg; PR_OS2_SetFloatExcpHandler(&excpreg); params = *pParams; PR_Free(pParams); params.start(params.thread); PR_OS2_UnsetFloatExcpHandler(&excpreg); } PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PARAMSTORE* params = PR_Malloc(sizeof(PARAMSTORE)); params->start = start; params->thread = thread; thread->md.handle = thread->id = (TID) _beginthread(ExcpStartFunc, NULL, thread->stack->stackSize, params); if(thread->md.handle == -1) { return PR_FAILURE; } /* * On OS/2, a thread is created with a thread priority of * THREAD_PRIORITY_NORMAL */ if (priority != PR_PRIORITY_NORMAL) { _PR_MD_SET_PRIORITY(&(thread->md), priority); } return PR_SUCCESS; } void _PR_MD_YIELD(void) { /* Isn't there some problem with DosSleep(0) on OS/2? */ DosSleep(0); } void _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri) { int nativePri = PRTYC_NOCHANGE; BOOL rv; if (newPri < PR_PRIORITY_FIRST) { newPri = PR_PRIORITY_FIRST; } else if (newPri > PR_PRIORITY_LAST) { newPri = PR_PRIORITY_LAST; } switch (newPri) { case PR_PRIORITY_LOW: case PR_PRIORITY_NORMAL: nativePri = PRTYC_REGULAR; break; case PR_PRIORITY_HIGH: nativePri = PRTYC_FOREGROUNDSERVER; break; case PR_PRIORITY_URGENT: nativePri = PRTYC_TIMECRITICAL; } rv = DosSetPriority(PRTYS_THREAD, nativePri, 0, thread->handle); PR_ASSERT(rv == NO_ERROR); if (rv != NO_ERROR) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_SetThreadPriority: can't set thread priority\n")); } return; } void _PR_MD_CLEAN_THREAD(PRThread *thread) { APIRET rv; if (thread->md.blocked_sema) { rv = DosCloseEventSem(thread->md.blocked_sema); PR_ASSERT(rv == NO_ERROR); thread->md.blocked_sema = 0; } if (thread->md.handle) { thread->md.handle = 0; } } void _PR_MD_EXIT_THREAD(PRThread *thread) { _PR_MD_CLEAN_THREAD(thread); _PR_MD_SET_CURRENT_THREAD(NULL); } void _PR_MD_EXIT(PRIntn status) { _exit(status); } #ifdef HAVE_THREAD_AFFINITY PR_EXTERN(PRInt32) _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ) { /* Can we do this on OS/2? Only on SMP versions? */ PR_NOT_REACHED("Not implemented"); return 0; /* This is what windows does: int rv; rv = SetThreadAffinityMask(thread->md.handle, mask); return rv?0:-1; */ } PR_EXTERN(PRInt32) _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask) { /* Can we do this on OS/2? Only on SMP versions? */ PR_NOT_REACHED("Not implemented"); return 0; /* This is what windows does: PRInt32 rv, system_mask; rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask); return rv?0:-1; */ } #endif /* HAVE_THREAD_AFFINITY */ void _PR_MD_SUSPEND_CPU(_PRCPU *cpu) { _PR_MD_SUSPEND_THREAD(cpu->thread); } void _PR_MD_RESUME_CPU(_PRCPU *cpu) { _PR_MD_RESUME_THREAD(cpu->thread); } void _PR_MD_SUSPEND_THREAD(PRThread *thread) { if (_PR_IS_NATIVE_THREAD(thread)) { APIRET rc; /* XXXMB - DosSuspendThread() is not a blocking call; how do we * know when the thread is *REALLY* suspended? */ rc = DosSuspendThread(thread->md.handle); PR_ASSERT(rc == NO_ERROR); } } void _PR_MD_RESUME_THREAD(PRThread *thread) { if (_PR_IS_NATIVE_THREAD(thread)) { DosResumeThread(thread->md.handle); } } PRThread* _MD_CURRENT_THREAD(void) { PRThread *thread; thread = _MD_GET_ATTACHED_THREAD(); if (NULL == thread) { thread = _PRI_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0); } PR_ASSERT(thread != NULL); return thread; } nspr-4.11/nspr/pr/src/md/os2/os2vaclegacy.s0000644000000000000000000000166212623070344016620 0ustar 00000000000000/ -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- / / This Source Code Form is subject to the terms of the Mozilla Public / License, v. 2.0. If a copy of the MPL was not distributed with this / file, You can obtain one at http://mozilla.org/MPL/2.0/. .text .align 4 .globl PR_NewMonitor PR_NewMonitor: jmp _PR_NewMonitor .align 4 .globl PR_EnterMonitor PR_EnterMonitor: mov %eax, 4(%esp) jmp _PR_EnterMonitor .align 4 .globl PR_ExitMonitor PR_ExitMonitor: mov %eax, 4(%esp) jmp _PR_ExitMonitor .align 4 .globl PR_AttachThread PR_AttachThread: mov %eax, 4(%esp) mov %edx, 8(%esp) mov %ecx, 12(%esp) jmp _PR_AttachThread .align 4 .globl PR_DetachThread PR_DetachThread: jmp _PR_DetachThread .align 4 .globl PR_GetCurrentThread PR_GetCurrentThread: jmp _PR_GetCurrentThread nspr-4.11/nspr/pr/src/md/prosdep.c0000644000000000000000000000307412623070344015166 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prbit.h" #include "prsystem.h" #ifdef XP_UNIX #include #endif #ifdef _WIN32 #include #endif #ifdef XP_BEOS #include #endif PRInt32 _pr_pageShift; PRInt32 _pr_pageSize; /* ** Get system page size */ static void GetPageSize(void) { PRInt32 pageSize; /* Get page size */ #ifdef XP_UNIX #if defined BSDI || defined AIX \ || defined LINUX || defined __GNU__ || defined __GLIBC__ \ || defined FREEBSD || defined NETBSD || defined OPENBSD \ || defined DARWIN || defined SYMBIAN _pr_pageSize = getpagesize(); #elif defined(HPUX) /* I have no idea. Don't get me started. --Rob */ _pr_pageSize = sysconf(_SC_PAGE_SIZE); #else _pr_pageSize = sysconf(_SC_PAGESIZE); #endif #endif /* XP_UNIX */ #ifdef XP_BEOS _pr_pageSize = B_PAGE_SIZE; #endif #ifdef XP_PC #ifdef _WIN32 SYSTEM_INFO info; GetSystemInfo(&info); _pr_pageSize = info.dwPageSize; #else _pr_pageSize = 4096; #endif #endif /* XP_PC */ pageSize = _pr_pageSize; PR_CEILING_LOG2(_pr_pageShift, pageSize); } PR_IMPLEMENT(PRInt32) PR_GetPageShift(void) { if (!_pr_pageSize) { GetPageSize(); } return _pr_pageShift; } PR_IMPLEMENT(PRInt32) PR_GetPageSize(void) { if (!_pr_pageSize) { GetPageSize(); } return _pr_pageSize; } nspr-4.11/nspr/pr/src/md/unix/.cvsignore0000644000000000000000000000001112623070344016315 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/md/unix/Makefile.in0000644000000000000000000000476012623070344016401 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = \ unix.c \ unix_errors.c \ uxproces.c \ uxrng.c \ uxshm.c \ uxwrap.c \ $(NULL) ifneq ($(USE_PTHREADS),1) CSRCS += uxpoll.c endif ifeq ($(PTHREADS_USER),1) CSRCS += pthreads_user.c endif CSRCS += $(PR_MD_CSRCS) ASFILES += $(PR_MD_ASFILES) TARGETS = $(OBJS) ifeq ($(OS_ARCH),SunOS) ifeq ($(CPU_ARCH),sparc) ifdef USE_64 ULTRASPARC_ASFILES = os_SunOS_sparcv9.s ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX))) else LIBRARY_NAME = $(ULTRASPARC_LIBRARY) LIBRARY_VERSION = $(MOD_MAJOR_VERSION) ULTRASPARC_ASFILES = os_SunOS_ultrasparc.s ULTRASPARC_ASOBJS = $(addprefix $(OBJDIR)/,$(ULTRASPARC_ASFILES:.s=.$(OBJ_SUFFIX))) TARGETS += $(ULTRASPARC_ASOBJS) $(SHARED_LIBRARY) RELEASE_LIBS = $(SHARED_LIBRARY) RELEASE_LIBS_DEST = $(RELEASE_LIB_DIR)/cpu/sparcv8plus lib_subdir = cpu/sparcv8plus endif endif endif INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) ifeq ($(OS_ARCH),SunOS) ifeq ($(CPU_ARCH),sparc) ifdef USE_64 $(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES) /usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v9 $< else $(SHARED_LIBRARY): $(ULTRASPARC_ASOBJS) $(LD) -G -z text -z endfiltee -o $@ $(ULTRASPARC_ASOBJS) $(INSTALL) -m 444 $@ $(dist_libdir)/cpu/sparcv8plus $(INSTALL) -m 444 $@ $(dist_bindir)/cpu/sparcv8plus # # The -f $(ORIGIN)/... linker flag uses the real file, after symbolic links # are resolved, as the origin. If NSDISTMODE is not "copy", libnspr4.so # will be installed as a symbolic link in $(dist_libdir), pointing to the # real libnspr4.so file in pr/src. Therefore we need to install an # additional copy of libnspr_flt4.so in pr/src/cpu/sparcv8plus. # ifneq ($(NSDISTMODE),copy) $(INSTALL) -m 444 $@ ../../cpu/sparcv8plus endif ifneq ($(NSDISTMODE),copy) clobber realclean clobber_all distclean:: rm -rf ../../cpu endif $(ULTRASPARC_ASOBJS): $(ULTRASPARC_ASFILES) /usr/ccs/bin/as -o $@ -K PIC -P -D_ASM -D__STDC__=0 -xarch=v8plus $< clean:: rm -rf $(ULTRASPARC_ASOBJS) endif endif endif nspr-4.11/nspr/pr/src/md/unix/aix.c0000644000000000000000000001574212623070344015263 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #ifdef AIX_HAVE_ATOMIC_OP_H #include PRInt32 _AIX_AtomicSet(PRInt32 *val, PRInt32 newval) { PRIntn oldval; boolean_t stored; oldval = fetch_and_add((atomic_p)val, 0); do { stored = compare_and_swap((atomic_p)val, &oldval, newval); } while (!stored); return oldval; } /* _AIX_AtomicSet */ #endif /* AIX_HAVE_ATOMIC_OP_H */ #if defined(AIX_TIMERS) #include static PRUint32 _aix_baseline_epoch; static void _MD_AixIntervalInit(void) { timebasestruct_t real_time; read_real_time(&real_time, TIMEBASE_SZ); (void)time_base_to_time(&real_time, TIMEBASE_SZ); _aix_baseline_epoch = real_time.tb_high; } /* _MD_AixIntervalInit */ PRIntervalTime _MD_AixGetInterval(void) { PRIntn rv; PRUint64 temp; timebasestruct_t real_time; read_real_time(&real_time, TIMEBASE_SZ); (void)time_base_to_time(&real_time, TIMEBASE_SZ); /* tb_high is in seconds, tb_low in 10(-9)seconds */ temp = 1000000000ULL * (PRUint64)(real_time.tb_high - _aix_baseline_epoch); temp += (PRUint64)real_time.tb_low; /* everything's 10(-9) seconds */ temp >>= 16; /* now it's something way different */ return (PRIntervalTime)temp; } /* _MD_AixGetInterval */ PRIntervalTime _MD_AixIntervalPerSec(void) { return 1000000000ULL >> 16; /* that's 15258, I think */ } /* _MD_AixIntervalPerSec */ #endif /* defined(AIX_TIMERS) */ #if !defined(PTHREADS_USER) #if defined(_PR_PTHREADS) /* * AIX 4.3 has sched_yield(). AIX 4.2 has pthread_yield(). * So we look up the appropriate function pointer at run time. */ #include int (*_PT_aix_yield_fcn)() = NULL; int _pr_aix_send_file_use_disabled = 0; void _MD_EarlyInit(void) { void *main_app_handle; char *evp; main_app_handle = dlopen(NULL, RTLD_NOW); PR_ASSERT(NULL != main_app_handle); _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle, "sched_yield"); if (!_PT_aix_yield_fcn) { _PT_aix_yield_fcn = (int(*)())dlsym(main_app_handle,"pthread_yield"); PR_ASSERT(NULL != _PT_aix_yield_fcn); } dlclose(main_app_handle); if (evp = getenv("NSPR_AIX_SEND_FILE_USE_DISABLED")) { if (1 == atoi(evp)) _pr_aix_send_file_use_disabled = 1; } #if defined(AIX_TIMERS) _MD_AixIntervalInit(); #endif } #else /* _PR_PTHREADS */ void _MD_EarlyInit(void) { #if defined(AIX_TIMERS) _MD_AixIntervalInit(); #endif } #endif /* _PR_PTHREADS */ PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS PR_IMPLEMENT(void) _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PR_IMPLEMENT(PRStatus) _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for AIX */ PR_IMPLEMENT(void) _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for AIX."); } PR_IMPLEMENT(PRStatus) _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for AIX."); } #endif /* _PR_PTHREADS */ #endif /* PTHREADS_USER */ /* * NSPR 2.0 overrides the system select() and poll() functions. * On AIX 4.2, we use dlopen("/unix", RTLD_NOW) and dlsym() to get * at the original system select() and poll() functions. */ #if !defined(AIX_RENAME_SELECT) #include #include #include static int (*aix_select_fcn)() = NULL; static int (*aix_poll_fcn)() = NULL; int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) { int rv; if (!aix_select_fcn) { void *aix_handle; aix_handle = dlopen("/unix", RTLD_NOW); if (!aix_handle) { PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } aix_select_fcn = (int(*)())dlsym(aix_handle,"select"); dlclose(aix_handle); if (!aix_select_fcn) { PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } } rv = (*aix_select_fcn)(width, r, w, e, t); return rv; } int _MD_POLL(void *listptr, unsigned long nfds, long timeout) { int rv; if (!aix_poll_fcn) { void *aix_handle; aix_handle = dlopen("/unix", RTLD_NOW); if (!aix_handle) { PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } aix_poll_fcn = (int(*)())dlsym(aix_handle,"poll"); dlclose(aix_handle); if (!aix_poll_fcn) { PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } } rv = (*aix_poll_fcn)(listptr, nfds, timeout); return rv; } #else /* * In AIX versions prior to 4.2, we use the two-step rename/link trick. * The binary must contain at least one "poll" symbol for linker's rename * to work. So we must have this dummy function that references poll(). */ #include void _pr_aix_dummy() { poll(0,0,0); } #endif /* !defined(AIX_RENAME_SELECT) */ #ifdef _PR_HAVE_ATOMIC_CAS #include "pratom.h" #define _PR_AIX_ATOMIC_LOCK -1 PR_IMPLEMENT(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem) { PRStackElem *addr; boolean_t locked = TRUE; /* Is it safe to cast a pointer to an int? */ PR_ASSERT(sizeof(int) == sizeof(PRStackElem *)); do { while ((addr = stack->prstk_head.prstk_elem_next) == (PRStackElem *)_PR_AIX_ATOMIC_LOCK) ; locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next, (int) addr, _PR_AIX_ATOMIC_LOCK); } while (locked == TRUE); stack_elem->prstk_elem_next = addr; _clear_lock((atomic_p)&stack->prstk_head.prstk_elem_next, (int)stack_elem); return; } PR_IMPLEMENT(PRStackElem *) PR_StackPop(PRStack *stack) { PRStackElem *element; boolean_t locked = TRUE; /* Is it safe to cast a pointer to an int? */ PR_ASSERT(sizeof(int) == sizeof(PRStackElem *)); do { while ((element = stack->prstk_head.prstk_elem_next) == (PRStackElem *) _PR_AIX_ATOMIC_LOCK) ; locked = _check_lock((atomic_p) &stack->prstk_head.prstk_elem_next, (int)element, _PR_AIX_ATOMIC_LOCK); } while (locked == TRUE); if (element == NULL) { _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, NULL); } else { _clear_lock((atomic_p) &stack->prstk_head.prstk_elem_next, (int) element->prstk_elem_next); } return element; } #endif /* _PR_HAVE_ATOMIC_CAS */ nspr-4.11/nspr/pr/src/md/unix/aixwrap.c0000644000000000000000000000200412623070344016140 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: aixwrap.c * Description: * This file contains a single function, _MD_SELECT(), which simply * invokes the select() function. This file is used in an ugly * hack to override the system select() function on AIX releases * prior to 4.2. (On AIX 4.2, we use a different mechanism to * override select().) */ #ifndef AIX_RENAME_SELECT #error aixwrap.c should only be used on AIX 3.2 or 4.1 #else #include #include int _MD_SELECT(int width, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) { return select(width, r, w, e, t); } int _MD_POLL(void *listptr, unsigned long nfds, long timeout) { return poll(listptr, nfds, timeout); } #endif /* AIX_RENAME_SELECT */ nspr-4.11/nspr/pr/src/md/unix/bsdi.c0000644000000000000000000000343312623070344015415 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include void _MD_EarlyInit(void) { /* * Ignore FPE because coercion of a NaN to an int causes SIGFPE * to be raised. */ struct sigaction act; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGFPE, &act, 0); } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for BSDI */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for BSDI."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for BSDI."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/darwin.c0000644000000000000000000000451412623070344015761 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include void _MD_EarlyInit(void) { } /* * The multiplier (as a fraction) for converting the Mach absolute time * unit to nanoseconds. */ static mach_timebase_info_data_t machTimebaseInfo; void _PR_Mach_IntervalInit(void) { kern_return_t rv; rv = mach_timebase_info(&machTimebaseInfo); PR_ASSERT(rv == KERN_SUCCESS); } PRIntervalTime _PR_Mach_GetInterval(void) { uint64_t time; /* * mach_absolute_time returns the time in the Mach absolute time unit. * Convert it to milliseconds. See Mac Technical Q&A QA1398. */ time = mach_absolute_time(); time = time * machTimebaseInfo.numer / machTimebaseInfo.denom / PR_NSEC_PER_MSEC; return (PRIntervalTime)time; } /* _PR_Mach_GetInterval */ PRIntervalTime _PR_Mach_TicksPerSecond(void) { return 1000; } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #if !defined(_PR_PTHREADS) if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #if !defined(_PR_PTHREADS) void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for Darwin */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for Darwin."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Darwin."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ /* darwin.c */ nspr-4.11/nspr/pr/src/md/unix/dgux.c0000644000000000000000000000310212623070344015434 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /* * using only NSPR threads here * * Copied from the UnixWare implementation. Should be kept in sync * with ../../../include/md/_dgux.h. */ #include void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); } void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for DG/UX */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for DG/UX."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for DG/UX."); } nspr-4.11/nspr/pr/src/md/unix/freebsd.c0000644000000000000000000000344412623070344016110 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include void _MD_EarlyInit(void) { /* * Ignore FPE because coercion of a NaN to an int causes SIGFPE * to be raised. */ struct sigaction act; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGFPE, &act, 0); } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) sigsetjmp(CONTEXT(t), 1); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for FreeBSD */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for FreeBSD."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for FreeBSD."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/hpux.c0000644000000000000000000001332212623070344015456 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #if defined(HPUX_LW_TIMER) #include #include #include #include #include int __lw_get_thread_times(int which, int64_t *sample, int64_t *time); static double msecond_per_itick; void _PR_HPUX_LW_IntervalInit(void) { struct pst_processor psp; int iticksperclktick, clk_tck; int rv; rv = pstat_getprocessor(&psp, sizeof(psp), 1, 0); PR_ASSERT(rv != -1); iticksperclktick = psp.psp_iticksperclktick; clk_tck = sysconf(_SC_CLK_TCK); msecond_per_itick = (1000.0)/(double)(iticksperclktick * clk_tck); } PRIntervalTime _PR_HPUX_LW_GetInterval(void) { int64_t time, sample; __lw_get_thread_times(1, &sample, &time); /* * Division is slower than float multiplication. * return (time / iticks_per_msecond); */ return (time * msecond_per_itick); } #endif /* HPUX_LW_TIMER */ #if !defined(PTHREADS_USER) void _MD_EarlyInit(void) { #ifndef _PR_PTHREADS /* * The following piece of code is taken from ns/nspr/src/md_HP-UX.c. * In the comment for revision 1.6, dated 1995/09/11 23:33:34, * robm says: * This version has some problems which need to be addressed. * First, intercept all system calls and prevent them from * executing the library code which performs stack switches * before normal system call invocation. In order for library * calls which make system calls to work (like stdio), however, * we must also allocate our own stack and switch the primordial * stack to use it. This isn't so bad, except that I fudged the * backtrace length when copying the old stack to the new one. * * This is the original comment of robm in the code: * XXXrobm Horrific. To avoid a problem with HP's system call * code, we allocate a new stack for the primordial thread and * use it. However, we don't know how far back the original stack * goes. We should create a routine that performs a backtrace and * finds out just how much we need to copy. As a temporary measure, * I just copy an arbitrary guess. * * In an email to servereng dated 2 Jan 1997, Mike Patnode (mikep) * suggests that this only needs to be done for HP-UX 9. */ #ifdef HPUX9 #define PIDOOMA_STACK_SIZE 524288 #define BACKTRACE_SIZE 8192 { jmp_buf jb; char *newstack; char *oldstack; if(!setjmp(jb)) { newstack = (char *) PR_MALLOC(PIDOOMA_STACK_SIZE); oldstack = (char *) (*(((int *) jb) + 1) - BACKTRACE_SIZE); memcpy(newstack, oldstack, BACKTRACE_SIZE); *(((int *) jb) + 1) = (int) (newstack + BACKTRACE_SIZE); longjmp(jb, 1); } } #endif /* HPUX9 */ #endif /* !_PR_PTHREADS */ } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for HP-UX */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for HP-UX."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for HP-UX."); } #endif /* _PR_PTHREADS */ void _MD_suspend_thread(PRThread *thread) { #ifdef _PR_PTHREADS #endif } void _MD_resume_thread(PRThread *thread) { #ifdef _PR_PTHREADS #endif } #endif /* PTHREADS_USER */ /* * The HP version of strchr is buggy. It looks past the end of the * string and causes a segmentation fault when our (NSPR) version * of malloc is used. * * A better solution might be to put a cushion in our malloc just in * case HP's version of strchr somehow gets used instead of this one. */ char * strchr(const char *s, int c) { char ch; if (!s) { return NULL; } ch = (char) c; while ((*s) && ((*s) != ch)) { s++; } if ((*s) == ch) { return (char *) s; } return NULL; } /* * Implemementation of memcmp in HP-UX (verified on releases A.09.03, * A.09.07, and B.10.10) dumps core if called with: * 1. First operand with address = 1(mod 4). * 2. Size = 1(mod 4) * 3. Last byte of the second operand is the last byte of the page and * next page is not accessible(not mapped or protected) * Thus, using the following naive version (tons of optimizations are * possible;^) */ int memcmp(const void *s1, const void *s2, size_t n) { register unsigned char *p1 = (unsigned char *) s1, *p2 = (unsigned char *) s2; while (n-- > 0) { register int r = ((int) ((unsigned int) *p1)) - ((int) ((unsigned int) *p2)); if (r) return r; p1++; p2++; } return 0; } nspr-4.11/nspr/pr/src/md/unix/irix.c0000644000000000000000000012111512623070344015445 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void _MD_IrixIntervalInit(void); #if defined(_PR_PTHREADS) /* * for compatibility with classic nspr */ void _PR_IRIX_CHILD_PROCESS() { } #else /* defined(_PR_PTHREADS) */ static void irix_detach_sproc(void); char *_nspr_sproc_private; /* ptr. to private region in every sproc */ extern PRUintn _pr_numCPU; typedef struct nspr_arena { PRCList links; usptr_t *usarena; } nspr_arena; #define ARENA_PTR(qp) \ ((nspr_arena *) ((char*) (qp) - offsetof(nspr_arena , links))) static usptr_t *alloc_new_arena(void); PRCList arena_list = PR_INIT_STATIC_CLIST(&arena_list); ulock_t arena_list_lock; nspr_arena first_arena; int _nspr_irix_arena_cnt = 1; PRCList sproc_list = PR_INIT_STATIC_CLIST(&sproc_list); ulock_t sproc_list_lock; typedef struct sproc_data { void (*entry) (void *, size_t); unsigned inh; void *arg; caddr_t sp; size_t len; int *pid; int creator_pid; } sproc_data; typedef struct sproc_params { PRCList links; sproc_data sd; } sproc_params; #define SPROC_PARAMS_PTR(qp) \ ((sproc_params *) ((char*) (qp) - offsetof(sproc_params , links))) long _nspr_irix_lock_cnt = 0; long _nspr_irix_sem_cnt = 0; long _nspr_irix_pollsem_cnt = 0; usptr_t *_pr_usArena; ulock_t _pr_heapLock; usema_t *_pr_irix_exit_sem; PRInt32 _pr_irix_exit_now = 0; PRInt32 _pr_irix_process_exit_code = 0; /* exit code for PR_ProcessExit */ PRInt32 _pr_irix_process_exit = 0; /* process exiting due to call to PR_ProcessExit */ int _pr_irix_primoridal_cpu_fd[2] = { -1, -1 }; static void (*libc_exit)(int) = NULL; static void *libc_handle = NULL; #define _NSPR_DEF_INITUSERS 100 /* default value of CONF_INITUSERS */ #define _NSPR_DEF_INITSIZE (4 * 1024 * 1024) /* 4 MB */ int _irix_initusers = _NSPR_DEF_INITUSERS; int _irix_initsize = _NSPR_DEF_INITSIZE; PRIntn _pr_io_in_progress, _pr_clock_in_progress; PRInt32 _pr_md_irix_sprocs_created, _pr_md_irix_sprocs_failed; PRInt32 _pr_md_irix_sprocs = 1; PRCList _pr_md_irix_sproc_list = PR_INIT_STATIC_CLIST(&_pr_md_irix_sproc_list); sigset_t ints_off; extern sigset_t timer_set; #if !defined(PR_SETABORTSIG) #define PR_SETABORTSIG 18 #endif /* * terminate the entire application if any sproc exits abnormally */ PRBool _nspr_terminate_on_error = PR_TRUE; /* * exported interface to set the shared arena parameters */ void _PR_Irix_Set_Arena_Params(PRInt32 initusers, PRInt32 initsize) { _irix_initusers = initusers; _irix_initsize = initsize; } static usptr_t *alloc_new_arena() { return(usinit("/dev/zero")); } static PRStatus new_poll_sem(struct _MDThread *mdthr, int val) { PRIntn _is; PRStatus rv = PR_SUCCESS; usema_t *sem = NULL; PRCList *qp; nspr_arena *arena; usptr_t *irix_arena; PRThread *me = _MD_GET_ATTACHED_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(_is); _PR_LOCK(arena_list_lock); for (qp = arena_list.next; qp != &arena_list; qp = qp->next) { arena = ARENA_PTR(qp); sem = usnewpollsema(arena->usarena, val); if (sem != NULL) { mdthr->cvar_pollsem = sem; mdthr->pollsem_arena = arena->usarena; break; } } if (sem == NULL) { /* * If no space left in the arena allocate a new one. */ if (errno == ENOMEM) { arena = PR_NEWZAP(nspr_arena); if (arena != NULL) { irix_arena = alloc_new_arena(); if (irix_arena) { PR_APPEND_LINK(&arena->links, &arena_list); _nspr_irix_arena_cnt++; arena->usarena = irix_arena; sem = usnewpollsema(arena->usarena, val); if (sem != NULL) { mdthr->cvar_pollsem = sem; mdthr->pollsem_arena = arena->usarena; } else rv = PR_FAILURE; } else { PR_DELETE(arena); rv = PR_FAILURE; } } else rv = PR_FAILURE; } else rv = PR_FAILURE; } _PR_UNLOCK(arena_list_lock); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(_is); if (rv == PR_SUCCESS) _MD_ATOMIC_INCREMENT(&_nspr_irix_pollsem_cnt); return rv; } static void free_poll_sem(struct _MDThread *mdthr) { PRIntn _is; PRThread *me = _MD_GET_ATTACHED_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(_is); usfreepollsema(mdthr->cvar_pollsem, mdthr->pollsem_arena); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(_is); _MD_ATOMIC_DECREMENT(&_nspr_irix_pollsem_cnt); } static PRStatus new_lock(struct _MDLock *lockp) { PRIntn _is; PRStatus rv = PR_SUCCESS; ulock_t lock = NULL; PRCList *qp; nspr_arena *arena; usptr_t *irix_arena; PRThread *me = _MD_GET_ATTACHED_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(_is); _PR_LOCK(arena_list_lock); for (qp = arena_list.next; qp != &arena_list; qp = qp->next) { arena = ARENA_PTR(qp); lock = usnewlock(arena->usarena); if (lock != NULL) { lockp->lock = lock; lockp->arena = arena->usarena; break; } } if (lock == NULL) { /* * If no space left in the arena allocate a new one. */ if (errno == ENOMEM) { arena = PR_NEWZAP(nspr_arena); if (arena != NULL) { irix_arena = alloc_new_arena(); if (irix_arena) { PR_APPEND_LINK(&arena->links, &arena_list); _nspr_irix_arena_cnt++; arena->usarena = irix_arena; lock = usnewlock(irix_arena); if (lock != NULL) { lockp->lock = lock; lockp->arena = arena->usarena; } else rv = PR_FAILURE; } else { PR_DELETE(arena); rv = PR_FAILURE; } } else rv = PR_FAILURE; } else rv = PR_FAILURE; } _PR_UNLOCK(arena_list_lock); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(_is); if (rv == PR_SUCCESS) _MD_ATOMIC_INCREMENT(&_nspr_irix_lock_cnt); return rv; } static void free_lock(struct _MDLock *lockp) { PRIntn _is; PRThread *me = _MD_GET_ATTACHED_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(_is); usfreelock(lockp->lock, lockp->arena); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(_is); _MD_ATOMIC_DECREMENT(&_nspr_irix_lock_cnt); } void _MD_FREE_LOCK(struct _MDLock *lockp) { PRIntn _is; PRThread *me = _MD_GET_ATTACHED_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(_is); free_lock(lockp); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(_is); } /* * _MD_get_attached_thread * Return the thread pointer of the current thread if it is attached. * * This function is needed for Irix because the thread-local-storage is * implemented by mmapin'g a page with the MAP_LOCAL flag. This causes the * sproc-private page to inherit contents of the page of the caller of sproc(). */ PRThread *_MD_get_attached_thread(void) { if (_MD_GET_SPROC_PID() == get_pid()) return _MD_THIS_THREAD(); else return 0; } /* * _MD_get_current_thread * Return the thread pointer of the current thread (attaching it if * necessary) */ PRThread *_MD_get_current_thread(void) { PRThread *me; me = _MD_GET_ATTACHED_THREAD(); if (NULL == me) { me = _PRI_AttachThread( PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0); } PR_ASSERT(me != NULL); return(me); } /* * irix_detach_sproc * auto-detach a sproc when it exits */ void irix_detach_sproc(void) { PRThread *me; me = _MD_GET_ATTACHED_THREAD(); if ((me != NULL) && (me->flags & _PR_ATTACHED)) { _PRI_DetachThread(); } } PRStatus _MD_NEW_LOCK(struct _MDLock *lockp) { PRStatus rv; PRIntn is; PRThread *me = _MD_GET_ATTACHED_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); rv = new_lock(lockp); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return rv; } static void sigchld_handler(int sig) { pid_t pid; int status; /* * If an sproc exited abnormally send a SIGKILL signal to all the * sprocs in the process to terminate the application */ while ((pid = waitpid(0, &status, WNOHANG)) > 0) { if (WIFSIGNALED(status) && ((WTERMSIG(status) == SIGSEGV) || (WTERMSIG(status) == SIGBUS) || (WTERMSIG(status) == SIGABRT) || (WTERMSIG(status) == SIGILL))) { prctl(PR_SETEXITSIG, SIGKILL); _exit(status); } } } static void save_context_and_block(int sig) { PRThread *me = _PR_MD_CURRENT_THREAD(); _PRCPU *cpu = _PR_MD_CURRENT_CPU(); /* * save context */ (void) setjmp(me->md.jb); /* * unblock the suspending thread */ if (me->cpu) { /* * I am a cpu thread, not a user-created GLOBAL thread */ unblockproc(cpu->md.suspending_id); } else { unblockproc(me->md.suspending_id); } /* * now, block current thread */ blockproc(getpid()); } /* ** The irix kernel has a bug in it which causes async connect's which are ** interrupted by a signal to fail terribly (EADDRINUSE is returned). ** We work around the bug by blocking signals during the async connect ** attempt. */ PRInt32 _MD_irix_connect( PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout) { PRInt32 rv; sigset_t oldset; sigprocmask(SIG_BLOCK, &ints_off, &oldset); rv = connect(osfd, addr, addrlen); sigprocmask(SIG_SETMASK, &oldset, 0); return(rv); } #include "prprf.h" /********************************************************************/ /********************************************************************/ /*************** Various thread like things for IRIX ****************/ /********************************************************************/ /********************************************************************/ void *_MD_GetSP(PRThread *t) { PRThread *me = _PR_MD_CURRENT_THREAD(); void *sp; if (me == t) (void) setjmp(t->md.jb); sp = (void *)(t->md.jb[JB_SP]); PR_ASSERT((sp >= (void *) t->stack->stackBottom) && (sp <= (void *) (t->stack->stackBottom + t->stack->stackSize))); return(sp); } void _MD_InitLocks() { char buf[200]; char *init_users, *init_size; PR_snprintf(buf, sizeof(buf), "/dev/zero"); if (init_users = getenv("_NSPR_IRIX_INITUSERS")) _irix_initusers = atoi(init_users); if (init_size = getenv("_NSPR_IRIX_INITSIZE")) _irix_initsize = atoi(init_size); usconfig(CONF_INITUSERS, _irix_initusers); usconfig(CONF_INITSIZE, _irix_initsize); usconfig(CONF_AUTOGROW, 1); usconfig(CONF_AUTORESV, 1); if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) { perror("PR_Init: unable to config mutex arena"); exit(-1); } _pr_usArena = usinit(buf); if (!_pr_usArena) { fprintf(stderr, "PR_Init: Error - unable to create lock/monitor arena\n"); exit(-1); } _pr_heapLock = usnewlock(_pr_usArena); _nspr_irix_lock_cnt++; arena_list_lock = usnewlock(_pr_usArena); _nspr_irix_lock_cnt++; sproc_list_lock = usnewlock(_pr_usArena); _nspr_irix_lock_cnt++; _pr_irix_exit_sem = usnewsema(_pr_usArena, 0); _nspr_irix_sem_cnt = 1; first_arena.usarena = _pr_usArena; PR_INIT_CLIST(&first_arena.links); PR_APPEND_LINK(&first_arena.links, &arena_list); } /* _PR_IRIX_CHILD_PROCESS is a private API for Server group */ void _PR_IRIX_CHILD_PROCESS() { extern PRUint32 _pr_global_threads; PR_ASSERT(_PR_MD_CURRENT_CPU() == _pr_primordialCPU); PR_ASSERT(_pr_numCPU == 1); PR_ASSERT(_pr_global_threads == 0); /* * save the new pid */ _pr_primordialCPU->md.id = getpid(); _MD_SET_SPROC_PID(getpid()); } static PRStatus pr_cvar_wait_sem(PRThread *thread, PRIntervalTime timeout) { int rv; #ifdef _PR_USE_POLL struct pollfd pfd; int msecs; if (timeout == PR_INTERVAL_NO_TIMEOUT) msecs = -1; else msecs = PR_IntervalToMilliseconds(timeout); #else struct timeval tv, *tvp; fd_set rd; if(timeout == PR_INTERVAL_NO_TIMEOUT) tvp = NULL; else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&rd); FD_SET(thread->md.cvar_pollsemfd, &rd); #endif /* * call uspsema only if a previous select call on this semaphore * did not timeout */ if (!thread->md.cvar_pollsem_select) { rv = _PR_WAIT_SEM(thread->md.cvar_pollsem); PR_ASSERT(rv >= 0); } else rv = 0; again: if(!rv) { #ifdef _PR_USE_POLL pfd.events = POLLIN; pfd.fd = thread->md.cvar_pollsemfd; rv = _MD_POLL(&pfd, 1, msecs); #else rv = _MD_SELECT(thread->md.cvar_pollsemfd + 1, &rd, NULL,NULL,tvp); #endif if ((rv == -1) && (errno == EINTR)) { rv = 0; goto again; } PR_ASSERT(rv >= 0); } if (rv > 0) { /* * acquired the semaphore, call uspsema next time */ thread->md.cvar_pollsem_select = 0; return PR_SUCCESS; } else { /* * select timed out; must call select, not uspsema, when trying * to acquire the semaphore the next time */ thread->md.cvar_pollsem_select = 1; return PR_FAILURE; } } PRStatus _MD_wait(PRThread *thread, PRIntervalTime ticks) { if ( thread->flags & _PR_GLOBAL_SCOPE ) { _MD_CHECK_FOR_EXIT(); if (pr_cvar_wait_sem(thread, ticks) == PR_FAILURE) { _MD_CHECK_FOR_EXIT(); /* * wait timed out */ _PR_THREAD_LOCK(thread); if (thread->wait.cvar) { /* * The thread will remove itself from the waitQ * of the cvar in _PR_WaitCondVar */ thread->wait.cvar = NULL; thread->state = _PR_RUNNING; _PR_THREAD_UNLOCK(thread); } else { _PR_THREAD_UNLOCK(thread); /* * This thread was woken up by a notifying thread * at the same time as a timeout; so, consume the * extra post operation on the semaphore */ _MD_CHECK_FOR_EXIT(); pr_cvar_wait_sem(thread, PR_INTERVAL_NO_TIMEOUT); } _MD_CHECK_FOR_EXIT(); } } else { _PR_MD_SWITCH_CONTEXT(thread); } return PR_SUCCESS; } PRStatus _MD_WakeupWaiter(PRThread *thread) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntn is; PR_ASSERT(_pr_md_idle_cpus >= 0); if (thread == NULL) { if (_pr_md_idle_cpus) _MD_Wakeup_CPUs(); } else if (!_PR_IS_NATIVE_THREAD(thread)) { if (_pr_md_idle_cpus) _MD_Wakeup_CPUs(); } else { PR_ASSERT(_PR_IS_NATIVE_THREAD(thread)); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _MD_CVAR_POST_SEM(thread); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); } return PR_SUCCESS; } void create_sproc (void (*entry) (void *, size_t), unsigned inh, void *arg, caddr_t sp, size_t len, int *pid) { sproc_params sparams; char data; int rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) { *pid = sprocsp(entry, /* startup func */ inh, /* attribute flags */ arg, /* thread param */ sp, /* stack address */ len); /* stack size */ } else { sparams.sd.entry = entry; sparams.sd.inh = inh; sparams.sd.arg = arg; sparams.sd.sp = sp; sparams.sd.len = len; sparams.sd.pid = pid; sparams.sd.creator_pid = getpid(); _PR_LOCK(sproc_list_lock); PR_APPEND_LINK(&sparams.links, &sproc_list); rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1); PR_ASSERT(rv == 1); _PR_UNLOCK(sproc_list_lock); blockproc(getpid()); } } /* * _PR_MD_WAKEUP_PRIMORDIAL_CPU * * wakeup cpu 0 */ void _PR_MD_WAKEUP_PRIMORDIAL_CPU() { char data = '0'; int rv; rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1); PR_ASSERT(rv == 1); } /* * _PR_MD_primordial_cpu * * process events that need to executed by the primordial cpu on each * iteration through the idle loop */ void _PR_MD_primordial_cpu() { PRCList *qp; sproc_params *sp; int pid; _PR_LOCK(sproc_list_lock); while ((qp = sproc_list.next) != &sproc_list) { sp = SPROC_PARAMS_PTR(qp); PR_REMOVE_LINK(&sp->links); pid = sp->sd.creator_pid; (*(sp->sd.pid)) = sprocsp(sp->sd.entry, /* startup func */ sp->sd.inh, /* attribute flags */ sp->sd.arg, /* thread param */ sp->sd.sp, /* stack address */ sp->sd.len); /* stack size */ unblockproc(pid); } _PR_UNLOCK(sproc_list_lock); } PRStatus _MD_CreateThread(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { typedef void (*SprocEntry) (void *, size_t); SprocEntry spentry = (SprocEntry)start; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 pid; PRStatus rv; if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); thread->md.cvar_pollsem_select = 0; thread->flags |= _PR_GLOBAL_SCOPE; thread->md.cvar_pollsemfd = -1; if (new_poll_sem(&thread->md,0) == PR_FAILURE) { if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } thread->md.cvar_pollsemfd = _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem); if ((thread->md.cvar_pollsemfd < 0)) { free_poll_sem(&thread->md); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } create_sproc(spentry, /* startup func */ PR_SALL, /* attribute flags */ (void *)thread, /* thread param */ NULL, /* stack address */ stackSize, &pid); /* stack size */ if (pid > 0) { _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_created); _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs); rv = PR_SUCCESS; if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return rv; } else { close(thread->md.cvar_pollsemfd); thread->md.cvar_pollsemfd = -1; free_poll_sem(&thread->md); thread->md.cvar_pollsem = NULL; _MD_ATOMIC_INCREMENT(&_pr_md_irix_sprocs_failed); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } } void _MD_CleanThread(PRThread *thread) { if (thread->flags & _PR_GLOBAL_SCOPE) { close(thread->md.cvar_pollsemfd); thread->md.cvar_pollsemfd = -1; free_poll_sem(&thread->md); thread->md.cvar_pollsem = NULL; } } void _MD_SetPriority(_MDThread *thread, PRThreadPriority newPri) { return; } extern void _MD_unix_terminate_waitpid_daemon(void); void _MD_CleanupBeforeExit(void) { extern PRInt32 _pr_cpus_exit; _MD_unix_terminate_waitpid_daemon(); _pr_irix_exit_now = 1; if (_pr_numCPU > 1) { /* * Set a global flag, and wakeup all cpus which will notice the flag * and exit. */ _pr_cpus_exit = getpid(); _MD_Wakeup_CPUs(); while(_pr_numCPU > 1) { _PR_WAIT_SEM(_pr_irix_exit_sem); _pr_numCPU--; } } /* * cause global threads on the recycle list to exit */ _PR_DEADQ_LOCK; if (_PR_NUM_DEADNATIVE != 0) { PRThread *thread; PRCList *ptr; ptr = _PR_DEADNATIVEQ.next; while( ptr != &_PR_DEADNATIVEQ ) { thread = _PR_THREAD_PTR(ptr); _MD_CVAR_POST_SEM(thread); ptr = ptr->next; } } _PR_DEADQ_UNLOCK; while(_PR_NUM_DEADNATIVE > 1) { _PR_WAIT_SEM(_pr_irix_exit_sem); _PR_DEC_DEADNATIVE; } } #ifdef _PR_HAVE_SGI_PRDA_PROCMASK extern void __sgi_prda_procmask(int); #endif PRStatus _MD_InitAttachedThread(PRThread *thread, PRBool wakeup_parent) { PRStatus rv = PR_SUCCESS; if (thread->flags & _PR_GLOBAL_SCOPE) { if (new_poll_sem(&thread->md,0) == PR_FAILURE) { return PR_FAILURE; } thread->md.cvar_pollsemfd = _PR_OPEN_POLL_SEM(thread->md.cvar_pollsem); if ((thread->md.cvar_pollsemfd < 0)) { free_poll_sem(&thread->md); return PR_FAILURE; } if (_MD_InitThread(thread, PR_FALSE) == PR_FAILURE) { close(thread->md.cvar_pollsemfd); thread->md.cvar_pollsemfd = -1; free_poll_sem(&thread->md); thread->md.cvar_pollsem = NULL; return PR_FAILURE; } } return rv; } PRStatus _MD_InitThread(PRThread *thread, PRBool wakeup_parent) { struct sigaction sigact; PRStatus rv = PR_SUCCESS; if (thread->flags & _PR_GLOBAL_SCOPE) { thread->md.id = getpid(); setblockproccnt(thread->md.id, 0); _MD_SET_SPROC_PID(getpid()); #ifdef _PR_HAVE_SGI_PRDA_PROCMASK /* * enable user-level processing of sigprocmask(); this is an * undocumented feature available in Irix 6.2, 6.3, 6.4 and 6.5 */ __sgi_prda_procmask(USER_LEVEL); #endif /* * set up SIGUSR1 handler; this is used to save state */ sigact.sa_handler = save_context_and_block; sigact.sa_flags = SA_RESTART; /* * Must mask clock interrupts */ sigact.sa_mask = timer_set; sigaction(SIGUSR1, &sigact, 0); /* * PR_SETABORTSIG is a new command implemented in a patch to * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all * sprocs in the process when one of them terminates abnormally * */ if (prctl(PR_SETABORTSIG, SIGKILL) < 0) { /* * if (errno == EINVAL) * * PR_SETABORTSIG not supported under this OS. * You may want to get a recent kernel rollup patch that * supports this feature. */ } /* * SIGCLD handler for detecting abormally-terminating * sprocs and for reaping sprocs */ sigact.sa_handler = sigchld_handler; sigact.sa_flags = SA_RESTART; sigact.sa_mask = ints_off; sigaction(SIGCLD, &sigact, NULL); } return rv; } /* * PR_Cleanup should be executed on the primordial sproc; migrate the thread * to the primordial cpu */ void _PR_MD_PRE_CLEANUP(PRThread *me) { PRIntn is; _PRCPU *cpu = _pr_primordialCPU; PR_ASSERT(cpu); me->flags |= _PR_BOUND_THREAD; if (me->cpu->id != 0) { _PR_INTSOFF(is); _PR_RUNQ_LOCK(cpu); me->cpu = cpu; me->state = _PR_RUNNABLE; _PR_ADD_RUNQ(me, cpu, me->priority); _PR_RUNQ_UNLOCK(cpu); _MD_Wakeup_CPUs(); _PR_MD_SWITCH_CONTEXT(me); _PR_FAST_INTSON(is); PR_ASSERT(me->cpu->id == 0); } } /* * process exiting */ PR_EXTERN(void ) _MD_exit(PRIntn status) { PRThread *me = _PR_MD_CURRENT_THREAD(); /* * the exit code of the process is the exit code of the primordial * sproc */ if (!_PR_IS_NATIVE_THREAD(me) && (_PR_MD_CURRENT_CPU()->id == 0)) { /* * primordial sproc case: call _exit directly * Cause SIGKILL to be sent to other sprocs */ prctl(PR_SETEXITSIG, SIGKILL); _exit(status); } else { int rv; char data; sigset_t set; /* * non-primordial sproc case: cause the primordial sproc, cpu 0, * to wakeup and call _exit */ _pr_irix_process_exit = 1; _pr_irix_process_exit_code = status; rv = write(_pr_irix_primoridal_cpu_fd[1], &data, 1); PR_ASSERT(rv == 1); /* * block all signals and wait for SIGKILL to terminate this sproc */ sigfillset(&set); sigsuspend(&set); /* * this code doesn't (shouldn't) execute */ prctl(PR_SETEXITSIG, SIGKILL); _exit(status); } } /* * Override the exit() function in libc to cause the process to exit * when the primodial/main nspr thread calls exit. Calls to exit by any * other thread simply result in a call to the exit function in libc. * The exit code of the process is the exit code of the primordial * sproc. */ void exit(int status) { PRThread *me, *thr; PRCList *qp; if (!_pr_initialized) { if (!libc_exit) { if (!libc_handle) libc_handle = dlopen("libc.so",RTLD_NOW); if (libc_handle) libc_exit = (void (*)(int)) dlsym(libc_handle, "exit"); } if (libc_exit) (*libc_exit)(status); else _exit(status); } me = _PR_MD_CURRENT_THREAD(); if (me == NULL) /* detached thread */ (*libc_exit)(status); PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || (_PR_MD_CURRENT_CPU())->id == me->cpu->id); if (me->flags & _PR_PRIMORDIAL) { me->flags |= _PR_BOUND_THREAD; PR_ASSERT((_PR_MD_CURRENT_CPU())->id == me->cpu->id); if (me->cpu->id != 0) { _PRCPU *cpu = _pr_primordialCPU; PRIntn is; _PR_INTSOFF(is); _PR_RUNQ_LOCK(cpu); me->cpu = cpu; me->state = _PR_RUNNABLE; _PR_ADD_RUNQ(me, cpu, me->priority); _PR_RUNQ_UNLOCK(cpu); _MD_Wakeup_CPUs(); _PR_MD_SWITCH_CONTEXT(me); _PR_FAST_INTSON(is); } PR_ASSERT((_PR_MD_CURRENT_CPU())->id == 0); if (prctl(PR_GETNSHARE) > 1) { #define SPROC_EXIT_WAIT_TIME 5 int sleep_cnt = SPROC_EXIT_WAIT_TIME; /* * sprocs still running; caue cpus and recycled global threads * to exit */ _pr_irix_exit_now = 1; if (_pr_numCPU > 1) { _MD_Wakeup_CPUs(); } _PR_DEADQ_LOCK; if (_PR_NUM_DEADNATIVE != 0) { PRThread *thread; PRCList *ptr; ptr = _PR_DEADNATIVEQ.next; while( ptr != &_PR_DEADNATIVEQ ) { thread = _PR_THREAD_PTR(ptr); _MD_CVAR_POST_SEM(thread); ptr = ptr->next; } } while (sleep_cnt-- > 0) { if (waitpid(0, NULL, WNOHANG) >= 0) sleep(1); else break; } prctl(PR_SETEXITSIG, SIGKILL); } (*libc_exit)(status); } else { /* * non-primordial thread; simply call exit in libc. */ (*libc_exit)(status); } } void _MD_InitRunningCPU(_PRCPU *cpu) { extern int _pr_md_pipefd[2]; _MD_unix_init_running_cpu(cpu); cpu->md.id = getpid(); _MD_SET_SPROC_PID(getpid()); if (_pr_md_pipefd[0] >= 0) { _PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0]; #ifndef _PR_USE_POLL FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu)); #endif } } void _MD_ExitThread(PRThread *thread) { if (thread->flags & _PR_GLOBAL_SCOPE) { _MD_ATOMIC_DECREMENT(&_pr_md_irix_sprocs); _MD_CLEAN_THREAD(thread); _MD_SET_CURRENT_THREAD(NULL); } } void _MD_SuspendCPU(_PRCPU *cpu) { PRInt32 rv; cpu->md.suspending_id = getpid(); rv = kill(cpu->md.id, SIGUSR1); PR_ASSERT(rv == 0); /* * now, block the current thread/cpu until woken up by the suspended * thread from it's SIGUSR1 signal handler */ blockproc(getpid()); } void _MD_ResumeCPU(_PRCPU *cpu) { unblockproc(cpu->md.id); } #if 0 /* * save the register context of a suspended sproc */ void get_context(PRThread *thr) { int len, fd; char pidstr[24]; char path[24]; /* * open the file corresponding to this process in procfs */ sprintf(path,"/proc/%s","00000"); len = strlen(path); sprintf(pidstr,"%d",thr->md.id); len -= strlen(pidstr); sprintf(path + len,"%s",pidstr); fd = open(path,O_RDONLY); if (fd >= 0) { (void) ioctl(fd, PIOCGREG, thr->md.gregs); close(fd); } return; } #endif /* 0 */ void _MD_SuspendThread(PRThread *thread) { PRInt32 rv; PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && _PR_IS_GCABLE_THREAD(thread)); thread->md.suspending_id = getpid(); rv = kill(thread->md.id, SIGUSR1); PR_ASSERT(rv == 0); /* * now, block the current thread/cpu until woken up by the suspended * thread from it's SIGUSR1 signal handler */ blockproc(getpid()); } void _MD_ResumeThread(PRThread *thread) { PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && _PR_IS_GCABLE_THREAD(thread)); (void)unblockproc(thread->md.id); } /* * return the set of processors available for scheduling procs in the * "mask" argument */ PRInt32 _MD_GetThreadAffinityMask(PRThread *unused, PRUint32 *mask) { PRInt32 nprocs, rv; struct pda_stat *pstat; #define MAX_PROCESSORS 32 nprocs = sysmp(MP_NPROCS); if (nprocs < 0) return(-1); pstat = (struct pda_stat*)PR_MALLOC(sizeof(struct pda_stat) * nprocs); if (pstat == NULL) return(-1); rv = sysmp(MP_STAT, pstat); if (rv < 0) { PR_DELETE(pstat); return(-1); } /* * look at the first 32 cpus */ nprocs = (nprocs > MAX_PROCESSORS) ? MAX_PROCESSORS : nprocs; *mask = 0; while (nprocs) { if ((pstat->p_flags & PDAF_ENABLED) && !(pstat->p_flags & PDAF_ISOLATED)) { *mask |= (1 << pstat->p_cpuid); } nprocs--; pstat++; } return 0; } static char *_thr_state[] = { "UNBORN", "RUNNABLE", "RUNNING", "LOCK_WAIT", "COND_WAIT", "JOIN_WAIT", "IO_WAIT", "SUSPENDED", "DEAD" }; void _PR_List_Threads() { PRThread *thr; void *handle; struct _PRCPU *cpu; PRCList *qp; int len, fd; char pidstr[24]; char path[24]; prpsinfo_t pinfo; printf("\n%s %-s\n"," ","LOCAL Threads"); printf("%s %-s\n"," ","----- -------"); printf("%s %-14s %-10s %-12s %-3s %-10s %-10s %-12s\n\n"," ", "Thread", "State", "Wait-Handle", "Cpu","Stk-Base","Stk-Sz","SP"); for (qp = _PR_ACTIVE_LOCAL_THREADQ().next; qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) { thr = _PR_ACTIVE_THREAD_PTR(qp); printf("%s 0x%-12x %-10s "," ",thr,_thr_state[thr->state]); if (thr->state == _PR_LOCK_WAIT) handle = thr->wait.lock; else if (thr->state == _PR_COND_WAIT) handle = thr->wait.cvar; else handle = NULL; if (handle) printf("0x%-10x ",handle); else printf("%-12s "," "); printf("%-3d ",thr->cpu->id); printf("0x%-8x ",thr->stack->stackBottom); printf("0x%-8x ",thr->stack->stackSize); printf("0x%-10x\n",thr->md.jb[JB_SP]); } printf("\n%s %-s\n"," ","GLOBAL Threads"); printf("%s %-s\n"," ","------ -------"); printf("%s %-14s %-6s %-12s %-12s %-12s %-12s\n\n"," ","Thread", "Pid","State","Wait-Handle", "Stk-Base","Stk-Sz"); for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next; qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) { thr = _PR_ACTIVE_THREAD_PTR(qp); if (thr->cpu != NULL) continue; /* it is a cpu thread */ printf("%s 0x%-12x %-6d "," ",thr,thr->md.id); /* * check if the sproc is still running * first call prctl(PR_GETSHMASK,pid) to check if * the process is part of the share group (the pid * could have been recycled by the OS) */ if (prctl(PR_GETSHMASK,thr->md.id) < 0) { printf("%-12s\n","TERMINATED"); continue; } /* * Now, check if the sproc terminated and is in zombie * state */ sprintf(path,"/proc/pinfo/%s","00000"); len = strlen(path); sprintf(pidstr,"%d",thr->md.id); len -= strlen(pidstr); sprintf(path + len,"%s",pidstr); fd = open(path,O_RDONLY); if (fd >= 0) { if (ioctl(fd, PIOCPSINFO, &pinfo) < 0) printf("%-12s ","TERMINATED"); else if (pinfo.pr_zomb) printf("%-12s ","TERMINATED"); else printf("%-12s ",_thr_state[thr->state]); close(fd); } else { printf("%-12s ","TERMINATED"); } if (thr->state == _PR_LOCK_WAIT) handle = thr->wait.lock; else if (thr->state == _PR_COND_WAIT) handle = thr->wait.cvar; else handle = NULL; if (handle) printf("%-12x ",handle); else printf("%-12s "," "); printf("0x%-10x ",thr->stack->stackBottom); printf("0x%-10x\n",thr->stack->stackSize); } printf("\n%s %-s\n"," ","CPUs"); printf("%s %-s\n"," ","----"); printf("%s %-14s %-6s %-12s \n\n"," ","Id","Pid","State"); for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { cpu = _PR_CPU_PTR(qp); printf("%s %-14d %-6d "," ",cpu->id,cpu->md.id); /* * check if the sproc is still running * first call prctl(PR_GETSHMASK,pid) to check if * the process is part of the share group (the pid * could have been recycled by the OS) */ if (prctl(PR_GETSHMASK,cpu->md.id) < 0) { printf("%-12s\n","TERMINATED"); continue; } /* * Now, check if the sproc terminated and is in zombie * state */ sprintf(path,"/proc/pinfo/%s","00000"); len = strlen(path); sprintf(pidstr,"%d",cpu->md.id); len -= strlen(pidstr); sprintf(path + len,"%s",pidstr); fd = open(path,O_RDONLY); if (fd >= 0) { if (ioctl(fd, PIOCPSINFO, &pinfo) < 0) printf("%-12s\n","TERMINATED"); else if (pinfo.pr_zomb) printf("%-12s\n","TERMINATED"); else printf("%-12s\n","RUNNING"); close(fd); } else { printf("%-12s\n","TERMINATED"); } } fflush(stdout); } #endif /* defined(_PR_PTHREADS) */ PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #if !defined(_PR_PTHREADS) if (isCurrent) { (void) setjmp(t->md.jb); } *np = sizeof(t->md.jb) / sizeof(PRWord); return (PRWord *) (t->md.jb); #else *np = 0; return NULL; #endif } void _MD_EarlyInit(void) { #if !defined(_PR_PTHREADS) char *eval; int fd; extern int __ateachexit(void (*func)(void)); sigemptyset(&ints_off); sigaddset(&ints_off, SIGALRM); sigaddset(&ints_off, SIGIO); sigaddset(&ints_off, SIGCLD); if (eval = getenv("_NSPR_TERMINATE_ON_ERROR")) _nspr_terminate_on_error = (0 == atoi(eval) == 0) ? PR_FALSE : PR_TRUE; fd = open("/dev/zero",O_RDWR , 0); if (fd < 0) { perror("open /dev/zero failed"); exit(1); } /* * Set up the sproc private data area. * This region exists at the same address, _nspr_sproc_private, for * every sproc, but each sproc gets a private copy of the region. */ _nspr_sproc_private = (char*)mmap(0, _pr_pageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE| MAP_LOCAL, fd, 0); if (_nspr_sproc_private == (void*)-1) { perror("mmap /dev/zero failed"); exit(1); } _MD_SET_SPROC_PID(getpid()); close(fd); __ateachexit(irix_detach_sproc); #endif _MD_IrixIntervalInit(); } /* _MD_EarlyInit */ void _MD_IrixInit(void) { #if !defined(_PR_PTHREADS) struct sigaction sigact; PRThread *me = _PR_MD_CURRENT_THREAD(); int rv; #ifdef _PR_HAVE_SGI_PRDA_PROCMASK /* * enable user-level processing of sigprocmask(); this is an undocumented * feature available in Irix 6.2, 6.3, 6.4 and 6.5 */ __sgi_prda_procmask(USER_LEVEL); #endif /* * set up SIGUSR1 handler; this is used to save state * during PR_SuspendAll */ sigact.sa_handler = save_context_and_block; sigact.sa_flags = SA_RESTART; sigact.sa_mask = ints_off; sigaction(SIGUSR1, &sigact, 0); /* * Change the name of the core file from core to core.pid, * This is inherited by the sprocs created by this process */ #ifdef PR_COREPID prctl(PR_COREPID, 0, 1); #endif /* * Irix-specific terminate on error processing */ /* * PR_SETABORTSIG is a new command implemented in a patch to * Irix 6.2, 6.3 and 6.4. This causes a signal to be sent to all * sprocs in the process when one of them terminates abnormally * */ if (prctl(PR_SETABORTSIG, SIGKILL) < 0) { /* * if (errno == EINVAL) * * PR_SETABORTSIG not supported under this OS. * You may want to get a recent kernel rollup patch that * supports this feature. * */ } /* * PR_SETEXITSIG - send the SIGCLD signal to the parent * sproc when any sproc terminates * * This is used to cause the entire application to * terminate when any sproc terminates abnormally by * receipt of a SIGSEGV, SIGBUS or SIGABRT signal. * If this is not done, the application may seem * "hung" to the user because the other sprocs may be * waiting for resources held by the * abnormally-terminating sproc. */ prctl(PR_SETEXITSIG, 0); sigact.sa_handler = sigchld_handler; sigact.sa_flags = SA_RESTART; sigact.sa_mask = ints_off; sigaction(SIGCLD, &sigact, NULL); /* * setup stack fields for the primordial thread */ me->stack->stackSize = prctl(PR_GETSTACKSIZE); me->stack->stackBottom = me->stack->stackTop - me->stack->stackSize; rv = pipe(_pr_irix_primoridal_cpu_fd); PR_ASSERT(rv == 0); #ifndef _PR_USE_POLL _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0]; FD_SET(_pr_irix_primoridal_cpu_fd[0], &_PR_FD_READ_SET(me->cpu)); #endif libc_handle = dlopen("libc.so",RTLD_NOW); PR_ASSERT(libc_handle != NULL); libc_exit = (void (*)(int)) dlsym(libc_handle, "exit"); PR_ASSERT(libc_exit != NULL); /* dlclose(libc_handle); */ #endif /* _PR_PTHREADS */ _PR_UnixInit(); } /**************************************************************************/ /************** code and such for NSPR 2.0's interval times ***************/ /**************************************************************************/ #define PR_PSEC_PER_SEC 1000000000000ULL /* 10^12 */ #ifndef SGI_CYCLECNTR_SIZE #define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */ #endif static PRIntn mmem_fd = -1; static PRIntn clock_width = 0; static void *iotimer_addr = NULL; static PRUint32 pr_clock_mask = 0; static PRUint32 pr_clock_shift = 0; static PRIntervalTime pr_ticks = 0; static PRUint32 pr_clock_granularity = 1; static PRUint32 pr_previous = 0, pr_residual = 0; static PRUint32 pr_ticks_per_second = 0; extern PRIntervalTime _PR_UNIX_GetInterval(void); extern PRIntervalTime _PR_UNIX_TicksPerSecond(void); static void _MD_IrixIntervalInit(void) { /* * As much as I would like, the service available through this * interface on R3000's (aka, IP12) just isn't going to make it. * The register is only 24 bits wide, and rolls over at a verocious * rate. */ PRUint32 one_tick = 0; struct utsname utsinfo; uname(&utsinfo); if ((strncmp("IP12", utsinfo.machine, 4) != 0) && ((mmem_fd = open("/dev/mmem", O_RDONLY)) != -1)) { int poffmask = getpagesize() - 1; __psunsigned_t phys_addr, raddr, cycleval; phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval); raddr = phys_addr & ~poffmask; iotimer_addr = mmap( 0, poffmask, PROT_READ, MAP_PRIVATE, mmem_fd, (__psint_t)raddr); clock_width = syssgi(SGI_CYCLECNTR_SIZE); if (clock_width < 0) { /* * We must be executing on a 6.0 or earlier system, since the * SGI_CYCLECNTR_SIZE call is not supported. * * The only pre-6.1 platforms with 64-bit counters are * IP19 and IP21 (Challenge, PowerChallenge, Onyx). */ if (!strncmp(utsinfo.machine, "IP19", 4) || !strncmp(utsinfo.machine, "IP21", 4)) clock_width = 64; else clock_width = 32; } /* * 'cycleval' is picoseconds / increment of the counter. * I'm pushing for a tick to be 100 microseconds, 10^(-4). * That leaves 10^(-8) left over, or 10^8 / cycleval. * Did I do that right? */ one_tick = 100000000UL / cycleval ; /* 100 microseconds */ while (0 != one_tick) { pr_clock_shift += 1; one_tick = one_tick >> 1; pr_clock_granularity = pr_clock_granularity << 1; } pr_clock_mask = pr_clock_granularity - 1; /* to make a mask out of it */ pr_ticks_per_second = PR_PSEC_PER_SEC / ((PRUint64)pr_clock_granularity * (PRUint64)cycleval); iotimer_addr = (void*) ((__psunsigned_t)iotimer_addr + (phys_addr & poffmask)); } else { pr_ticks_per_second = _PR_UNIX_TicksPerSecond(); } } /* _MD_IrixIntervalInit */ PRIntervalTime _MD_IrixIntervalPerSec(void) { return pr_ticks_per_second; } PRIntervalTime _MD_IrixGetInterval(void) { if (mmem_fd != -1) { if (64 == clock_width) { PRUint64 temp = *(PRUint64*)iotimer_addr; pr_ticks = (PRIntervalTime)(temp >> pr_clock_shift); } else { PRIntervalTime ticks = pr_ticks; PRUint32 now = *(PRUint32*)iotimer_addr, temp; PRUint32 residual = pr_residual, previous = pr_previous; temp = now - previous + residual; residual = temp & pr_clock_mask; ticks += temp >> pr_clock_shift; pr_previous = now; pr_residual = residual; pr_ticks = ticks; } } else { /* * No fast access. Use the time of day clock. This isn't the * right answer since this clock can get set back, tick at odd * rates, and it's expensive to acqurie. */ pr_ticks = _PR_UNIX_GetInterval(); } return pr_ticks; } /* _MD_IrixGetInterval */ nspr-4.11/nspr/pr/src/md/unix/linux.c0000644000000000000000000000357312623070344015640 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifdef _PR_PTHREADS extern void _MD_unix_terminate_waitpid_daemon(void); void _MD_CleanupBeforeExit(void) { _MD_unix_terminate_waitpid_daemon(); } #else /* ! _PR_PTHREADS */ void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { /* * set the pointers to the stack-pointer and frame-pointer words in the * context structure; this is for debugging use. */ thread->md.sp = _MD_GET_SP_PTR(thread); thread->md.fp = _MD_GET_FP_PTR(thread); return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for Linux */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for Linux."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Linux."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/netbsd.c0000644000000000000000000000354612623070344015760 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include void _MD_EarlyInit(void) { /* * Ignore FPE because coercion of a NaN to an int causes SIGFPE * to be raised. */ struct sigaction act; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGFPE, &act, 0); } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) sigsetjmp(CONTEXT(t), 1); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for NetBSD */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for NetBSD."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for NetBSD."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/nto.c0000644000000000000000000000136012623070344015271 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* Fake this out */ int socketpair (int foo, int foo2, int foo3, int sv[2]) { printf("error in socketpair\n"); exit (-1); } void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } nspr-4.11/nspr/pr/src/md/unix/objs.mk0000644000000000000000000000133412623070344015614 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # This makefile appends to the variable OBJS the platform-dependent # object modules that will be part of the nspr20 library. CSRCS = \ unix.c \ unix_errors.c \ uxproces.c \ uxrng.c \ uxshm.c \ uxwrap.c \ $(NULL) ifneq ($(USE_PTHREADS),1) CSRCS += uxpoll.c endif ifeq ($(PTHREADS_USER),1) CSRCS += pthreads_user.c endif CSRCS += $(PR_MD_CSRCS) ASFILES += $(PR_MD_ASFILES) OBJS += $(addprefix md/unix/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \ $(addprefix md/unix/$(OBJDIR)/,$(ASFILES:.s=.$(OBJ_SUFFIX))) nspr-4.11/nspr/pr/src/md/unix/openbsd.c0000644000000000000000000000355112623070344016127 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include void _MD_EarlyInit(void) { /* * Ignore FPE because coercion of a NaN to an int causes SIGFPE * to be raised. */ struct sigaction act; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGFPE, &act, 0); } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) sigsetjmp(CONTEXT(t), 1); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for OpenBSD */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for OpenBSD."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OpenBSD."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/os_AIX.s0000644000000000000000000000604112623070344015634 0ustar 00000000000000# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. .set r0,0; .set SP,1; .set RTOC,2; .set r3,3; .set r4,4 .set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 .set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 .set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 .set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 .set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 .set r30,30; .set r31,31 .rename H.10.NO_SYMBOL{PR},"" .rename H.18.longjmp{TC},"longjmp" .lglobl H.10.NO_SYMBOL{PR} .globl .longjmp .globl longjmp{DS} .extern .sigcleanup .extern .jmprestfpr # .text section .csect H.10.NO_SYMBOL{PR} .longjmp: mr r13,r3 mr r14,r4 stu SP,-56(SP) bl .sigcleanup l RTOC,0x14(SP) cal SP,0x38(SP) mr r3,r13 mr r4,r14 l r5,0x8(r3) l SP,0xc(r3) l r7,0xf8(r3) st r7,0x0(SP) l RTOC,0x10(r3) bl .jmprestfpr # 1 == cr0 in disassembly cmpi 1,r4,0x0 mtlr r5 lm r13,0x14(r3) l r5,0x60(r3) mtcrf 0x38,r5 mr r3,r4 bne __L1 lil r3,0x1 __L1: br # traceback table .long 0x00000000 .byte 0x00 # VERSION=0 .byte 0x00 # LANG=TB_C .byte 0x20 # IS_GL=0,IS_EPROL=0,HAS_TBOFF=1 # INT_PROC=0,HAS_CTL=0,TOCLESS=0 # FP_PRESENT=0,LOG_ABORT=0 .byte 0x40 # INT_HNDL=0,NAME_PRESENT=1 # USES_ALLOCA=0,CL_DIS_INV=WALK_ONCOND # SAVES_CR=0,SAVES_LR=0 .byte 0x80 # STORES_BC=1,FPR_SAVED=0 .byte 0x00 # GPR_SAVED=0 .byte 0x02 # FIXEDPARMS=2 .byte 0x01 # FLOATPARMS=0,PARMSONSTK=1 .long 0x00000000 # .long 0x00000014 # TB_OFFSET .short 7 # NAME_LEN .byte "longjmp" .byte 0 # padding .byte 0 # padding .byte 0 # padding # End of traceback table .long 0x00000000 # "\0\0\0\0" # .data section .toc # 0x00000038 T.18.longjmp: .tc H.18.longjmp{TC},longjmp{DS} .csect longjmp{DS} .long .longjmp # "\0\0\0\0" .long TOC{TC0} # "\0\0\0008" .long 0x00000000 # "\0\0\0\0" # End csect longjmp{DS} # .bss section nspr-4.11/nspr/pr/src/md/unix/os_BSD_386_2.s0000644000000000000000000000177312623070344016453 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * os_BSD_386_2.s * We need to define our own setjmp/longjmp on BSDI 2.x because libc's * implementation does some sanity checking that defeats user level threads. * This should no longer be necessary in BSDI 3.0. */ .globl _setjmp .align 2 _setjmp: movl 4(%esp),%eax movl 0(%esp),%edx movl %edx, 0(%eax) /* rta */ movl %ebx, 4(%eax) movl %esp, 8(%eax) movl %ebp,12(%eax) movl %esi,16(%eax) movl %edi,20(%eax) movl $0,%eax ret .globl _longjmp .align 2 _longjmp: movl 4(%esp),%edx movl 8(%esp),%eax movl 0(%edx),%ecx movl 4(%edx),%ebx movl 8(%edx),%esp movl 12(%edx),%ebp movl 16(%edx),%esi movl 20(%edx),%edi cmpl $0,%eax jne 1f movl $1,%eax 1: movl %ecx,0(%esp) ret nspr-4.11/nspr/pr/src/md/unix/os_Darwin.s0000644000000000000000000000066212623070344016442 0ustar 00000000000000# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifdef __i386__ #include "os_Darwin_x86.s" #elif defined(__x86_64__) #include "os_Darwin_x86_64.s" #elif defined(__ppc__) #include "os_Darwin_ppc.s" #endif nspr-4.11/nspr/pr/src/md/unix/os_Darwin_ppc.s0000644000000000000000000000354612623070344017310 0ustar 00000000000000# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # Based on the programming examples in The PowerPC Architecture: # A Specification for A New Family of RISC Processors, 2nd Ed., # Book I, Section E.1, "Synchronization," pp. 249-256, May 1994. # .text # # PRInt32 __PR_DarwinPPC_AtomicIncrement(PRInt32 *val); # .align 2 .globl __PR_DarwinPPC_AtomicIncrement .private_extern __PR_DarwinPPC_AtomicIncrement __PR_DarwinPPC_AtomicIncrement: lwarx r4,0,r3 addi r0,r4,1 stwcx. r0,0,r3 bne- __PR_DarwinPPC_AtomicIncrement mr r3,r0 blr # # PRInt32 __PR_DarwinPPC_AtomicDecrement(PRInt32 *val); # .align 2 .globl __PR_DarwinPPC_AtomicDecrement .private_extern __PR_DarwinPPC_AtomicDecrement __PR_DarwinPPC_AtomicDecrement: lwarx r4,0,r3 addi r0,r4,-1 stwcx. r0,0,r3 bne- __PR_DarwinPPC_AtomicDecrement mr r3,r0 blr # # PRInt32 __PR_DarwinPPC_AtomicSet(PRInt32 *val, PRInt32 newval); # .align 2 .globl __PR_DarwinPPC_AtomicSet .private_extern __PR_DarwinPPC_AtomicSet __PR_DarwinPPC_AtomicSet: lwarx r5,0,r3 stwcx. r4,0,r3 bne- __PR_DarwinPPC_AtomicSet mr r3,r5 blr # # PRInt32 __PR_DarwinPPC_AtomicAdd(PRInt32 *ptr, PRInt32 val); # .align 2 .globl __PR_DarwinPPC_AtomicAdd .private_extern __PR_DarwinPPC_AtomicAdd __PR_DarwinPPC_AtomicAdd: lwarx r5,0,r3 add r0,r4,r5 stwcx. r0,0,r3 bne- __PR_DarwinPPC_AtomicAdd mr r3,r0 blr nspr-4.11/nspr/pr/src/md/unix/os_Darwin_x86.s0000644000000000000000000000362312623070344017147 0ustar 00000000000000# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # Based on os_Linux_x86.s # # # PRInt32 __PR_Darwin_x86_AtomicIncrement(PRInt32 *val); # # Atomically increment the integer pointed to by 'val' and return # the result of the increment. # .text .globl __PR_Darwin_x86_AtomicIncrement .private_extern __PR_Darwin_x86_AtomicIncrement .align 4 __PR_Darwin_x86_AtomicIncrement: movl 4(%esp), %ecx movl $1, %eax lock xaddl %eax, (%ecx) incl %eax ret # # PRInt32 __PR_Darwin_x86_AtomicDecrement(PRInt32 *val); # # Atomically decrement the integer pointed to by 'val' and return # the result of the decrement. # .text .globl __PR_Darwin_x86_AtomicDecrement .private_extern __PR_Darwin_x86_AtomicDecrement .align 4 __PR_Darwin_x86_AtomicDecrement: movl 4(%esp), %ecx movl $-1, %eax lock xaddl %eax, (%ecx) decl %eax ret # # PRInt32 __PR_Darwin_x86_AtomicSet(PRInt32 *val, PRInt32 newval); # # Atomically set the integer pointed to by 'val' to the new # value 'newval' and return the old value. # .text .globl __PR_Darwin_x86_AtomicSet .private_extern __PR_Darwin_x86_AtomicSet .align 4 __PR_Darwin_x86_AtomicSet: movl 4(%esp), %ecx movl 8(%esp), %eax xchgl %eax, (%ecx) ret # # PRInt32 __PR_Darwin_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val); # # Atomically add 'val' to the integer pointed to by 'ptr' # and return the result of the addition. # .text .globl __PR_Darwin_x86_AtomicAdd .private_extern __PR_Darwin_x86_AtomicAdd .align 4 __PR_Darwin_x86_AtomicAdd: movl 4(%esp), %ecx movl 8(%esp), %eax movl %eax, %edx lock xaddl %eax, (%ecx) addl %edx, %eax ret nspr-4.11/nspr/pr/src/md/unix/os_Darwin_x86_64.s0000644000000000000000000000344312623070344017460 0ustar 00000000000000# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # PRInt32 __PR_Darwin_x86_64_AtomicIncrement(PRInt32 *val) # # Atomically increment the integer pointed to by 'val' and return # the result of the increment. # .text .globl __PR_Darwin_x86_64_AtomicIncrement .private_extern __PR_Darwin_x86_64_AtomicIncrement .align 4 __PR_Darwin_x86_64_AtomicIncrement: movl $1, %eax lock xaddl %eax, (%rdi) incl %eax ret # PRInt32 __PR_Darwin_x86_64_AtomicDecrement(PRInt32 *val) # # Atomically decrement the integer pointed to by 'val' and return # the result of the decrement. # .text .globl __PR_Darwin_x86_64_AtomicDecrement .private_extern __PR_Darwin_x86_64_AtomicDecrement .align 4 __PR_Darwin_x86_64_AtomicDecrement: movl $-1, %eax lock xaddl %eax, (%rdi) decl %eax ret # PRInt32 __PR_Darwin_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval) # # Atomically set the integer pointed to by 'val' to the new # value 'newval' and return the old value. # .text .globl __PR_Darwin_x86_64_AtomicSet .private_extern __PR_Darwin_x86_64_AtomicSet .align 4 __PR_Darwin_x86_64_AtomicSet: movl %esi, %eax xchgl %eax, (%rdi) ret # PRInt32 __PR_Darwin_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val) # # Atomically add 'val' to the integer pointed to by 'ptr' # and return the result of the addition. # .text .globl __PR_Darwin_x86_64_AtomicAdd .private_extern __PR_Darwin_x86_64_AtomicAdd .align 4 __PR_Darwin_x86_64_AtomicAdd: movl %esi, %eax lock xaddl %eax, (%rdi) addl %esi, %eax ret nspr-4.11/nspr/pr/src/md/unix/os_HPUX.s0000644000000000000000000000110512623070344015773 0ustar 00000000000000; ; This Source Code Form is subject to the terms of the Mozilla Public ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifdef __LP64__ .LEVEL 2.0W #else .LEVEL 1.1 #endif .CODE ; equivalent to the following two lines ; .SPACE $TEXT$,SORT=8 ; .SUBSPA $CODE$,QUAD=0,ALIGN=4,ACCESS=0x2c,CODE_ONLY,SORT=24 ret_cr16 .PROC .CALLINFO FRAME=0, NO_CALLS .EXPORT ret_cr16,ENTRY .ENTRY BV %r0(%rp) .EXIT MFCTL %cr16,%ret0 .PROCEND .END nspr-4.11/nspr/pr/src/md/unix/os_HPUX_ia64.s0000644000000000000000000000432312623070344016623 0ustar 00000000000000// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. .text // PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val) // // Atomically increment the integer pointed to by 'val' and return // the result of the increment. // .align 16 .global _PR_ia64_AtomicIncrement# .proc _PR_ia64_AtomicIncrement# _PR_ia64_AtomicIncrement: #ifndef _LP64 addp4 r32 = 0, r32 ;; #endif fetchadd4.acq r8 = [r32], 1 ;; adds r8 = 1, r8 br.ret.sptk.many b0 .endp _PR_ia64_AtomicIncrement# // PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val) // // Atomically decrement the integer pointed to by 'val' and return // the result of the decrement. // .align 16 .global _PR_ia64_AtomicDecrement# .proc _PR_ia64_AtomicDecrement# _PR_ia64_AtomicDecrement: #ifndef _LP64 addp4 r32 = 0, r32 ;; #endif fetchadd4.rel r8 = [r32], -1 ;; adds r8 = -1, r8 br.ret.sptk.many b0 .endp _PR_ia64_AtomicDecrement# // PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val) // // Atomically add 'val' to the integer pointed to by 'ptr' // and return the result of the addition. // .align 16 .global _PR_ia64_AtomicAdd# .proc _PR_ia64_AtomicAdd# _PR_ia64_AtomicAdd: #ifndef _LP64 addp4 r32 = 0, r32 ;; #endif ld4 r15 = [r32] ;; .L3: mov r14 = r15 mov ar.ccv = r15 add r8 = r15, r33 ;; cmpxchg4.acq r15 = [r32], r8, ar.ccv ;; cmp4.ne p6, p7 = r15, r14 (p6) br.cond.dptk .L3 br.ret.sptk.many b0 .endp _PR_ia64_AtomicAdd# // PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval) // // Atomically set the integer pointed to by 'val' to the new // value 'newval' and return the old value. // .align 16 .global _PR_ia64_AtomicSet# .proc _PR_ia64_AtomicSet# _PR_ia64_AtomicSet: #ifndef _LP64 addp4 r32 = 0, r32 ;; #endif xchg4 r8 = [r32], r33 br.ret.sptk.many b0 .endp _PR_ia64_AtomicSet# nspr-4.11/nspr/pr/src/md/unix/os_Irix.s0000644000000000000000000000311012623070344016120 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Atomically add a new element to the top of the stack * * usage : PR_StackPush(listp, elementp); * ----------------------- */ #include "md/_irix.h" #ifdef _PR_HAVE_ATOMIC_CAS #include #include LEAF(PR_StackPush) retry_push: .set noreorder lw v0,0(a0) li t1,1 beq v0,t1,retry_push move t0,a1 ll v0,0(a0) beq v0,t1,retry_push nop sc t1,0(a0) beq t1,0,retry_push nop sw v0,0(a1) sync sw t0,0(a0) nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop jr ra nop END(PR_StackPush) /* * * Atomically remove the element at the top of the stack * * usage : elemep = PR_StackPop(listp); * */ LEAF(PR_StackPop) retry_pop: .set noreorder lw v0,0(a0) li t1,1 beq v0,0,done nop beq v0,t1,retry_pop nop ll v0,0(a0) beq v0,0,done nop beq v0,t1,retry_pop nop sc t1,0(a0) beq t1,0,retry_pop nop lw t0,0(v0) sw t0,0(a0) done: nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop jr ra nop END(PR_StackPop) #endif /* _PR_HAVE_ATOMIC_CAS */ nspr-4.11/nspr/pr/src/md/unix/os_Linux_ia64.s0000644000000000000000000000415412623070344017140 0ustar 00000000000000// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. .text // PRInt32 _PR_ia64_AtomicIncrement(PRInt32 *val) // // Atomically increment the integer pointed to by 'val' and return // the result of the increment. // .align 16 .global _PR_ia64_AtomicIncrement# .proc _PR_ia64_AtomicIncrement# _PR_ia64_AtomicIncrement: fetchadd4.acq r8 = [r32], 1 ;; adds r8 = 1, r8 br.ret.sptk.many b0 .endp _PR_ia64_AtomicIncrement# // PRInt32 _PR_ia64_AtomicDecrement(PRInt32 *val) // // Atomically decrement the integer pointed to by 'val' and return // the result of the decrement. // .align 16 .global _PR_ia64_AtomicDecrement# .proc _PR_ia64_AtomicDecrement# _PR_ia64_AtomicDecrement: fetchadd4.rel r8 = [r32], -1 ;; adds r8 = -1, r8 br.ret.sptk.many b0 .endp _PR_ia64_AtomicDecrement# // PRInt32 _PR_ia64_AtomicAdd(PRInt32 *ptr, PRInt32 val) // // Atomically add 'val' to the integer pointed to by 'ptr' // and return the result of the addition. // .align 16 .global _PR_ia64_AtomicAdd# .proc _PR_ia64_AtomicAdd# _PR_ia64_AtomicAdd: ld4 r15 = [r32] ;; .L3: mov r14 = r15 mov ar.ccv = r15 add r8 = r15, r33 ;; cmpxchg4.acq r15 = [r32], r8, ar.ccv ;; cmp4.ne p6, p7 = r15, r14 (p6) br.cond.dptk .L3 br.ret.sptk.many b0 .endp _PR_ia64_AtomicAdd# // PRInt32 _PR_ia64_AtomicSet(PRInt32 *val, PRInt32 newval) // // Atomically set the integer pointed to by 'val' to the new // value 'newval' and return the old value. // .align 16 .global _PR_ia64_AtomicSet# .proc _PR_ia64_AtomicSet# _PR_ia64_AtomicSet: xchg4 r8 = [r32], r33 br.ret.sptk.many b0 .endp _PR_ia64_AtomicSet# // Magic indicating no need for an executable stack .section .note.GNU-stack, "", @progbits ; .previous nspr-4.11/nspr/pr/src/md/unix/os_Linux_ppc.s0000644000000000000000000000376212623070344017163 0ustar 00000000000000# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # Based on the programming examples in The PowerPC Architecture: # A Specification for A New Family of RISC Processors, 2nd Ed., # Book I, Section E.1, "Synchronization," pp. 249-256, May 1994. # .section ".text" # # PRInt32 _PR_ppc_AtomicIncrement(PRInt32 *val); # .align 2 .globl _PR_ppc_AtomicIncrement .type _PR_ppc_AtomicIncrement,@function _PR_ppc_AtomicIncrement: .Lfd1: lwarx 4,0,3 addi 0,4,1 stwcx. 0,0,3 bne- .Lfd1 mr 3,0 blr .Lfe1: .size _PR_ppc_AtomicIncrement,.Lfe1-_PR_ppc_AtomicIncrement # # PRInt32 _PR_ppc_AtomicDecrement(PRInt32 *val); # .align 2 .globl _PR_ppc_AtomicDecrement .type _PR_ppc_AtomicDecrement,@function _PR_ppc_AtomicDecrement: .Lfd2: lwarx 4,0,3 addi 0,4,-1 stwcx. 0,0,3 bne- .Lfd2 mr 3,0 blr .Lfe2: .size _PR_ppc_AtomicDecrement,.Lfe2-_PR_ppc_AtomicDecrement # # PRInt32 _PR_ppc_AtomicSet(PRInt32 *val, PRInt32 newval); # .align 2 .globl _PR_ppc_AtomicSet .type _PR_ppc_AtomicSet,@function _PR_ppc_AtomicSet: .Lfd3: lwarx 5,0,3 stwcx. 4,0,3 bne- .Lfd3 mr 3,5 blr .Lfe3: .size _PR_ppc_AtomicSet,.Lfe3-_PR_ppc_AtomicSet # # PRInt32 _PR_ppc_AtomicAdd(PRInt32 *ptr, PRInt32 val); # .align 2 .globl _PR_ppc_AtomicAdd .type _PR_ppc_AtomicAdd,@function _PR_ppc_AtomicAdd: .Lfd4: lwarx 5,0,3 add 0,4,5 stwcx. 0,0,3 bne- .Lfd4 mr 3,0 blr .Lfe4: .size _PR_ppc_AtomicAdd,.Lfe4-_PR_ppc_AtomicAdd # Magic indicating no need for an executable stack .section .note.GNU-stack, "", @progbits ; .previous nspr-4.11/nspr/pr/src/md/unix/os_Linux_x86.s0000644000000000000000000000370512623070344017023 0ustar 00000000000000// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // PRInt32 _PR_x86_AtomicIncrement(PRInt32 *val) // // Atomically increment the integer pointed to by 'val' and return // the result of the increment. // .text .globl _PR_x86_AtomicIncrement .align 4 _PR_x86_AtomicIncrement: movl 4(%esp), %ecx movl $1, %eax lock xaddl %eax, (%ecx) incl %eax ret // PRInt32 _PR_x86_AtomicDecrement(PRInt32 *val) // // Atomically decrement the integer pointed to by 'val' and return // the result of the decrement. // .text .globl _PR_x86_AtomicDecrement .align 4 _PR_x86_AtomicDecrement: movl 4(%esp), %ecx movl $-1, %eax lock xaddl %eax, (%ecx) decl %eax ret // PRInt32 _PR_x86_AtomicSet(PRInt32 *val, PRInt32 newval) // // Atomically set the integer pointed to by 'val' to the new // value 'newval' and return the old value. // // An alternative implementation: // .text // .globl _PR_x86_AtomicSet // .align 4 //_PR_x86_AtomicSet: // movl 4(%esp), %ecx // movl 8(%esp), %edx // movl (%ecx), %eax //retry: // lock // cmpxchgl %edx, (%ecx) // jne retry // ret // .text .globl _PR_x86_AtomicSet .align 4 _PR_x86_AtomicSet: movl 4(%esp), %ecx movl 8(%esp), %eax xchgl %eax, (%ecx) ret // PRInt32 _PR_x86_AtomicAdd(PRInt32 *ptr, PRInt32 val) // // Atomically add 'val' to the integer pointed to by 'ptr' // and return the result of the addition. // .text .globl _PR_x86_AtomicAdd .align 4 _PR_x86_AtomicAdd: movl 4(%esp), %ecx movl 8(%esp), %eax movl %eax, %edx lock xaddl %eax, (%ecx) addl %edx, %eax ret // Magic indicating no need for an executable stack .section .note.GNU-stack, "", @progbits ; .previous nspr-4.11/nspr/pr/src/md/unix/os_Linux_x86_64.s0000644000000000000000000000403512623070344017331 0ustar 00000000000000// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // PRInt32 _PR_x86_64_AtomicIncrement(PRInt32 *val) // // Atomically increment the integer pointed to by 'val' and return // the result of the increment. // .text .globl _PR_x86_64_AtomicIncrement .type _PR_x86_64_AtomicIncrement, @function .align 4 _PR_x86_64_AtomicIncrement: movl $1, %eax lock xaddl %eax, (%rdi) incl %eax ret .size _PR_x86_64_AtomicIncrement, .-_PR_x86_64_AtomicIncrement // PRInt32 _PR_x86_64_AtomicDecrement(PRInt32 *val) // // Atomically decrement the integer pointed to by 'val' and return // the result of the decrement. // .text .globl _PR_x86_64_AtomicDecrement .type _PR_x86_64_AtomicDecrement, @function .align 4 _PR_x86_64_AtomicDecrement: movl $-1, %eax lock xaddl %eax, (%rdi) decl %eax ret .size _PR_x86_64_AtomicDecrement, .-_PR_x86_64_AtomicDecrement // PRInt32 _PR_x86_64_AtomicSet(PRInt32 *val, PRInt32 newval) // // Atomically set the integer pointed to by 'val' to the new // value 'newval' and return the old value. // .text .globl _PR_x86_64_AtomicSet .type _PR_x86_64_AtomicSet, @function .align 4 _PR_x86_64_AtomicSet: movl %esi, %eax xchgl %eax, (%rdi) ret .size _PR_x86_64_AtomicSet, .-_PR_x86_64_AtomicSet // PRInt32 _PR_x86_64_AtomicAdd(PRInt32 *ptr, PRInt32 val) // // Atomically add 'val' to the integer pointed to by 'ptr' // and return the result of the addition. // .text .globl _PR_x86_64_AtomicAdd .type _PR_x86_64_AtomicAdd, @function .align 4 _PR_x86_64_AtomicAdd: movl %esi, %eax lock xaddl %eax, (%rdi) addl %esi, %eax ret .size _PR_x86_64_AtomicAdd, .-_PR_x86_64_AtomicAdd // Magic indicating no need for an executable stack .section .note.GNU-stack, "", @progbits ; .previous nspr-4.11/nspr/pr/src/md/unix/os_SunOS_sparcv9.s0000644000000000000000000001535712623070344017703 0ustar 00000000000000! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- ! ! This Source Code Form is subject to the terms of the Mozilla Public ! License, v. 2.0. If a copy of the MPL was not distributed with this ! file, You can obtain one at http://mozilla.org/MPL/2.0/. ! ! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc) ! using CAS (compare-and-swap) atomic instructions ! ! this MUST be compiled with an ultrasparc-aware assembler ! ! standard asm linkage macros; this module must be compiled ! with the -P option (use C preprocessor) #include ! ====================================================================== ! ! Perform the sequence a = a + 1 atomically with respect to other ! fetch-and-adds to location a in a wait-free fashion. ! ! usage : val = PR_AtomicIncrement(address) ! return: current value (you'd think this would be old val) ! ! ----------------------- ! Note on REGISTER USAGE: ! as this is a LEAF procedure, a new stack frame is not created; ! we use the caller's stack frame so what would normally be %i (input) ! registers are actually %o (output registers). Also, we must not ! overwrite the contents of %l (local) registers as they are not ! assumed to be volatile during calls. ! ! So, the registers used are: ! %o0 [input] - the address of the value to increment ! %o1 [local] - work register ! %o2 [local] - work register ! %o3 [local] - work register ! ----------------------- ENTRY(_MD_AtomicIncrement) ! standard assembler/ELF prologue retryAI: ld [%o0], %o2 ! set o2 to the current value add %o2, 0x1, %o3 ! calc the new value mov %o3, %o1 ! save the return value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAI ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o1, %o0 ! set the return code to the new value SET_SIZE(_MD_AtomicIncrement) ! standard assembler/ELF epilogue ! ! end ! ! ====================================================================== ! ! ====================================================================== ! ! Perform the sequence a = a - 1 atomically with respect to other ! fetch-and-decs to location a in a wait-free fashion. ! ! usage : val = PR_AtomicDecrement(address) ! return: current value (you'd think this would be old val) ! ! ----------------------- ! Note on REGISTER USAGE: ! as this is a LEAF procedure, a new stack frame is not created; ! we use the caller's stack frame so what would normally be %i (input) ! registers are actually %o (output registers). Also, we must not ! overwrite the contents of %l (local) registers as they are not ! assumed to be volatile during calls. ! ! So, the registers used are: ! %o0 [input] - the address of the value to increment ! %o1 [local] - work register ! %o2 [local] - work register ! %o3 [local] - work register ! ----------------------- ENTRY(_MD_AtomicDecrement) ! standard assembler/ELF prologue retryAD: ld [%o0], %o2 ! set o2 to the current value sub %o2, 0x1, %o3 ! calc the new value mov %o3, %o1 ! save the return value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAD ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o1, %o0 ! set the return code to the new value SET_SIZE(_MD_AtomicDecrement) ! standard assembler/ELF epilogue ! ! end ! ! ====================================================================== ! ! ====================================================================== ! ! Perform the sequence a = b atomically with respect to other ! fetch-and-stores to location a in a wait-free fashion. ! ! usage : old_val = PR_AtomicSet(address, newval) ! ! ----------------------- ! Note on REGISTER USAGE: ! as this is a LEAF procedure, a new stack frame is not created; ! we use the caller's stack frame so what would normally be %i (input) ! registers are actually %o (output registers). Also, we must not ! overwrite the contents of %l (local) registers as they are not ! assumed to be volatile during calls. ! ! So, the registers used are: ! %o0 [input] - the address of the value to increment ! %o1 [input] - the new value to set for [%o0] ! %o2 [local] - work register ! %o3 [local] - work register ! ----------------------- ENTRY(_MD_AtomicSet) ! standard assembler/ELF prologue retryAS: ld [%o0], %o2 ! set o2 to the current value mov %o1, %o3 ! set up the new value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAS ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o3, %o0 ! set the return code to the prev value SET_SIZE(_MD_AtomicSet) ! standard assembler/ELF epilogue ! ! end ! ! ====================================================================== ! ! ====================================================================== ! ! Perform the sequence a = a + b atomically with respect to other ! fetch-and-adds to location a in a wait-free fashion. ! ! usage : newval = PR_AtomicAdd(address, val) ! return: the value after addition ! ENTRY(_MD_AtomicAdd) ! standard assembler/ELF prologue retryAA: ld [%o0], %o2 ! set o2 to the current value add %o2, %o1, %o3 ! calc the new value mov %o3, %o4 ! save the return value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAA ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o4, %o0 ! set the return code to the new value SET_SIZE(_MD_AtomicAdd) ! standard assembler/ELF epilogue ! ! end ! nspr-4.11/nspr/pr/src/md/unix/os_SunOS_ultrasparc.s0000644000000000000000000001535612623070344020473 0ustar 00000000000000! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- ! ! This Source Code Form is subject to the terms of the Mozilla Public ! License, v. 2.0. If a copy of the MPL was not distributed with this ! file, You can obtain one at http://mozilla.org/MPL/2.0/. ! ! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc) ! using CAS (compare-and-swap) atomic instructions ! ! this MUST be compiled with an ultrasparc-aware assembler ! ! standard asm linkage macros; this module must be compiled ! with the -P option (use C preprocessor) #include ! ====================================================================== ! ! Perform the sequence a = a + 1 atomically with respect to other ! fetch-and-adds to location a in a wait-free fashion. ! ! usage : val = PR_AtomicIncrement(address) ! return: current value (you'd think this would be old val) ! ! ----------------------- ! Note on REGISTER USAGE: ! as this is a LEAF procedure, a new stack frame is not created; ! we use the caller's stack frame so what would normally be %i (input) ! registers are actually %o (output registers). Also, we must not ! overwrite the contents of %l (local) registers as they are not ! assumed to be volatile during calls. ! ! So, the registers used are: ! %o0 [input] - the address of the value to increment ! %o1 [local] - work register ! %o2 [local] - work register ! %o3 [local] - work register ! ----------------------- ENTRY(PR_AtomicIncrement) ! standard assembler/ELF prologue retryAI: ld [%o0], %o2 ! set o2 to the current value add %o2, 0x1, %o3 ! calc the new value mov %o3, %o1 ! save the return value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAI ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o1, %o0 ! set the return code to the new value SET_SIZE(PR_AtomicIncrement) ! standard assembler/ELF epilogue ! ! end ! ! ====================================================================== ! ! ====================================================================== ! ! Perform the sequence a = a - 1 atomically with respect to other ! fetch-and-decs to location a in a wait-free fashion. ! ! usage : val = PR_AtomicDecrement(address) ! return: current value (you'd think this would be old val) ! ! ----------------------- ! Note on REGISTER USAGE: ! as this is a LEAF procedure, a new stack frame is not created; ! we use the caller's stack frame so what would normally be %i (input) ! registers are actually %o (output registers). Also, we must not ! overwrite the contents of %l (local) registers as they are not ! assumed to be volatile during calls. ! ! So, the registers used are: ! %o0 [input] - the address of the value to increment ! %o1 [local] - work register ! %o2 [local] - work register ! %o3 [local] - work register ! ----------------------- ENTRY(PR_AtomicDecrement) ! standard assembler/ELF prologue retryAD: ld [%o0], %o2 ! set o2 to the current value sub %o2, 0x1, %o3 ! calc the new value mov %o3, %o1 ! save the return value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAD ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o1, %o0 ! set the return code to the new value SET_SIZE(PR_AtomicDecrement) ! standard assembler/ELF epilogue ! ! end ! ! ====================================================================== ! ! ====================================================================== ! ! Perform the sequence a = b atomically with respect to other ! fetch-and-stores to location a in a wait-free fashion. ! ! usage : old_val = PR_AtomicSet(address, newval) ! ! ----------------------- ! Note on REGISTER USAGE: ! as this is a LEAF procedure, a new stack frame is not created; ! we use the caller's stack frame so what would normally be %i (input) ! registers are actually %o (output registers). Also, we must not ! overwrite the contents of %l (local) registers as they are not ! assumed to be volatile during calls. ! ! So, the registers used are: ! %o0 [input] - the address of the value to increment ! %o1 [input] - the new value to set for [%o0] ! %o2 [local] - work register ! %o3 [local] - work register ! ----------------------- ENTRY(PR_AtomicSet) ! standard assembler/ELF prologue retryAS: ld [%o0], %o2 ! set o2 to the current value mov %o1, %o3 ! set up the new value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAS ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o3, %o0 ! set the return code to the prev value SET_SIZE(PR_AtomicSet) ! standard assembler/ELF epilogue ! ! end ! ! ====================================================================== ! ! ====================================================================== ! ! Perform the sequence a = a + b atomically with respect to other ! fetch-and-adds to location a in a wait-free fashion. ! ! usage : newval = PR_AtomicAdd(address, val) ! return: the value after addition ! ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue retryAA: ld [%o0], %o2 ! set o2 to the current value add %o2, %o1, %o3 ! calc the new value mov %o3, %o4 ! save the return value cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed cmp %o2, %o3 ! see if we set the value bne retryAA ! if not, try again nop ! empty out the branch pipeline retl ! return back to the caller mov %o4, %o0 ! set the return code to the new value SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue ! ! end ! nspr-4.11/nspr/pr/src/md/unix/os_SunOS_x86.s0000644000000000000000000000456412623070344016737 0ustar 00000000000000// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. .text .globl getedi getedi: movl %edi,%eax ret .type getedi,@function .size getedi,.-getedi .globl setedi setedi: movl 4(%esp),%edi ret .type setedi,@function .size setedi,.-setedi .globl __MD_FlushRegisterWindows .globl _MD_FlushRegisterWindows __MD_FlushRegisterWindows: _MD_FlushRegisterWindows: ret // // sol_getsp() // // Return the current sp (for debugging) // .globl sol_getsp sol_getsp: movl %esp, %eax ret // // sol_curthread() // // Return a unique identifier for the currently active thread. // .globl sol_curthread sol_curthread: movl %ecx, %eax ret // PRInt32 _MD_AtomicIncrement(PRInt32 *val) // // Atomically increment the integer pointed to by 'val' and return // the result of the increment. // .text .globl _MD_AtomicIncrement .align 4 _MD_AtomicIncrement: movl 4(%esp), %ecx movl $1, %eax lock xaddl %eax, (%ecx) incl %eax ret // PRInt32 _MD_AtomicDecrement(PRInt32 *val) // // Atomically decrement the integer pointed to by 'val' and return // the result of the decrement. // .text .globl _MD_AtomicDecrement .align 4 _MD_AtomicDecrement: movl 4(%esp), %ecx movl $-1, %eax lock xaddl %eax, (%ecx) decl %eax ret // PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval) // // Atomically set the integer pointed to by 'val' to the new // value 'newval' and return the old value. // // An alternative implementation: // .text // .globl _MD_AtomicSet // .align 4 //_MD_AtomicSet: // movl 4(%esp), %ecx // movl 8(%esp), %edx // movl (%ecx), %eax //retry: // lock // cmpxchgl %edx, (%ecx) // jne retry // ret // .text .globl _MD_AtomicSet .align 4 _MD_AtomicSet: movl 4(%esp), %ecx movl 8(%esp), %eax xchgl %eax, (%ecx) ret // PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val) // // Atomically add 'val' to the integer pointed to by 'ptr' // and return the result of the addition. // .text .globl _MD_AtomicAdd .align 4 _MD_AtomicAdd: movl 4(%esp), %ecx movl 8(%esp), %eax movl %eax, %edx lock xaddl %eax, (%ecx) addl %edx, %eax ret nspr-4.11/nspr/pr/src/md/unix/os_SunOS_x86_64.s0000644000000000000000000000267012623070344017244 0ustar 00000000000000// -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // PRInt32 _MD_AtomicIncrement(PRInt32 *val) // // Atomically increment the integer pointed to by 'val' and return // the result of the increment. // .text .globl _MD_AtomicIncrement .align 4 _MD_AtomicIncrement: movl $1, %eax lock xaddl %eax, (%rdi) incl %eax ret // PRInt32 _MD_AtomicDecrement(PRInt32 *val) // // Atomically decrement the integer pointed to by 'val' and return // the result of the decrement. // .text .globl _MD_AtomicDecrement .align 4 _MD_AtomicDecrement: movl $-1, %eax lock xaddl %eax, (%rdi) decl %eax ret // PRInt32 _MD_AtomicSet(PRInt32 *val, PRInt32 newval) // // Atomically set the integer pointed to by 'val' to the new // value 'newval' and return the old value. // .text .globl _MD_AtomicSet .align 4 _MD_AtomicSet: movl %esi, %eax xchgl %eax, (%rdi) ret // PRInt32 _MD_AtomicAdd(PRInt32 *ptr, PRInt32 val) // // Atomically add 'val' to the integer pointed to by 'ptr' // and return the result of the addition. // .text .globl _MD_AtomicAdd .align 4 _MD_AtomicAdd: movl %esi, %eax lock xaddl %eax, (%rdi) addl %esi, %eax ret nspr-4.11/nspr/pr/src/md/unix/osf1.c0000644000000000000000000000300112623070344015333 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifndef _PR_PTHREADS void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for OSF1 */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for OSF1."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for OSF1."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/pthreads_user.c0000644000000000000000000002465312623070344017353 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include sigset_t ints_off; pthread_mutex_t _pr_heapLock; pthread_key_t current_thread_key; pthread_key_t current_cpu_key; pthread_key_t last_thread_key; pthread_key_t intsoff_key; PRInt32 _pr_md_pthreads_created, _pr_md_pthreads_failed; PRInt32 _pr_md_pthreads = 1; void _MD_EarlyInit(void) { extern PRInt32 _nspr_noclock; if (pthread_key_create(¤t_thread_key, NULL) != 0) { perror("pthread_key_create failed"); exit(1); } if (pthread_key_create(¤t_cpu_key, NULL) != 0) { perror("pthread_key_create failed"); exit(1); } if (pthread_key_create(&last_thread_key, NULL) != 0) { perror("pthread_key_create failed"); exit(1); } if (pthread_key_create(&intsoff_key, NULL) != 0) { perror("pthread_key_create failed"); exit(1); } sigemptyset(&ints_off); sigaddset(&ints_off, SIGALRM); sigaddset(&ints_off, SIGIO); sigaddset(&ints_off, SIGCLD); /* * disable clock interrupts */ _nspr_noclock = 1; } void _MD_InitLocks() { if (pthread_mutex_init(&_pr_heapLock, NULL) != 0) { perror("pthread_mutex_init failed"); exit(1); } } PR_IMPLEMENT(void) _MD_FREE_LOCK(struct _MDLock *lockp) { PRIntn _is; PRThread *me = _PR_MD_CURRENT_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(_is); pthread_mutex_destroy(&lockp->mutex); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(_is); } PR_IMPLEMENT(PRStatus) _MD_NEW_LOCK(struct _MDLock *lockp) { PRStatus rv; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); rv = pthread_mutex_init(&lockp->mutex, NULL); if (me && !_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return (rv == 0) ? PR_SUCCESS : PR_FAILURE; } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); } PR_IMPLEMENT(void) _MD_SetPriority(_MDThread *thread, PRThreadPriority newPri) { /* * XXX - to be implemented */ return; } PR_IMPLEMENT(PRStatus) _MD_InitThread(struct PRThread *thread) { struct sigaction sigact; if (thread->flags & _PR_GLOBAL_SCOPE) { thread->md.pthread = pthread_self(); #if 0 /* * set up SIGUSR1 handler; this is used to save state * during PR_SuspendAll */ sigact.sa_handler = save_context_and_block; sigact.sa_flags = SA_RESTART; /* * Must mask clock interrupts */ sigact.sa_mask = timer_set; sigaction(SIGUSR1, &sigact, 0); #endif } return PR_SUCCESS; } PR_IMPLEMENT(void) _MD_ExitThread(struct PRThread *thread) { if (thread->flags & _PR_GLOBAL_SCOPE) { _MD_CLEAN_THREAD(thread); _MD_SET_CURRENT_THREAD(NULL); } } PR_IMPLEMENT(void) _MD_CleanThread(struct PRThread *thread) { if (thread->flags & _PR_GLOBAL_SCOPE) { pthread_mutex_destroy(&thread->md.pthread_mutex); pthread_cond_destroy(&thread->md.pthread_cond); } } PR_IMPLEMENT(void) _MD_SuspendThread(struct PRThread *thread) { PRInt32 rv; PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && _PR_IS_GCABLE_THREAD(thread)); #if 0 thread->md.suspending_id = getpid(); rv = kill(thread->md.id, SIGUSR1); PR_ASSERT(rv == 0); /* * now, block the current thread/cpu until woken up by the suspended * thread from it's SIGUSR1 signal handler */ blockproc(getpid()); #endif } PR_IMPLEMENT(void) _MD_ResumeThread(struct PRThread *thread) { PRInt32 rv; PR_ASSERT((thread->flags & _PR_GLOBAL_SCOPE) && _PR_IS_GCABLE_THREAD(thread)); #if 0 rv = unblockproc(thread->md.id); #endif } PR_IMPLEMENT(void) _MD_SuspendCPU(struct _PRCPU *thread) { PRInt32 rv; #if 0 cpu->md.suspending_id = getpid(); rv = kill(cpu->md.id, SIGUSR1); PR_ASSERT(rv == 0); /* * now, block the current thread/cpu until woken up by the suspended * thread from it's SIGUSR1 signal handler */ blockproc(getpid()); #endif } PR_IMPLEMENT(void) _MD_ResumeCPU(struct _PRCPU *thread) { #if 0 unblockproc(cpu->md.id); #endif } #define PT_NANOPERMICRO 1000UL #define PT_BILLION 1000000000UL PR_IMPLEMENT(PRStatus) _pt_wait(PRThread *thread, PRIntervalTime timeout) { int rv; struct timeval now; struct timespec tmo; PRUint32 ticks = PR_TicksPerSecond(); if (timeout != PR_INTERVAL_NO_TIMEOUT) { tmo.tv_sec = timeout / ticks; tmo.tv_nsec = timeout - (tmo.tv_sec * ticks); tmo.tv_nsec = PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec); /* pthreads wants this in absolute time, off we go ... */ (void)GETTIMEOFDAY(&now); /* that one's usecs, this one's nsecs - grrrr! */ tmo.tv_sec += now.tv_sec; tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec); tmo.tv_sec += tmo.tv_nsec / PT_BILLION; tmo.tv_nsec %= PT_BILLION; } pthread_mutex_lock(&thread->md.pthread_mutex); thread->md.wait--; if (thread->md.wait < 0) { if (timeout != PR_INTERVAL_NO_TIMEOUT) { rv = pthread_cond_timedwait(&thread->md.pthread_cond, &thread->md.pthread_mutex, &tmo); } else rv = pthread_cond_wait(&thread->md.pthread_cond, &thread->md.pthread_mutex); if (rv != 0) { thread->md.wait++; } } else rv = 0; pthread_mutex_unlock(&thread->md.pthread_mutex); return (rv == 0) ? PR_SUCCESS : PR_FAILURE; } PR_IMPLEMENT(PRStatus) _MD_wait(PRThread *thread, PRIntervalTime ticks) { if ( thread->flags & _PR_GLOBAL_SCOPE ) { _MD_CHECK_FOR_EXIT(); if (_pt_wait(thread, ticks) == PR_FAILURE) { _MD_CHECK_FOR_EXIT(); /* * wait timed out */ _PR_THREAD_LOCK(thread); if (thread->wait.cvar) { /* * The thread will remove itself from the waitQ * of the cvar in _PR_WaitCondVar */ thread->wait.cvar = NULL; thread->state = _PR_RUNNING; _PR_THREAD_UNLOCK(thread); } else { _pt_wait(thread, PR_INTERVAL_NO_TIMEOUT); _PR_THREAD_UNLOCK(thread); } } } else { _PR_MD_SWITCH_CONTEXT(thread); } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) _MD_WakeupWaiter(PRThread *thread) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 pid, rv; PRIntn is; PR_ASSERT(_pr_md_idle_cpus >= 0); if (thread == NULL) { if (_pr_md_idle_cpus) _MD_Wakeup_CPUs(); } else if (!_PR_IS_NATIVE_THREAD(thread)) { /* * If the thread is on my cpu's runq there is no need to * wakeup any cpus */ if (!_PR_IS_NATIVE_THREAD(me)) { if (me->cpu != thread->cpu) { if (_pr_md_idle_cpus) _MD_Wakeup_CPUs(); } } else { if (_pr_md_idle_cpus) _MD_Wakeup_CPUs(); } } else { PR_ASSERT(_PR_IS_NATIVE_THREAD(thread)); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); pthread_mutex_lock(&thread->md.pthread_mutex); thread->md.wait++; rv = pthread_cond_signal(&thread->md.pthread_cond); PR_ASSERT(rv == 0); pthread_mutex_unlock(&thread->md.pthread_mutex); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); } return PR_SUCCESS; } /* These functions should not be called for AIX */ PR_IMPLEMENT(void) _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for AIX."); } PR_IMPLEMENT(PRStatus) _MD_CreateThread( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PRIntn is; int rv; PRThread *me = _PR_MD_CURRENT_THREAD(); pthread_attr_t attr; if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); if (pthread_mutex_init(&thread->md.pthread_mutex, NULL) != 0) { if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } if (pthread_cond_init(&thread->md.pthread_cond, NULL) != 0) { pthread_mutex_destroy(&thread->md.pthread_mutex); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } thread->flags |= _PR_GLOBAL_SCOPE; pthread_attr_init(&attr); /* initialize attr with default attributes */ if (pthread_attr_setstacksize(&attr, (size_t) stackSize) != 0) { pthread_mutex_destroy(&thread->md.pthread_mutex); pthread_cond_destroy(&thread->md.pthread_cond); pthread_attr_destroy(&attr); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_FAILURE; } thread->md.wait = 0; rv = pthread_create(&thread->md.pthread, &attr, start, (void *)thread); if (0 == rv) { _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_created); _MD_ATOMIC_INCREMENT(&_pr_md_pthreads); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return PR_SUCCESS; } else { pthread_mutex_destroy(&thread->md.pthread_mutex); pthread_cond_destroy(&thread->md.pthread_cond); pthread_attr_destroy(&attr); _MD_ATOMIC_INCREMENT(&_pr_md_pthreads_failed); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, rv); return PR_FAILURE; } } PR_IMPLEMENT(void) _MD_InitRunningCPU(struct _PRCPU *cpu) { extern int _pr_md_pipefd[2]; _MD_unix_init_running_cpu(cpu); cpu->md.pthread = pthread_self(); if (_pr_md_pipefd[0] >= 0) { _PR_IOQ_MAX_OSFD(cpu) = _pr_md_pipefd[0]; #ifndef _PR_USE_POLL FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(cpu)); #endif } } void _MD_CleanupBeforeExit(void) { #if 0 extern PRInt32 _pr_cpus_exit; _pr_irix_exit_now = 1; if (_pr_numCPU > 1) { /* * Set a global flag, and wakeup all cpus which will notice the flag * and exit. */ _pr_cpus_exit = getpid(); _MD_Wakeup_CPUs(); while(_pr_numCPU > 1) { _PR_WAIT_SEM(_pr_irix_exit_sem); _pr_numCPU--; } } /* * cause global threads on the recycle list to exit */ _PR_DEADQ_LOCK; if (_PR_NUM_DEADNATIVE != 0) { PRThread *thread; PRCList *ptr; ptr = _PR_DEADNATIVEQ.next; while( ptr != &_PR_DEADNATIVEQ ) { thread = _PR_THREAD_PTR(ptr); _MD_CVAR_POST_SEM(thread); ptr = ptr->next; } } _PR_DEADQ_UNLOCK; while(_PR_NUM_DEADNATIVE > 1) { _PR_WAIT_SEM(_pr_irix_exit_sem); _PR_DEC_DEADNATIVE; } #endif } nspr-4.11/nspr/pr/src/md/unix/qnx.c0000644000000000000000000000266112623070344015304 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); } void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for Unixware */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for Unixware."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRUintn priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Unixware."); return PR_FAILURE; } nspr-4.11/nspr/pr/src/md/unix/riscos.c0000644000000000000000000000344212623070344015776 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #ifndef _PR_PTHREADS if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); #else *np = 0; return NULL; #endif } #ifdef _PR_PTHREADS void _MD_CleanupBeforeExit(void) { } #else /* ! _PR_PTHREADS */ void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { /* * set the pointers to the stack-pointer and frame-pointer words in the * context structure; this is for debugging use. */ thread->md.sp = _MD_GET_SP_PTR(thread); thread->md.fp = _MD_GET_FP_PTR(thread); return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for RISC OS */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for RISC OS."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for RISC OS."); return PR_FAILURE; } #endif /* ! _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/scoos.c0000644000000000000000000000565612623070344015633 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * SCO ODT 5.0 - originally created by mikep */ #include "primpl.h" #include void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); } #ifdef ALARMS_BREAK_TCP /* I don't think they do */ PRInt32 _MD_connect(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout) { PRInt32 rv; _MD_BLOCK_CLOCK_INTERRUPTS(); rv = _connect(osfd,addr,addrlen); _MD_UNBLOCK_CLOCK_INTERRUPTS(); } PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout) { PRInt32 rv; _MD_BLOCK_CLOCK_INTERRUPTS(); rv = _accept(osfd,addr,addrlen); _MD_UNBLOCK_CLOCK_INTERRUPTS(); return(rv); } #endif /* * These are also implemented in pratom.c using NSPR locks. Any reason * this might be better or worse? If you like this better, define * _PR_HAVE_ATOMIC_OPS in include/md/unixware.h */ #ifdef _PR_HAVE_ATOMIC_OPS /* Atomic operations */ #include static FILE *_uw_semf; void _MD_INIT_ATOMIC(void) { /* Sigh. Sure wish SYSV semaphores weren't such a pain to use */ if ((_uw_semf = tmpfile()) == NULL) PR_ASSERT(0); return; } void _MD_ATOMIC_INCREMENT(PRInt32 *val) { flockfile(_uw_semf); (*val)++; unflockfile(_uw_semf); } void _MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) { flockfile(_uw_semf); (*ptr) += val; unflockfile(_uw_semf); } void _MD_ATOMIC_DECREMENT(PRInt32 *val) { flockfile(_uw_semf); (*val)--; unflockfile(_uw_semf); } void _MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) { flockfile(_uw_semf); *val = newval; unflockfile(_uw_semf); } #endif void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for SCO */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for SCO."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SCO."); } nspr-4.11/nspr/pr/src/md/unix/solaris.c0000644000000000000000000000663312623070344016155 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" extern PRBool suspendAllOn; extern PRThread *suspendAllThread; extern void _MD_SET_PRIORITY(_MDThread *md, PRThreadPriority newPri); PRIntervalTime _MD_Solaris_TicksPerSecond(void) { /* * Ticks have a 10-microsecond resolution. So there are * 100000 ticks per second. */ return 100000UL; } /* Interval timers, implemented using gethrtime() */ PRIntervalTime _MD_Solaris_GetInterval(void) { union { hrtime_t hrt; /* hrtime_t is a 64-bit (long long) integer */ PRInt64 pr64; } time; PRInt64 resolution; PRIntervalTime ticks; time.hrt = gethrtime(); /* in nanoseconds */ /* * Convert from nanoseconds to ticks. A tick's resolution is * 10 microseconds, or 10000 nanoseconds. */ LL_I2L(resolution, 10000); LL_DIV(time.pr64, time.pr64, resolution); LL_L2UI(ticks, time.pr64); return ticks; } #ifdef _PR_PTHREADS void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np) { *np = 0; return NULL; } #endif /* _PR_PTHREADS */ #if defined(_PR_LOCAL_THREADS_ONLY) void _MD_EarlyInit(void) { } void _MD_SolarisInit() { _PR_UnixInit(); } void _MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { PR_ASSERT((thread == NULL) || (!(thread->flags & _PR_GLOBAL_SCOPE))); return PR_SUCCESS; } /* These functions should not be called for Solaris */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for Solaris"); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Solaris"); return(PR_FAILURE); } #ifdef USE_SETJMP PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); } #else PRWord *_MD_HomeGCRegisters(PRThread *t, PRIntn isCurrent, PRIntn *np) { if (isCurrent) { (void) getcontext(CONTEXT(t)); } *np = NGREG; return (PRWord*) &t->md.context.uc_mcontext.gregs[0]; } #endif /* USE_SETJMP */ #endif /* _PR_LOCAL_THREADS_ONLY */ #ifndef _PR_PTHREADS #if defined(i386) && defined(SOLARIS2_4) /* * Because clock_gettime() on Solaris/x86 2.4 always generates a * segmentation fault, we use an emulated version _pr_solx86_clock_gettime(), * which is implemented using gettimeofday(). */ int _pr_solx86_clock_gettime(clockid_t clock_id, struct timespec *tp) { struct timeval tv; if (clock_id != CLOCK_REALTIME) { errno = EINVAL; return -1; } gettimeofday(&tv, NULL); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; return 0; } #endif /* i386 && SOLARIS2_4 */ #endif /* _PR_PTHREADS */ nspr-4.11/nspr/pr/src/md/unix/symbian.c0000644000000000000000000000066412623070344016141 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { *np = 0; return NULL; } nspr-4.11/nspr/pr/src/md/unix/unix.c0000644000000000000000000031732312623070344015465 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef _PR_POLL_AVAILABLE #include #endif #if defined(ANDROID) #include #endif /* To get FIONREAD */ #if defined(UNIXWARE) #include #endif #if defined(NTO) #include #endif /* * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or * PRInt32* pointer to a _PRSockLen_t* pointer. */ #if defined(HAVE_SOCKLEN_T) \ || (defined(__GLIBC__) && __GLIBC__ >= 2) #define _PRSockLen_t socklen_t #elif defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \ || defined(AIX4_1) || defined(LINUX) \ || defined(BSDI) || defined(SCO) \ || defined(DARWIN) \ || defined(QNX) #define _PRSockLen_t int #elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \ || defined(NETBSD) || defined(OPENBSD) || defined(UNIXWARE) \ || defined(DGUX) || defined(NTO) || defined(RISCOS) #define _PRSockLen_t size_t #else #error "Cannot determine architecture" #endif /* ** Global lock variable used to bracket calls into rusty libraries that ** aren't thread safe (like libc, libX, etc). */ static PRLock *_pr_rename_lock = NULL; static PRMonitor *_pr_Xfe_mon = NULL; static PRInt64 minus_one; sigset_t timer_set; #if !defined(_PR_PTHREADS) static sigset_t empty_set; #ifdef SOLARIS #include #include #endif #ifndef PIPE_BUF #define PIPE_BUF 512 #endif /* * _nspr_noclock - if set clock interrupts are disabled */ int _nspr_noclock = 1; #ifdef IRIX extern PRInt32 _nspr_terminate_on_error; #endif /* * There is an assertion in this code that NSPR's definition of PRIOVec * is bit compatible with UNIX' definition of a struct iovec. This is * applicable to the 'writev()' operations where the types are casually * cast to avoid warnings. */ int _pr_md_pipefd[2] = { -1, -1 }; static char _pr_md_pipebuf[PIPE_BUF]; static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag, PRIntervalTime timeout); _PRInterruptTable _pr_interruptTable[] = { { "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, }, { 0 } }; void _MD_unix_init_running_cpu(_PRCPU *cpu) { PR_INIT_CLIST(&(cpu->md.md_unix.ioQ)); cpu->md.md_unix.ioq_max_osfd = -1; cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT; } PRStatus _MD_open_dir(_MDDir *d, const char *name) { int err; d->d = opendir(name); if (!d->d) { err = _MD_ERRNO(); _PR_MD_MAP_OPENDIR_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; } PRInt32 _MD_close_dir(_MDDir *d) { int rv = 0, err; if (d->d) { rv = closedir(d->d); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_CLOSEDIR_ERROR(err); } } return rv; } char * _MD_read_dir(_MDDir *d, PRIntn flags) { struct dirent *de; int err; for (;;) { /* * XXX: readdir() is not MT-safe. There is an MT-safe version * readdir_r() on some systems. */ _MD_ERRNO() = 0; de = readdir(d->d); if (!de) { err = _MD_ERRNO(); _PR_MD_MAP_READDIR_ERROR(err); return 0; } if ((flags & PR_SKIP_DOT) && (de->d_name[0] == '.') && (de->d_name[1] == 0)) continue; if ((flags & PR_SKIP_DOT_DOT) && (de->d_name[0] == '.') && (de->d_name[1] == '.') && (de->d_name[2] == 0)) continue; if ((flags & PR_SKIP_HIDDEN) && (de->d_name[0] == '.')) continue; break; } return de->d_name; } PRInt32 _MD_delete(const char *name) { PRInt32 rv, err; #ifdef UNIXWARE sigset_t set, oset; #endif #ifdef UNIXWARE sigfillset(&set); sigprocmask(SIG_SETMASK, &set, &oset); #endif rv = unlink(name); #ifdef UNIXWARE sigprocmask(SIG_SETMASK, &oset, NULL); #endif if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_UNLINK_ERROR(err); } return(rv); } PRInt32 _MD_rename(const char *from, const char *to) { PRInt32 rv = -1, err; /* ** This is trying to enforce the semantics of WINDOZE' rename ** operation. That means one is not allowed to rename over top ** of an existing file. Holding a lock across these two function ** and the open function is known to be a bad idea, but .... */ if (NULL != _pr_rename_lock) PR_Lock(_pr_rename_lock); if (0 == access(to, F_OK)) PR_SetError(PR_FILE_EXISTS_ERROR, 0); else { rv = rename(from, to); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_RENAME_ERROR(err); } } if (NULL != _pr_rename_lock) PR_Unlock(_pr_rename_lock); return rv; } PRInt32 _MD_access(const char *name, PRAccessHow how) { PRInt32 rv, err; int amode; switch (how) { case PR_ACCESS_WRITE_OK: amode = W_OK; break; case PR_ACCESS_READ_OK: amode = R_OK; break; case PR_ACCESS_EXISTS: amode = F_OK; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = -1; goto done; } rv = access(name, amode); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_ACCESS_ERROR(err); } done: return(rv); } PRInt32 _MD_mkdir(const char *name, PRIntn mode) { int rv, err; /* ** This lock is used to enforce rename semantics as described ** in PR_Rename. Look there for more fun details. */ if (NULL !=_pr_rename_lock) PR_Lock(_pr_rename_lock); rv = mkdir(name, mode); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_MKDIR_ERROR(err); } if (NULL !=_pr_rename_lock) PR_Unlock(_pr_rename_lock); return rv; } PRInt32 _MD_rmdir(const char *name) { int rv, err; rv = rmdir(name); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_RMDIR_ERROR(err); } return rv; } PRInt32 _MD_read(PRFileDesc *fd, void *buf, PRInt32 amount) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 rv, err; #ifndef _PR_USE_POLL fd_set rd; #else struct pollfd pfd; #endif /* _PR_USE_POLL */ PRInt32 osfd = fd->secret->md.osfd; #ifndef _PR_USE_POLL FD_ZERO(&rd); FD_SET(osfd, &rd); #else pfd.fd = osfd; pfd.events = POLLIN; #endif /* _PR_USE_POLL */ while ((rv = read(osfd,buf,amount)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, PR_INTERVAL_NO_TIMEOUT)) < 0) goto done; } else { #ifndef _PR_USE_POLL while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_SELECT() if it is interrupted */ } #else /* _PR_USE_POLL */ while ((rv = _MD_POLL(&pfd, 1, -1)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_POLL() if it is interrupted */ } #endif /* _PR_USE_POLL */ if (rv == -1) { break; } } if (_PR_PENDING_INTERRUPT(me)) break; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { _PR_MD_MAP_READ_ERROR(err); } } done: return(rv); } PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 rv, err; #ifndef _PR_USE_POLL fd_set wd; #else struct pollfd pfd; #endif /* _PR_USE_POLL */ PRInt32 osfd = fd->secret->md.osfd; #ifndef _PR_USE_POLL FD_ZERO(&wd); FD_SET(osfd, &wd); #else pfd.fd = osfd; pfd.events = POLLOUT; #endif /* _PR_USE_POLL */ while ((rv = write(osfd,buf,amount)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, PR_INTERVAL_NO_TIMEOUT)) < 0) goto done; } else { #ifndef _PR_USE_POLL while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_SELECT() if it is interrupted */ } #else /* _PR_USE_POLL */ while ((rv = _MD_POLL(&pfd, 1, -1)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_POLL() if it is interrupted */ } #endif /* _PR_USE_POLL */ if (rv == -1) { break; } } if (_PR_PENDING_INTERRUPT(me)) break; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { _PR_MD_MAP_WRITE_ERROR(err); } } done: return(rv); } PRInt32 _MD_fsync(PRFileDesc *fd) { PRInt32 rv, err; rv = fsync(fd->secret->md.osfd); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_FSYNC_ERROR(err); } return(rv); } PRInt32 _MD_close(PRInt32 osfd) { PRInt32 rv, err; rv = close(osfd); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_CLOSE_ERROR(err); } return(rv); } PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { PRInt32 osfd, err; osfd = socket(domain, type, proto); if (osfd == -1) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKET_ERROR(err); return(osfd); } return(osfd); } PRInt32 _MD_socketavailable(PRFileDesc *fd) { PRInt32 result; if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) { _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO()); return -1; } return result; } PRInt64 _MD_socketavailable64(PRFileDesc *fd) { PRInt64 result; LL_I2L(result, _MD_socketavailable(fd)); return result; } /* _MD_socketavailable64 */ #define READ_FD 1 #define WRITE_FD 2 /* * socket_io_wait -- * * wait for socket i/o, periodically checking for interrupt * * The first implementation uses select(), for platforms without * poll(). The second (preferred) implementation uses poll(). */ #ifndef _PR_USE_POLL static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout) { PRInt32 rv = -1; struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRInt32 syserror; fd_set rd_wr; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; FD_ZERO(&rd_wr); do { FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_SELECT_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; default: now = epoch = PR_IntervalNow(); remaining = timeout; FD_ZERO(&rd_wr); do { /* * We block in _MD_SELECT for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { tv.tv_usec = PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); } FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); /* * we don't consider EINTR a real error */ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_SELECT_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * We loop again if _MD_SELECT timed out or got interrupted * by a signal, and the timeout deadline has not passed yet. */ if (rv == 0 || (rv == -1 && syserror == EINTR)) { /* * If _MD_SELECT timed out, we know how much time * we spent in blocking, so we can avoid a * PR_IntervalNow() call. */ if (rv == 0) { if (wait_for_remaining) { now += remaining; } else { now += PR_SecondsToInterval(tv.tv_sec) + PR_MicrosecondsToInterval(tv.tv_usec); } } else { now = PR_IntervalNow(); } elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = timeout - elapsed; } } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; } return(rv); } #else /* _PR_USE_POLL */ static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout) { PRInt32 rv = -1; int msecs; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRInt32 syserror; struct pollfd pfd; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; pfd.fd = osfd; if (fd_type == READ_FD) { pfd.events = POLLIN; } else { pfd.events = POLLOUT; } do { rv = _MD_POLL(&pfd, 1, msecs); if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_POLL_ERROR(syserror); break; } /* * If POLLERR is set, don't process it; retry the operation */ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) { rv = -1; _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; default: now = epoch = PR_IntervalNow(); remaining = timeout; pfd.fd = osfd; if (fd_type == READ_FD) { pfd.events = POLLIN; } else { pfd.events = POLLOUT; } do { /* * We block in _MD_POLL for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; msecs = PR_IntervalToMilliseconds(remaining); if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { wait_for_remaining = PR_FALSE; msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; } rv = _MD_POLL(&pfd, 1, msecs); /* * we don't consider EINTR a real error */ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_POLL_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * If POLLERR is set, don't process it; retry the operation */ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) { rv = -1; _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents); break; } /* * We loop again if _MD_POLL timed out or got interrupted * by a signal, and the timeout deadline has not passed yet. */ if (rv == 0 || (rv == -1 && syserror == EINTR)) { /* * If _MD_POLL timed out, we know how much time * we spent in blocking, so we can avoid a * PR_IntervalNow() call. */ if (rv == 0) { if (wait_for_remaining) { now += remaining; } else { now += PR_MillisecondsToInterval(msecs); } } else { now = PR_IntervalNow(); } elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = timeout - elapsed; } } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; } return(rv); } #endif /* _PR_USE_POLL */ static PRInt32 local_io_wait( PRInt32 osfd, PRInt32 wait_flag, PRIntervalTime timeout) { _PRUnixPollDesc pd; PRInt32 rv; PR_LOG(_pr_io_lm, PR_LOG_MIN, ("waiting to %s on osfd=%d", (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write", osfd)); if (timeout == PR_INTERVAL_NO_WAIT) return 0; pd.osfd = osfd; pd.in_flags = wait_flag; pd.out_flags = 0; rv = _PR_WaitForMultipleFDs(&pd, 1, timeout); if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; } return rv; } PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); /* * Many OS's (Solaris, Unixware) have a broken recv which won't read * from socketpairs. As long as we don't use flags on socketpairs, this * is a decent fix. - mikep */ #if defined(UNIXWARE) || defined(SOLARIS) while ((rv = read(osfd,buf,amount)) == -1) { #else while ((rv = recv(osfd,buf,amount,flags)) == -1) { #endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd,_PR_UNIX_POLL_READ,timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECV_ERROR(err); } done: return(rv); } PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((*addrlen = PR_NETADDR_SIZE(addr)), ((rv = recvfrom(osfd, buf, amount, flags, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECVFROM_ERROR(err); } done: #ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv); } PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); #if defined(SOLARIS) PRInt32 tmp_amount = amount; #endif /* * On pre-2.6 Solaris, send() is much slower than write(). * On 2.6 and beyond, with in-kernel sockets, send() and * write() are fairly equivalent in performance. */ #if defined(SOLARIS) PR_ASSERT(0 == flags); while ((rv = write(osfd,buf,tmp_amount)) == -1) { #else while ((rv = send(osfd,buf,amount,flags)) == -1) { #endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { #if defined(SOLARIS) /* * The write system call has been reported to return the ERANGE * error on occasion. Try to write in smaller chunks to workaround * this bug. */ if (err == ERANGE) { if (tmp_amount > 1) { tmp_amount = tmp_amount/2; /* half the bytes */ continue; } } #endif break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next send() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (_PR_IS_NATIVE_THREAD(me)) { if (socket_io_wait(osfd, WRITE_FD, timeout)< 0) { rv = -1; goto done; } } else { if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) { rv = -1; goto done; } } } if (rv < 0) { _PR_MD_MAP_SEND_ERROR(err); } done: return(rv); } PRInt32 _MD_sendto( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); #ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) &addrCopy, addrlen)) == -1) { #else while ((rv = sendto(osfd, buf, amount, flags, (struct sockaddr *) addr, addrlen)) == -1) { #endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))< 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_SENDTO_ERROR(err); } done: return(rv); } PRInt32 _MD_writev( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 index, amount = 0; PRInt32 osfd = fd->secret->md.osfd; /* * Calculate the total number of bytes to be sent; needed for * optimization later. * We could avoid this if this number was passed in; but it is * probably not a big deal because iov_size is usually small (less than * 3) */ if (!fd->secret->nonblocking) { for (index=0; indexsecret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, WRITE_FD, timeout))<0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } /* * optimization; if bytes sent is less than "amount" call * select before returning. This is because it is likely that * the next writev() call will return EWOULDBLOCK. */ if ((!fd->secret->nonblocking) && (rv > 0) && (rv < amount) && (timeout != PR_INTERVAL_NO_WAIT)) { if (_PR_IS_NATIVE_THREAD(me)) { if (socket_io_wait(osfd, WRITE_FD, timeout) < 0) { rv = -1; goto done; } } else { if (local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout) < 0) { rv = -1; goto done; } } } if (rv < 0) { _PR_MD_MAP_WRITEV_ERROR(err); } done: return(rv); } PRInt32 _MD_accept(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((rv = accept(osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK) || (err == ECONNABORTED)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_ACCEPT_ERROR(err); } done: #ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv); } extern int _connect (int s, const struct sockaddr *name, int namelen); PRInt32 _MD_connect( PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 osfd = fd->secret->md.osfd; #ifdef IRIX extern PRInt32 _MD_irix_connect( PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout); #endif #ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; #endif /* * We initiate the connection setup by making a nonblocking connect() * call. If the connect() call fails, there are two cases we handle * specially: * 1. The connect() call was interrupted by a signal. In this case * we simply retry connect(). * 2. The NSPR socket is nonblocking and connect() fails with * EINPROGRESS. We first wait until the socket becomes writable. * Then we try to find out whether the connection setup succeeded * or failed. */ retry: #ifdef IRIX if ((rv = _MD_irix_connect(osfd, addr, addrlen, timeout)) == -1) { #else #ifdef _PR_HAVE_SOCKADDR_LEN if ((rv = connect(osfd, (struct sockaddr *)&addrCopy, addrlen)) == -1) { #else if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) { #endif #endif err = _MD_ERRNO(); if (err == EINTR) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } goto retry; } if (!fd->secret->nonblocking && (err == EINPROGRESS)) { if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, timeout)) < 0) return -1; } else { /* * socket_io_wait() may return -1 or 1. */ rv = socket_io_wait(osfd, WRITE_FD, timeout); if (rv == -1) { return -1; } } PR_ASSERT(rv == 1); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0); return -1; } err = _MD_unix_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return -1; } return 0; } _PR_MD_MAP_CONNECT_ERROR(err); } return rv; } /* _MD_connect */ PRInt32 _MD_bind(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv, err; #ifdef _PR_HAVE_SOCKADDR_LEN PRNetAddr addrCopy; addrCopy = *addr; ((struct sockaddr *) &addrCopy)->sa_len = addrlen; ((struct sockaddr *) &addrCopy)->sa_family = addr->raw.family; rv = bind(fd->secret->md.osfd, (struct sockaddr *) &addrCopy, (int )addrlen); #else rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen); #endif if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_BIND_ERROR(err); } return(rv); } PRInt32 _MD_listen(PRFileDesc *fd, PRIntn backlog) { PRInt32 rv, err; rv = listen(fd->secret->md.osfd, backlog); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_LISTEN_ERROR(err); } return(rv); } PRInt32 _MD_shutdown(PRFileDesc *fd, PRIntn how) { PRInt32 rv, err; rv = shutdown(fd->secret->md.osfd, how); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SHUTDOWN_ERROR(err); } return(rv); } PRInt32 _MD_socketpair(int af, int type, int flags, PRInt32 *osfd) { PRInt32 rv, err; rv = socketpair(af, type, flags, osfd); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKETPAIR_ERROR(err); } return rv; } PRStatus _MD_getsockname(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 rv, err; rv = getsockname(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); #ifdef _PR_HAVE_SOCKADDR_LEN if (rv == 0) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_getpeername(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen) { PRInt32 rv, err; rv = getpeername(fd->secret->md.osfd, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen); #ifdef _PR_HAVE_SOCKADDR_LEN if (rv == 0) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } } #endif /* _PR_HAVE_SOCKADDR_LEN */ if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETPEERNAME_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_getsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) { PRInt32 rv, err; rv = getsockopt(fd->secret->md.osfd, level, optname, optval, (_PRSockLen_t *)optlen); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_GETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_setsockopt(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen) { PRInt32 rv, err; rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_SETSOCKOPT_ERROR(err); } return rv==0?PR_SUCCESS:PR_FAILURE; } PRStatus _MD_set_fd_inheritable(PRFileDesc *fd, PRBool inheritable) { int rv; rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC); if (-1 == rv) { PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); return PR_FAILURE; } return PR_SUCCESS; } void _MD_init_fd_inheritable(PRFileDesc *fd, PRBool imported) { if (imported) { fd->secret->inheritable = _PR_TRI_UNKNOWN; } else { /* By default, a Unix fd is not closed on exec. */ #ifdef DEBUG { int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); PR_ASSERT(0 == flags); } #endif fd->secret->inheritable = _PR_TRI_TRUE; } } /************************************************************************/ #if !defined(_PR_USE_POLL) /* ** Scan through io queue and find any bad fd's that triggered the error ** from _MD_SELECT */ static void FindBadFDs(void) { PRCList *q; PRThread *me = _MD_CURRENT_THREAD(); PR_ASSERT(!_PR_IS_NATIVE_THREAD(me)); q = (_PR_IOQ(me->cpu)).next; _PR_IOQ_MAX_OSFD(me->cpu) = -1; _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT; while (q != &_PR_IOQ(me->cpu)) { PRPollQueue *pq = _PR_POLLQUEUE_PTR(q); PRBool notify = PR_FALSE; _PRUnixPollDesc *pds = pq->pds; _PRUnixPollDesc *epds = pds + pq->npds; PRInt32 pq_max_osfd = -1; q = q->next; for (; pds < epds; pds++) { PRInt32 osfd = pds->osfd; pds->out_flags = 0; PR_ASSERT(osfd >= 0 || pds->in_flags == 0); if (pds->in_flags == 0) { continue; /* skip this fd */ } if (fcntl(osfd, F_GETFL, 0) == -1) { /* Found a bad descriptor, remove it from the fd_sets. */ PR_LOG(_pr_io_lm, PR_LOG_MAX, ("file descriptor %d is bad", osfd)); pds->out_flags = _PR_UNIX_POLL_NVAL; notify = PR_TRUE; } if (osfd > pq_max_osfd) { pq_max_osfd = osfd; } } if (notify) { PRIntn pri; PR_REMOVE_LINK(&pq->links); pq->on_ioq = PR_FALSE; /* * Decrement the count of descriptors for each desciptor/event * because this I/O request is being removed from the * ioq */ pds = pq->pds; for (; pds < epds; pds++) { PRInt32 osfd = pds->osfd; PRInt16 in_flags = pds->in_flags; PR_ASSERT(osfd >= 0 || in_flags == 0); if (in_flags & _PR_UNIX_POLL_READ) { if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu)); } if (in_flags & _PR_UNIX_POLL_WRITE) { if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu)); } if (in_flags & _PR_UNIX_POLL_EXCEPT) { if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); } } _PR_THREAD_LOCK(pq->thr); if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) { _PRCPU *cpu = pq->thr->cpu; _PR_SLEEPQ_LOCK(pq->thr->cpu); _PR_DEL_SLEEPQ(pq->thr, PR_TRUE); _PR_SLEEPQ_UNLOCK(pq->thr->cpu); if (pq->thr->flags & _PR_SUSPENDING) { /* * set thread state to SUSPENDED; * a Resume operation on the thread * will move it to the runQ */ pq->thr->state = _PR_SUSPENDED; _PR_MISCQ_LOCK(pq->thr->cpu); _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu); _PR_MISCQ_UNLOCK(pq->thr->cpu); } else { pri = pq->thr->priority; pq->thr->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(pq->thr, cpu, pri); _PR_RUNQ_UNLOCK(cpu); } } _PR_THREAD_UNLOCK(pq->thr); } else { if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout; if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd; } } if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; } } #endif /* !defined(_PR_USE_POLL) */ /************************************************************************/ /* ** Called by the scheduler when there is nothing to do. This means that ** all threads are blocked on some monitor somewhere. ** ** Note: this code doesn't release the scheduler lock. */ /* ** Pause the current CPU. longjmp to the cpu's pause stack ** ** This must be called with the scheduler locked */ void _MD_PauseCPU(PRIntervalTime ticks) { PRThread *me = _MD_CURRENT_THREAD(); #ifdef _PR_USE_POLL int timeout; struct pollfd *pollfds; /* an array of pollfd structures */ struct pollfd *pollfdPtr; /* a pointer that steps through the array */ unsigned long npollfds; /* number of pollfd structures in array */ unsigned long pollfds_size; int nfd; /* to hold the return value of poll() */ #else struct timeval timeout, *tvp; fd_set r, w, e; fd_set *rp, *wp, *ep; PRInt32 max_osfd, nfd; #endif /* _PR_USE_POLL */ PRInt32 rv; PRCList *q; PRUint32 min_timeout; sigset_t oldset; #ifdef IRIX extern sigset_t ints_off; #endif PR_ASSERT(_PR_MD_GET_INTSOFF() != 0); _PR_MD_IOQ_LOCK(); #ifdef _PR_USE_POLL /* Build up the pollfd structure array to wait on */ /* Find out how many pollfd structures are needed */ npollfds = _PR_IOQ_OSFD_CNT(me->cpu); PR_ASSERT(npollfds >= 0); /* * We use a pipe to wake up a native thread. An fd is needed * for the pipe and we poll it for reading. */ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { npollfds++; #ifdef IRIX /* * On Irix, a second pipe is used to cause the primordial cpu to * wakeup and exit, when the process is exiting because of a call * to exit/PR_ProcessExit. */ if (me->cpu->id == 0) { npollfds++; } #endif } /* * if the cpu's pollfd array is not big enough, release it and allocate a new one */ if (npollfds > _PR_IOQ_POLLFDS_SIZE(me->cpu)) { if (_PR_IOQ_POLLFDS(me->cpu) != NULL) PR_DELETE(_PR_IOQ_POLLFDS(me->cpu)); pollfds_size = PR_MAX(_PR_IOQ_MIN_POLLFDS_SIZE(me->cpu), npollfds); pollfds = (struct pollfd *) PR_MALLOC(pollfds_size * sizeof(struct pollfd)); _PR_IOQ_POLLFDS(me->cpu) = pollfds; _PR_IOQ_POLLFDS_SIZE(me->cpu) = pollfds_size; } else { pollfds = _PR_IOQ_POLLFDS(me->cpu); } pollfdPtr = pollfds; /* * If we need to poll the pipe for waking up a native thread, * the pipe's fd is the first element in the pollfds array. */ if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { pollfdPtr->fd = _pr_md_pipefd[0]; pollfdPtr->events = POLLIN; pollfdPtr++; #ifdef IRIX /* * On Irix, the second element is the exit pipe */ if (me->cpu->id == 0) { pollfdPtr->fd = _pr_irix_primoridal_cpu_fd[0]; pollfdPtr->events = POLLIN; pollfdPtr++; } #endif } min_timeout = PR_INTERVAL_NO_TIMEOUT; for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) { PRPollQueue *pq = _PR_POLLQUEUE_PTR(q); _PRUnixPollDesc *pds = pq->pds; _PRUnixPollDesc *epds = pds + pq->npds; if (pq->timeout < min_timeout) { min_timeout = pq->timeout; } for (; pds < epds; pds++, pollfdPtr++) { /* * Assert that the pollfdPtr pointer does not go * beyond the end of the pollfds array */ PR_ASSERT(pollfdPtr < pollfds + npollfds); pollfdPtr->fd = pds->osfd; /* direct copy of poll flags */ pollfdPtr->events = pds->in_flags; } } _PR_IOQ_TIMEOUT(me->cpu) = min_timeout; #else /* * assigment of fd_sets */ r = _PR_FD_READ_SET(me->cpu); w = _PR_FD_WRITE_SET(me->cpu); e = _PR_FD_EXCEPTION_SET(me->cpu); rp = &r; wp = &w; ep = &e; max_osfd = _PR_IOQ_MAX_OSFD(me->cpu) + 1; min_timeout = _PR_IOQ_TIMEOUT(me->cpu); #endif /* _PR_USE_POLL */ /* ** Compute the minimum timeout value: make it the smaller of the ** timeouts specified by the i/o pollers or the timeout of the first ** sleeping thread. */ q = _PR_SLEEPQ(me->cpu).next; if (q != &_PR_SLEEPQ(me->cpu)) { PRThread *t = _PR_THREAD_PTR(q); if (t->sleep < min_timeout) { min_timeout = t->sleep; } } if (min_timeout > ticks) { min_timeout = ticks; } #ifdef _PR_USE_POLL if (min_timeout == PR_INTERVAL_NO_TIMEOUT) timeout = -1; else timeout = PR_IntervalToMilliseconds(min_timeout); #else if (min_timeout == PR_INTERVAL_NO_TIMEOUT) { tvp = NULL; } else { timeout.tv_sec = PR_IntervalToSeconds(min_timeout); timeout.tv_usec = PR_IntervalToMicroseconds(min_timeout) % PR_USEC_PER_SEC; tvp = &timeout; } #endif /* _PR_USE_POLL */ _PR_MD_IOQ_UNLOCK(); _MD_CHECK_FOR_EXIT(); /* * check for i/o operations */ #ifndef _PR_NO_CLOCK_TIMER /* * Disable the clock interrupts while we are in select, if clock interrupts * are enabled. Otherwise, when the select/poll calls are interrupted, the * timer value starts ticking from zero again when the system call is restarted. */ #ifdef IRIX /* * SIGCHLD signal is used on Irix to detect he termination of an * sproc by SIGSEGV, SIGBUS or SIGABRT signals when * _nspr_terminate_on_error is set. */ if ((!_nspr_noclock) || (_nspr_terminate_on_error)) #else if (!_nspr_noclock) #endif /* IRIX */ #ifdef IRIX sigprocmask(SIG_BLOCK, &ints_off, &oldset); #else PR_ASSERT(sigismember(&timer_set, SIGALRM)); sigprocmask(SIG_BLOCK, &timer_set, &oldset); #endif /* IRIX */ #endif /* !_PR_NO_CLOCK_TIMER */ #ifndef _PR_USE_POLL PR_ASSERT(FD_ISSET(_pr_md_pipefd[0],rp)); nfd = _MD_SELECT(max_osfd, rp, wp, ep, tvp); #else nfd = _MD_POLL(pollfds, npollfds, timeout); #endif /* !_PR_USE_POLL */ #ifndef _PR_NO_CLOCK_TIMER #ifdef IRIX if ((!_nspr_noclock) || (_nspr_terminate_on_error)) #else if (!_nspr_noclock) #endif /* IRIX */ sigprocmask(SIG_SETMASK, &oldset, 0); #endif /* !_PR_NO_CLOCK_TIMER */ _MD_CHECK_FOR_EXIT(); #ifdef IRIX _PR_MD_primordial_cpu(); #endif _PR_MD_IOQ_LOCK(); /* ** Notify monitors that are associated with the selected descriptors. */ #ifdef _PR_USE_POLL if (nfd > 0) { pollfdPtr = pollfds; if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { /* * Assert that the pipe is the first element in the * pollfds array. */ PR_ASSERT(pollfds[0].fd == _pr_md_pipefd[0]); if ((pollfds[0].revents & POLLIN) && (nfd == 1)) { /* * woken up by another thread; read all the data * in the pipe to empty the pipe */ while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF){ } PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); } pollfdPtr++; #ifdef IRIX /* * On Irix, check to see if the primordial cpu needs to exit * to cause the process to terminate */ if (me->cpu->id == 0) { PR_ASSERT(pollfds[1].fd == _pr_irix_primoridal_cpu_fd[0]); if (pollfdPtr->revents & POLLIN) { if (_pr_irix_process_exit) { /* * process exit due to a call to PR_ProcessExit */ prctl(PR_SETEXITSIG, SIGKILL); _exit(_pr_irix_process_exit_code); } else { while ((rv = read(_pr_irix_primoridal_cpu_fd[0], _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) { } PR_ASSERT(rv > 0); } } pollfdPtr++; } #endif } for (q = _PR_IOQ(me->cpu).next; q != &_PR_IOQ(me->cpu); q = q->next) { PRPollQueue *pq = _PR_POLLQUEUE_PTR(q); PRBool notify = PR_FALSE; _PRUnixPollDesc *pds = pq->pds; _PRUnixPollDesc *epds = pds + pq->npds; for (; pds < epds; pds++, pollfdPtr++) { /* * Assert that the pollfdPtr pointer does not go beyond * the end of the pollfds array. */ PR_ASSERT(pollfdPtr < pollfds + npollfds); /* * Assert that the fd's in the pollfds array (stepped * through by pollfdPtr) are in the same order as * the fd's in _PR_IOQ() (stepped through by q and pds). * This is how the pollfds array was created earlier. */ PR_ASSERT(pollfdPtr->fd == pds->osfd); pds->out_flags = pollfdPtr->revents; /* Negative fd's are ignored by poll() */ if (pds->osfd >= 0 && pds->out_flags) { notify = PR_TRUE; } } if (notify) { PRIntn pri; PRThread *thred; PR_REMOVE_LINK(&pq->links); pq->on_ioq = PR_FALSE; thred = pq->thr; _PR_THREAD_LOCK(thred); if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) { _PRCPU *cpu = pq->thr->cpu; _PR_SLEEPQ_LOCK(pq->thr->cpu); _PR_DEL_SLEEPQ(pq->thr, PR_TRUE); _PR_SLEEPQ_UNLOCK(pq->thr->cpu); if (pq->thr->flags & _PR_SUSPENDING) { /* * set thread state to SUSPENDED; * a Resume operation on the thread * will move it to the runQ */ pq->thr->state = _PR_SUSPENDED; _PR_MISCQ_LOCK(pq->thr->cpu); _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu); _PR_MISCQ_UNLOCK(pq->thr->cpu); } else { pri = pq->thr->priority; pq->thr->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(pq->thr, cpu, pri); _PR_RUNQ_UNLOCK(cpu); if (_pr_md_idle_cpus > 1) _PR_MD_WAKEUP_WAITER(thred); } } _PR_THREAD_UNLOCK(thred); _PR_IOQ_OSFD_CNT(me->cpu) -= pq->npds; PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0); } } } else if (nfd == -1) { PR_LOG(_pr_io_lm, PR_LOG_MAX, ("poll() failed with errno %d", errno)); } #else if (nfd > 0) { q = _PR_IOQ(me->cpu).next; _PR_IOQ_MAX_OSFD(me->cpu) = -1; _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT; while (q != &_PR_IOQ(me->cpu)) { PRPollQueue *pq = _PR_POLLQUEUE_PTR(q); PRBool notify = PR_FALSE; _PRUnixPollDesc *pds = pq->pds; _PRUnixPollDesc *epds = pds + pq->npds; PRInt32 pq_max_osfd = -1; q = q->next; for (; pds < epds; pds++) { PRInt32 osfd = pds->osfd; PRInt16 in_flags = pds->in_flags; PRInt16 out_flags = 0; PR_ASSERT(osfd >= 0 || in_flags == 0); if ((in_flags & _PR_UNIX_POLL_READ) && FD_ISSET(osfd, rp)) { out_flags |= _PR_UNIX_POLL_READ; } if ((in_flags & _PR_UNIX_POLL_WRITE) && FD_ISSET(osfd, wp)) { out_flags |= _PR_UNIX_POLL_WRITE; } if ((in_flags & _PR_UNIX_POLL_EXCEPT) && FD_ISSET(osfd, ep)) { out_flags |= _PR_UNIX_POLL_EXCEPT; } pds->out_flags = out_flags; if (out_flags) { notify = PR_TRUE; } if (osfd > pq_max_osfd) { pq_max_osfd = osfd; } } if (notify == PR_TRUE) { PRIntn pri; PRThread *thred; PR_REMOVE_LINK(&pq->links); pq->on_ioq = PR_FALSE; /* * Decrement the count of descriptors for each desciptor/event * because this I/O request is being removed from the * ioq */ pds = pq->pds; for (; pds < epds; pds++) { PRInt32 osfd = pds->osfd; PRInt16 in_flags = pds->in_flags; PR_ASSERT(osfd >= 0 || in_flags == 0); if (in_flags & _PR_UNIX_POLL_READ) { if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu)); } if (in_flags & _PR_UNIX_POLL_WRITE) { if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu)); } if (in_flags & _PR_UNIX_POLL_EXCEPT) { if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); } } /* * Because this thread can run on a different cpu right * after being added to the run queue, do not dereference * pq */ thred = pq->thr; _PR_THREAD_LOCK(thred); if (pq->thr->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) { _PRCPU *cpu = thred->cpu; _PR_SLEEPQ_LOCK(pq->thr->cpu); _PR_DEL_SLEEPQ(pq->thr, PR_TRUE); _PR_SLEEPQ_UNLOCK(pq->thr->cpu); if (pq->thr->flags & _PR_SUSPENDING) { /* * set thread state to SUSPENDED; * a Resume operation on the thread * will move it to the runQ */ pq->thr->state = _PR_SUSPENDED; _PR_MISCQ_LOCK(pq->thr->cpu); _PR_ADD_SUSPENDQ(pq->thr, pq->thr->cpu); _PR_MISCQ_UNLOCK(pq->thr->cpu); } else { pri = pq->thr->priority; pq->thr->state = _PR_RUNNABLE; pq->thr->cpu = cpu; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(pq->thr, cpu, pri); _PR_RUNQ_UNLOCK(cpu); if (_pr_md_idle_cpus > 1) _PR_MD_WAKEUP_WAITER(thred); } } _PR_THREAD_UNLOCK(thred); } else { if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout; if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd; } } if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { if ((FD_ISSET(_pr_md_pipefd[0], rp)) && (nfd == 1)) { /* * woken up by another thread; read all the data * in the pipe to empty the pipe */ while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF){ } PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); } if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; #ifdef IRIX if ((me->cpu->id == 0) && (FD_ISSET(_pr_irix_primoridal_cpu_fd[0], rp))) { if (_pr_irix_process_exit) { /* * process exit due to a call to PR_ProcessExit */ prctl(PR_SETEXITSIG, SIGKILL); _exit(_pr_irix_process_exit_code); } else { while ((rv = read(_pr_irix_primoridal_cpu_fd[0], _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) { } PR_ASSERT(rv > 0); } } if (me->cpu->id == 0) { if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_irix_primoridal_cpu_fd[0]) _PR_IOQ_MAX_OSFD(me->cpu) = _pr_irix_primoridal_cpu_fd[0]; } #endif } } else if (nfd < 0) { if (errno == EBADF) { FindBadFDs(); } else { PR_LOG(_pr_io_lm, PR_LOG_MAX, ("select() failed with errno %d", errno)); } } else { PR_ASSERT(nfd == 0); /* * compute the new value of _PR_IOQ_TIMEOUT */ q = _PR_IOQ(me->cpu).next; _PR_IOQ_MAX_OSFD(me->cpu) = -1; _PR_IOQ_TIMEOUT(me->cpu) = PR_INTERVAL_NO_TIMEOUT; while (q != &_PR_IOQ(me->cpu)) { PRPollQueue *pq = _PR_POLLQUEUE_PTR(q); _PRUnixPollDesc *pds = pq->pds; _PRUnixPollDesc *epds = pds + pq->npds; PRInt32 pq_max_osfd = -1; q = q->next; for (; pds < epds; pds++) { if (pds->osfd > pq_max_osfd) { pq_max_osfd = pds->osfd; } } if (pq->timeout < _PR_IOQ_TIMEOUT(me->cpu)) _PR_IOQ_TIMEOUT(me->cpu) = pq->timeout; if (_PR_IOQ_MAX_OSFD(me->cpu) < pq_max_osfd) _PR_IOQ_MAX_OSFD(me->cpu) = pq_max_osfd; } if (_PR_IS_NATIVE_THREAD_SUPPORTED()) { if (_PR_IOQ_MAX_OSFD(me->cpu) < _pr_md_pipefd[0]) _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; } } #endif /* _PR_USE_POLL */ _PR_MD_IOQ_UNLOCK(); } void _MD_Wakeup_CPUs() { PRInt32 rv, data; data = 0; rv = write(_pr_md_pipefd[1], &data, 1); while ((rv < 0) && (errno == EAGAIN)) { /* * pipe full, read all data in pipe to empty it */ while ((rv = read(_pr_md_pipefd[0], _pr_md_pipebuf, PIPE_BUF)) == PIPE_BUF) { } PR_ASSERT((rv > 0) || ((rv == -1) && (errno == EAGAIN))); rv = write(_pr_md_pipefd[1], &data, 1); } } void _MD_InitCPUS() { PRInt32 rv, flags; PRThread *me = _MD_CURRENT_THREAD(); rv = pipe(_pr_md_pipefd); PR_ASSERT(rv == 0); _PR_IOQ_MAX_OSFD(me->cpu) = _pr_md_pipefd[0]; #ifndef _PR_USE_POLL FD_SET(_pr_md_pipefd[0], &_PR_FD_READ_SET(me->cpu)); #endif flags = fcntl(_pr_md_pipefd[0], F_GETFL, 0); fcntl(_pr_md_pipefd[0], F_SETFL, flags | O_NONBLOCK); flags = fcntl(_pr_md_pipefd[1], F_GETFL, 0); fcntl(_pr_md_pipefd[1], F_SETFL, flags | O_NONBLOCK); } /* ** Unix SIGALRM (clock) signal handler */ static void ClockInterruptHandler() { int olderrno; PRUintn pri; _PRCPU *cpu = _PR_MD_CURRENT_CPU(); PRThread *me = _MD_CURRENT_THREAD(); #ifdef SOLARIS if (!me || _PR_IS_NATIVE_THREAD(me)) { _pr_primordialCPU->u.missed[_pr_primordialCPU->where] |= _PR_MISSED_CLOCK; return; } #endif if (_PR_MD_GET_INTSOFF() != 0) { cpu->u.missed[cpu->where] |= _PR_MISSED_CLOCK; return; } _PR_MD_SET_INTSOFF(1); olderrno = errno; _PR_ClockInterrupt(); errno = olderrno; /* ** If the interrupt wants a resched or if some other thread at ** the same priority needs the cpu, reschedule. */ pri = me->priority; if ((cpu->u.missed[3] || (_PR_RUNQREADYMASK(me->cpu) >> pri))) { #ifdef _PR_NO_PREEMPT cpu->resched = PR_TRUE; if (pr_interruptSwitchHook) { (*pr_interruptSwitchHook)(pr_interruptSwitchHookArg); } #else /* _PR_NO_PREEMPT */ /* ** Re-enable unix interrupts (so that we can use ** setjmp/longjmp for context switching without having to ** worry about the signal state) */ sigprocmask(SIG_SETMASK, &empty_set, 0); PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock caused context switch")); if(!(me->flags & _PR_IDLE_THREAD)) { _PR_THREAD_LOCK(me); me->state = _PR_RUNNABLE; me->cpu = cpu; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(me, cpu, pri); _PR_RUNQ_UNLOCK(cpu); _PR_THREAD_UNLOCK(me); } else me->state = _PR_RUNNABLE; _MD_SWITCH_CONTEXT(me); PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("clock back from context switch")); #endif /* _PR_NO_PREEMPT */ } /* * Because this thread could be running on a different cpu after * a context switch the current cpu should be accessed and the * value of the 'cpu' variable should not be used. */ _PR_MD_SET_INTSOFF(0); } /* * On HP-UX 9, we have to use the sigvector() interface to restart * interrupted system calls, because sigaction() does not have the * SA_RESTART flag. */ #ifdef HPUX9 static void HPUX9_ClockInterruptHandler( int sig, int code, struct sigcontext *scp) { ClockInterruptHandler(); scp->sc_syscall_action = SIG_RESTART; } #endif /* HPUX9 */ /* # of milliseconds per clock tick that we will use */ #define MSEC_PER_TICK 50 void _MD_StartInterrupts() { char *eval; if ((eval = getenv("NSPR_NOCLOCK")) != NULL) { if (atoi(eval) == 0) _nspr_noclock = 0; else _nspr_noclock = 1; } #ifndef _PR_NO_CLOCK_TIMER if (!_nspr_noclock) { _MD_EnableClockInterrupts(); } #endif } void _MD_StopInterrupts() { sigprocmask(SIG_BLOCK, &timer_set, 0); } void _MD_EnableClockInterrupts() { struct itimerval itval; extern PRUintn _pr_numCPU; #ifdef HPUX9 struct sigvec vec; vec.sv_handler = (void (*)()) HPUX9_ClockInterruptHandler; vec.sv_mask = 0; vec.sv_flags = 0; sigvector(SIGALRM, &vec, 0); #else struct sigaction vtact; vtact.sa_handler = (void (*)()) ClockInterruptHandler; sigemptyset(&vtact.sa_mask); vtact.sa_flags = SA_RESTART; sigaction(SIGALRM, &vtact, 0); #endif /* HPUX9 */ PR_ASSERT(_pr_numCPU == 1); itval.it_interval.tv_sec = 0; itval.it_interval.tv_usec = MSEC_PER_TICK * PR_USEC_PER_MSEC; itval.it_value = itval.it_interval; setitimer(ITIMER_REAL, &itval, 0); } void _MD_DisableClockInterrupts() { struct itimerval itval; extern PRUintn _pr_numCPU; PR_ASSERT(_pr_numCPU == 1); itval.it_interval.tv_sec = 0; itval.it_interval.tv_usec = 0; itval.it_value = itval.it_interval; setitimer(ITIMER_REAL, &itval, 0); } void _MD_BlockClockInterrupts() { sigprocmask(SIG_BLOCK, &timer_set, 0); } void _MD_UnblockClockInterrupts() { sigprocmask(SIG_UNBLOCK, &timer_set, 0); } void _MD_MakeNonblock(PRFileDesc *fd) { PRInt32 osfd = fd->secret->md.osfd; int flags; if (osfd <= 2) { /* Don't mess around with stdin, stdout or stderr */ return; } flags = fcntl(osfd, F_GETFL, 0); /* * Use O_NONBLOCK (POSIX-style non-blocking I/O) whenever possible. * On SunOS 4, we must use FNDELAY (BSD-style non-blocking I/O), * otherwise connect() still blocks and can be interrupted by SIGALRM. */ fcntl(osfd, F_SETFL, flags | O_NONBLOCK); } PRInt32 _MD_open(const char *name, PRIntn flags, PRIntn mode) { PRInt32 osflags; PRInt32 rv, err; if (flags & PR_RDWR) { osflags = O_RDWR; } else if (flags & PR_WRONLY) { osflags = O_WRONLY; } else { osflags = O_RDONLY; } if (flags & PR_EXCL) osflags |= O_EXCL; if (flags & PR_APPEND) osflags |= O_APPEND; if (flags & PR_TRUNCATE) osflags |= O_TRUNC; if (flags & PR_SYNC) { #if defined(O_SYNC) osflags |= O_SYNC; #elif defined(O_FSYNC) osflags |= O_FSYNC; #else #error "Neither O_SYNC nor O_FSYNC is defined on this platform" #endif } /* ** On creations we hold the 'create' lock in order to enforce ** the semantics of PR_Rename. (see the latter for more details) */ if (flags & PR_CREATE_FILE) { osflags |= O_CREAT; if (NULL !=_pr_rename_lock) PR_Lock(_pr_rename_lock); } #if defined(ANDROID) osflags |= O_LARGEFILE; #endif rv = _md_iovector._open64(name, osflags, mode); if (rv < 0) { err = _MD_ERRNO(); _PR_MD_MAP_OPEN_ERROR(err); } if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock)) PR_Unlock(_pr_rename_lock); return rv; } PRIntervalTime intr_timeout_ticks; #if defined(SOLARIS) || defined(IRIX) static void sigsegvhandler() { fprintf(stderr,"Received SIGSEGV\n"); fflush(stderr); pause(); } static void sigaborthandler() { fprintf(stderr,"Received SIGABRT\n"); fflush(stderr); pause(); } static void sigbushandler() { fprintf(stderr,"Received SIGBUS\n"); fflush(stderr); pause(); } #endif /* SOLARIS, IRIX */ #endif /* !defined(_PR_PTHREADS) */ void _MD_query_fd_inheritable(PRFileDesc *fd) { int flags; PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); flags = fcntl(fd->secret->md.osfd, F_GETFD, 0); PR_ASSERT(-1 != flags); fd->secret->inheritable = (flags & FD_CLOEXEC) ? _PR_TRI_FALSE : _PR_TRI_TRUE; } PROffset32 _MD_lseek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence) { PROffset32 rv, where; switch (whence) { case PR_SEEK_SET: where = SEEK_SET; break; case PR_SEEK_CUR: where = SEEK_CUR; break; case PR_SEEK_END: where = SEEK_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = -1; goto done; } rv = lseek(fd->secret->md.osfd,offset,where); if (rv == -1) { PRInt32 syserr = _MD_ERRNO(); _PR_MD_MAP_LSEEK_ERROR(syserr); } done: return(rv); } PROffset64 _MD_lseek64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence) { PRInt32 where; PROffset64 rv; switch (whence) { case PR_SEEK_SET: where = SEEK_SET; break; case PR_SEEK_CUR: where = SEEK_CUR; break; case PR_SEEK_END: where = SEEK_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = minus_one; goto done; } rv = _md_iovector._lseek64(fd->secret->md.osfd, offset, where); if (LL_EQ(rv, minus_one)) { PRInt32 syserr = _MD_ERRNO(); _PR_MD_MAP_LSEEK_ERROR(syserr); } done: return rv; } /* _MD_lseek64 */ /* ** _MD_set_fileinfo_times -- ** Set the modifyTime and creationTime of the PRFileInfo ** structure using the values in struct stat. ** ** _MD_set_fileinfo64_times -- ** Set the modifyTime and creationTime of the PRFileInfo64 ** structure using the values in _MDStat64. */ #if defined(_PR_STAT_HAS_ST_ATIM) /* ** struct stat has st_atim, st_mtim, and st_ctim fields of ** type timestruc_t. */ static void _MD_set_fileinfo_times( const struct stat *sb, PRFileInfo *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtim.tv_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtim.tv_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctim.tv_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctim.tv_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } static void _MD_set_fileinfo64_times( const _MDStat64 *sb, PRFileInfo64 *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtim.tv_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtim.tv_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctim.tv_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctim.tv_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } #elif defined(_PR_STAT_HAS_ST_ATIM_UNION) /* ** The st_atim, st_mtim, and st_ctim fields in struct stat are ** unions with a st__tim union member of type timestruc_t. */ static void _MD_set_fileinfo_times( const struct stat *sb, PRFileInfo *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } static void _MD_set_fileinfo64_times( const _MDStat64 *sb, PRFileInfo64 *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtim.st__tim.tv_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtim.st__tim.tv_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctim.st__tim.tv_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctim.st__tim.tv_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } #elif defined(_PR_STAT_HAS_ST_ATIMESPEC) /* ** struct stat has st_atimespec, st_mtimespec, and st_ctimespec ** fields of type struct timespec. */ #if defined(_PR_TIMESPEC_HAS_TS_SEC) static void _MD_set_fileinfo_times( const struct stat *sb, PRFileInfo *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } static void _MD_set_fileinfo64_times( const _MDStat64 *sb, PRFileInfo64 *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtimespec.ts_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtimespec.ts_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctimespec.ts_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctimespec.ts_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } #else /* _PR_TIMESPEC_HAS_TS_SEC */ /* ** The POSIX timespec structure has tv_sec and tv_nsec. */ static void _MD_set_fileinfo_times( const struct stat *sb, PRFileInfo *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } static void _MD_set_fileinfo64_times( const _MDStat64 *sb, PRFileInfo64 *info) { PRInt64 us, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(info->modifyTime, sb->st_mtimespec.tv_sec); LL_MUL(info->modifyTime, info->modifyTime, s2us); LL_I2L(us, sb->st_mtimespec.tv_nsec / 1000); LL_ADD(info->modifyTime, info->modifyTime, us); LL_I2L(info->creationTime, sb->st_ctimespec.tv_sec); LL_MUL(info->creationTime, info->creationTime, s2us); LL_I2L(us, sb->st_ctimespec.tv_nsec / 1000); LL_ADD(info->creationTime, info->creationTime, us); } #endif /* _PR_TIMESPEC_HAS_TS_SEC */ #elif defined(_PR_STAT_HAS_ONLY_ST_ATIME) /* ** struct stat only has st_atime, st_mtime, and st_ctime fields ** of type time_t. */ static void _MD_set_fileinfo_times( const struct stat *sb, PRFileInfo *info) { PRInt64 s, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, sb->st_mtime); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb->st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } static void _MD_set_fileinfo64_times( const _MDStat64 *sb, PRFileInfo64 *info) { PRInt64 s, s2us; LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, sb->st_mtime); LL_MUL(s, s, s2us); info->modifyTime = s; LL_I2L(s, sb->st_ctime); LL_MUL(s, s, s2us); info->creationTime = s; } #else #error "I don't know yet" #endif static int _MD_convert_stat_to_fileinfo( const struct stat *sb, PRFileInfo *info) { if (S_IFREG & sb->st_mode) info->type = PR_FILE_FILE; else if (S_IFDIR & sb->st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; #if defined(_PR_HAVE_LARGE_OFF_T) if (0x7fffffffL < sb->st_size) { PR_SetError(PR_FILE_TOO_BIG_ERROR, 0); return -1; } #endif /* defined(_PR_HAVE_LARGE_OFF_T) */ info->size = sb->st_size; _MD_set_fileinfo_times(sb, info); return 0; } /* _MD_convert_stat_to_fileinfo */ static int _MD_convert_stat64_to_fileinfo64( const _MDStat64 *sb, PRFileInfo64 *info) { if (S_IFREG & sb->st_mode) info->type = PR_FILE_FILE; else if (S_IFDIR & sb->st_mode) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_OTHER; LL_I2L(info->size, sb->st_size); _MD_set_fileinfo64_times(sb, info); return 0; } /* _MD_convert_stat64_to_fileinfo64 */ PRInt32 _MD_getfileinfo(const char *fn, PRFileInfo *info) { PRInt32 rv; struct stat sb; rv = stat(fn, &sb); if (rv < 0) _PR_MD_MAP_STAT_ERROR(_MD_ERRNO()); else if (NULL != info) rv = _MD_convert_stat_to_fileinfo(&sb, info); return rv; } PRInt32 _MD_getfileinfo64(const char *fn, PRFileInfo64 *info) { _MDStat64 sb; PRInt32 rv = _md_iovector._stat64(fn, &sb); if (rv < 0) _PR_MD_MAP_STAT_ERROR(_MD_ERRNO()); else if (NULL != info) rv = _MD_convert_stat64_to_fileinfo64(&sb, info); return rv; } PRInt32 _MD_getopenfileinfo(const PRFileDesc *fd, PRFileInfo *info) { struct stat sb; PRInt32 rv = fstat(fd->secret->md.osfd, &sb); if (rv < 0) _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO()); else if (NULL != info) rv = _MD_convert_stat_to_fileinfo(&sb, info); return rv; } PRInt32 _MD_getopenfileinfo64(const PRFileDesc *fd, PRFileInfo64 *info) { _MDStat64 sb; PRInt32 rv = _md_iovector._fstat64(fd->secret->md.osfd, &sb); if (rv < 0) _PR_MD_MAP_FSTAT_ERROR(_MD_ERRNO()); else if (NULL != info) rv = _MD_convert_stat64_to_fileinfo64(&sb, info); return rv; } /* * _md_iovector._open64 must be initialized to 'open' so that _PR_InitLog can * open the log file during NSPR initialization, before _md_iovector is * initialized by _PR_MD_FINAL_INIT. This means the log file cannot be a * large file on some platforms. */ #ifdef SYMBIAN struct _MD_IOVector _md_iovector; /* Will crash if NSPR_LOG_FILE is set. */ #else struct _MD_IOVector _md_iovector = { open }; #endif /* ** These implementations are to emulate large file routines on systems that ** don't have them. Their goal is to check in case overflow occurs. Otherwise ** they will just operate as normal using 32-bit file routines. ** ** The checking might be pre- or post-op, depending on the semantics. */ #if defined(SOLARIS2_5) static PRIntn _MD_solaris25_fstat64(PRIntn osfd, _MDStat64 *buf) { PRInt32 rv; struct stat sb; rv = fstat(osfd, &sb); if (rv >= 0) { /* ** I'm only copying the fields that are immediately needed. ** If somebody else calls this function, some of the fields ** may not be defined. */ (void)memset(buf, 0, sizeof(_MDStat64)); buf->st_mode = sb.st_mode; buf->st_ctim = sb.st_ctim; buf->st_mtim = sb.st_mtim; buf->st_size = sb.st_size; } return rv; } /* _MD_solaris25_fstat64 */ static PRIntn _MD_solaris25_stat64(const char *fn, _MDStat64 *buf) { PRInt32 rv; struct stat sb; rv = stat(fn, &sb); if (rv >= 0) { /* ** I'm only copying the fields that are immediately needed. ** If somebody else calls this function, some of the fields ** may not be defined. */ (void)memset(buf, 0, sizeof(_MDStat64)); buf->st_mode = sb.st_mode; buf->st_ctim = sb.st_ctim; buf->st_mtim = sb.st_mtim; buf->st_size = sb.st_size; } return rv; } /* _MD_solaris25_stat64 */ #endif /* defined(SOLARIS2_5) */ #if defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) static PROffset64 _MD_Unix_lseek64(PRIntn osfd, PROffset64 offset, PRIntn whence) { PRUint64 maxoff; PROffset64 rv = minus_one; LL_I2L(maxoff, 0x7fffffff); if (LL_CMP(offset, <=, maxoff)) { off_t off; LL_L2I(off, offset); LL_I2L(rv, lseek(osfd, off, whence)); } else errno = EFBIG; /* we can't go there */ return rv; } /* _MD_Unix_lseek64 */ static void* _MD_Unix_mmap64( void *addr, PRSize len, PRIntn prot, PRIntn flags, PRIntn fildes, PRInt64 offset) { PR_SetError(PR_FILE_TOO_BIG_ERROR, 0); return NULL; } /* _MD_Unix_mmap64 */ #endif /* defined(_PR_NO_LARGE_FILES) || defined(SOLARIS2_5) */ /* Android <= 19 doesn't have mmap64. */ #if defined(ANDROID) && __ANDROID_API__ <= 19 extern void *__mmap2(void *, size_t, int, int, int, size_t); #define ANDROID_PAGE_SIZE 4096 static void * mmap64(void *addr, size_t len, int prot, int flags, int fd, loff_t offset) { if (offset & (ANDROID_PAGE_SIZE - 1)) { errno = EINVAL; return MAP_FAILED; } return __mmap2(addr, len, prot, flags, fd, offset / ANDROID_PAGE_SIZE); } #endif #if defined(OSF1) && defined(__GNUC__) /* * On OSF1 V5.0A, defines stat and fstat as * macros when compiled under gcc, so it is rather tricky to * take the addresses of the real functions the macros expend * to. A simple solution is to define forwarder functions * and take the addresses of the forwarder functions instead. */ static int stat_forwarder(const char *path, struct stat *buffer) { return stat(path, buffer); } static int fstat_forwarder(int filedes, struct stat *buffer) { return fstat(filedes, buffer); } #endif static void _PR_InitIOV(void) { #if defined(SOLARIS2_5) PRLibrary *lib; void *open64_func; open64_func = PR_FindSymbolAndLibrary("open64", &lib); if (NULL != open64_func) { PR_ASSERT(NULL != lib); _md_iovector._open64 = (_MD_Open64)open64_func; _md_iovector._mmap64 = (_MD_Mmap64)PR_FindSymbol(lib, "mmap64"); _md_iovector._fstat64 = (_MD_Fstat64)PR_FindSymbol(lib, "fstat64"); _md_iovector._stat64 = (_MD_Stat64)PR_FindSymbol(lib, "stat64"); _md_iovector._lseek64 = (_MD_Lseek64)PR_FindSymbol(lib, "lseek64"); (void)PR_UnloadLibrary(lib); } else { _md_iovector._open64 = open; _md_iovector._mmap64 = _MD_Unix_mmap64; _md_iovector._fstat64 = _MD_solaris25_fstat64; _md_iovector._stat64 = _MD_solaris25_stat64; _md_iovector._lseek64 = _MD_Unix_lseek64; } #elif defined(_PR_NO_LARGE_FILES) _md_iovector._open64 = open; _md_iovector._mmap64 = _MD_Unix_mmap64; _md_iovector._fstat64 = fstat; _md_iovector._stat64 = stat; _md_iovector._lseek64 = _MD_Unix_lseek64; #elif defined(_PR_HAVE_OFF64_T) #if defined(IRIX5_3) || defined(ANDROID) /* * Android doesn't have open64. We pass the O_LARGEFILE flag to open * in _MD_open. */ _md_iovector._open64 = open; #else _md_iovector._open64 = open64; #endif _md_iovector._mmap64 = mmap64; _md_iovector._fstat64 = fstat64; _md_iovector._stat64 = stat64; _md_iovector._lseek64 = lseek64; #elif defined(_PR_HAVE_LARGE_OFF_T) _md_iovector._open64 = open; _md_iovector._mmap64 = mmap; #if defined(OSF1) && defined(__GNUC__) _md_iovector._fstat64 = fstat_forwarder; _md_iovector._stat64 = stat_forwarder; #else _md_iovector._fstat64 = fstat; _md_iovector._stat64 = stat; #endif _md_iovector._lseek64 = lseek; #else #error "I don't know yet" #endif LL_I2L(minus_one, -1); } /* _PR_InitIOV */ void _PR_UnixInit(void) { struct sigaction sigact; int rv; sigemptyset(&timer_set); #if !defined(_PR_PTHREADS) sigaddset(&timer_set, SIGALRM); sigemptyset(&empty_set); intr_timeout_ticks = PR_SecondsToInterval(_PR_INTERRUPT_CHECK_INTERVAL_SECS); #if defined(SOLARIS) || defined(IRIX) if (getenv("NSPR_SIGSEGV_HANDLE")) { sigact.sa_handler = sigsegvhandler; sigact.sa_flags = 0; sigact.sa_mask = timer_set; sigaction(SIGSEGV, &sigact, 0); } if (getenv("NSPR_SIGABRT_HANDLE")) { sigact.sa_handler = sigaborthandler; sigact.sa_flags = 0; sigact.sa_mask = timer_set; sigaction(SIGABRT, &sigact, 0); } if (getenv("NSPR_SIGBUS_HANDLE")) { sigact.sa_handler = sigbushandler; sigact.sa_flags = 0; sigact.sa_mask = timer_set; sigaction(SIGBUS, &sigact, 0); } #endif #endif /* !defined(_PR_PTHREADS) */ /* * Under HP-UX DCE threads, sigaction() installs a per-thread * handler, so we use sigvector() to install a process-wide * handler. */ #if defined(HPUX) && defined(_PR_DCETHREADS) { struct sigvec vec; vec.sv_handler = SIG_IGN; vec.sv_mask = 0; vec.sv_flags = 0; rv = sigvector(SIGPIPE, &vec, NULL); PR_ASSERT(0 == rv); } #else sigact.sa_handler = SIG_IGN; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; rv = sigaction(SIGPIPE, &sigact, 0); PR_ASSERT(0 == rv); #endif /* HPUX && _PR_DCETHREADS */ _pr_rename_lock = PR_NewLock(); PR_ASSERT(NULL != _pr_rename_lock); _pr_Xfe_mon = PR_NewMonitor(); PR_ASSERT(NULL != _pr_Xfe_mon); _PR_InitIOV(); /* one last hack */ } void _PR_UnixCleanup(void) { if (_pr_rename_lock) { PR_DestroyLock(_pr_rename_lock); _pr_rename_lock = NULL; } if (_pr_Xfe_mon) { PR_DestroyMonitor(_pr_Xfe_mon); _pr_Xfe_mon = NULL; } } #if !defined(_PR_PTHREADS) /* * Variables used by the GC code, initialized in _MD_InitSegs(). */ static PRInt32 _pr_zero_fd = -1; static PRLock *_pr_md_lock = NULL; /* * _MD_InitSegs -- * * This is Unix's version of _PR_MD_INIT_SEGS(), which is * called by _PR_InitSegs(), which in turn is called by * PR_Init(). */ void _MD_InitSegs(void) { #ifdef DEBUG /* ** Disable using mmap(2) if NSPR_NO_MMAP is set */ if (getenv("NSPR_NO_MMAP")) { _pr_zero_fd = -2; return; } #endif _pr_zero_fd = open("/dev/zero",O_RDWR , 0); /* Prevent the fd from being inherited by child processes */ fcntl(_pr_zero_fd, F_SETFD, FD_CLOEXEC); _pr_md_lock = PR_NewLock(); } PRStatus _MD_AllocSegment(PRSegment *seg, PRUint32 size, void *vaddr) { static char *lastaddr = (char*) _PR_STACK_VMBASE; PRStatus retval = PR_SUCCESS; int prot; void *rv; PR_ASSERT(seg != 0); PR_ASSERT(size != 0); PR_Lock(_pr_md_lock); if (_pr_zero_fd < 0) { from_heap: seg->vaddr = PR_MALLOC(size); if (!seg->vaddr) { retval = PR_FAILURE; } else { seg->size = size; } goto exit; } prot = PROT_READ|PROT_WRITE; /* * On Alpha Linux, the user-level thread stack needs * to be made executable because longjmp/signal seem * to put machine instructions on the stack. */ #if defined(LINUX) && defined(__alpha) prot |= PROT_EXEC; #endif rv = mmap((vaddr != 0) ? vaddr : lastaddr, size, prot, _MD_MMAP_FLAGS, _pr_zero_fd, 0); if (rv == (void*)-1) { goto from_heap; } lastaddr += size; seg->vaddr = rv; seg->size = size; seg->flags = _PR_SEG_VM; exit: PR_Unlock(_pr_md_lock); return retval; } void _MD_FreeSegment(PRSegment *seg) { if (seg->flags & _PR_SEG_VM) (void) munmap(seg->vaddr, seg->size); else PR_DELETE(seg->vaddr); } #endif /* _PR_PTHREADS */ /* *----------------------------------------------------------------------- * * PR_Now -- * * Returns the current time in microseconds since the epoch. * The epoch is midnight January 1, 1970 GMT. * The implementation is machine dependent. This is the Unix * implementation. * Cf. time_t time(time_t *tp) * *----------------------------------------------------------------------- */ PR_IMPLEMENT(PRTime) PR_Now(void) { struct timeval tv; PRInt64 s, us, s2us; GETTIMEOFDAY(&tv); LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, tv.tv_sec); LL_I2L(us, tv.tv_usec); LL_MUL(s, s, s2us); LL_ADD(s, s, us); return s; } #if defined(_MD_INTERVAL_USE_GTOD) /* * This version of interval times is based on the time of day * capability offered by the system. This isn't valid for two reasons: * 1) The time of day is neither linear nor montonically increasing * 2) The units here are milliseconds. That's not appropriate for our use. */ PRIntervalTime _PR_UNIX_GetInterval() { struct timeval time; PRIntervalTime ticks; (void)GETTIMEOFDAY(&time); /* fallicy of course */ ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */ ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */ return ticks; } /* _PR_UNIX_GetInterval */ PRIntervalTime _PR_UNIX_TicksPerSecond() { return 1000; /* this needs some work :) */ } #endif #if defined(HAVE_CLOCK_MONOTONIC) PRIntervalTime _PR_UNIX_GetInterval2() { struct timespec time; PRIntervalTime ticks; if (clock_gettime(CLOCK_MONOTONIC, &time) != 0) { fprintf(stderr, "clock_gettime failed: %d\n", errno); abort(); } ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; ticks += (PRUint32)time.tv_nsec / PR_NSEC_PER_MSEC; return ticks; } PRIntervalTime _PR_UNIX_TicksPerSecond2() { return 1000; } #endif #if !defined(_PR_PTHREADS) /* * Wait for I/O on multiple descriptors. * * Return 0 if timed out, return -1 if interrupted, * else return the number of ready descriptors. */ PRInt32 _PR_WaitForMultipleFDs( _PRUnixPollDesc *unixpds, PRInt32 pdcnt, PRIntervalTime timeout) { PRPollQueue pq; PRIntn is; PRInt32 rv; _PRCPU *io_cpu; _PRUnixPollDesc *unixpd, *eunixpd; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } pq.pds = unixpds; pq.npds = pdcnt; _PR_INTSOFF(is); _PR_MD_IOQ_LOCK(); _PR_THREAD_LOCK(me); pq.thr = me; io_cpu = me->cpu; pq.on_ioq = PR_TRUE; pq.timeout = timeout; _PR_ADD_TO_IOQ(pq, me->cpu); #if !defined(_PR_USE_POLL) eunixpd = unixpds + pdcnt; for (unixpd = unixpds; unixpd < eunixpd; unixpd++) { PRInt32 osfd = unixpd->osfd; if (unixpd->in_flags & _PR_UNIX_POLL_READ) { FD_SET(osfd, &_PR_FD_READ_SET(me->cpu)); _PR_FD_READ_CNT(me->cpu)[osfd]++; } if (unixpd->in_flags & _PR_UNIX_POLL_WRITE) { FD_SET(osfd, &_PR_FD_WRITE_SET(me->cpu)); (_PR_FD_WRITE_CNT(me->cpu))[osfd]++; } if (unixpd->in_flags & _PR_UNIX_POLL_EXCEPT) { FD_SET(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); (_PR_FD_EXCEPTION_CNT(me->cpu))[osfd]++; } if (osfd > _PR_IOQ_MAX_OSFD(me->cpu)) { _PR_IOQ_MAX_OSFD(me->cpu) = osfd; } } #endif /* !defined(_PR_USE_POLL) */ if (_PR_IOQ_TIMEOUT(me->cpu) > timeout) { _PR_IOQ_TIMEOUT(me->cpu) = timeout; } _PR_IOQ_OSFD_CNT(me->cpu) += pdcnt; _PR_SLEEPQ_LOCK(me->cpu); _PR_ADD_SLEEPQ(me, timeout); me->state = _PR_IO_WAIT; me->io_pending = PR_TRUE; me->io_suspended = PR_FALSE; _PR_SLEEPQ_UNLOCK(me->cpu); _PR_THREAD_UNLOCK(me); _PR_MD_IOQ_UNLOCK(); _PR_MD_WAIT(me, timeout); me->io_pending = PR_FALSE; me->io_suspended = PR_FALSE; /* * This thread should run on the same cpu on which it was blocked; when * the IO request times out the fd sets and fd counts for the * cpu are updated below. */ PR_ASSERT(me->cpu == io_cpu); /* ** If we timed out the pollq might still be on the ioq. Remove it ** before continuing. */ if (pq.on_ioq) { _PR_MD_IOQ_LOCK(); /* * Need to check pq.on_ioq again */ if (pq.on_ioq) { PR_REMOVE_LINK(&pq.links); #ifndef _PR_USE_POLL eunixpd = unixpds + pdcnt; for (unixpd = unixpds; unixpd < eunixpd; unixpd++) { PRInt32 osfd = unixpd->osfd; PRInt16 in_flags = unixpd->in_flags; if (in_flags & _PR_UNIX_POLL_READ) { if (--(_PR_FD_READ_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_READ_SET(me->cpu)); } if (in_flags & _PR_UNIX_POLL_WRITE) { if (--(_PR_FD_WRITE_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_WRITE_SET(me->cpu)); } if (in_flags & _PR_UNIX_POLL_EXCEPT) { if (--(_PR_FD_EXCEPTION_CNT(me->cpu))[osfd] == 0) FD_CLR(osfd, &_PR_FD_EXCEPTION_SET(me->cpu)); } } #endif /* _PR_USE_POLL */ PR_ASSERT(pq.npds == pdcnt); _PR_IOQ_OSFD_CNT(me->cpu) -= pdcnt; PR_ASSERT(_PR_IOQ_OSFD_CNT(me->cpu) >= 0); } _PR_MD_IOQ_UNLOCK(); } /* XXX Should we use _PR_FAST_INTSON or _PR_INTSON? */ if (1 == pdcnt) { _PR_FAST_INTSON(is); } else { _PR_INTSON(is); } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } rv = 0; if (pq.on_ioq == PR_FALSE) { /* Count the number of ready descriptors */ while (--pdcnt >= 0) { if (unixpds->out_flags != 0) { rv++; } unixpds++; } } return rv; } /* * Unblock threads waiting for I/O * used when interrupting threads * * NOTE: The thread lock should held when this function is called. * On return, the thread lock is released. */ void _PR_Unblock_IO_Wait(PRThread *thr) { int pri = thr->priority; _PRCPU *cpu = thr->cpu; /* * GLOBAL threads wakeup periodically to check for interrupt */ if (_PR_IS_NATIVE_THREAD(thr)) { _PR_THREAD_UNLOCK(thr); return; } PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ)); _PR_SLEEPQ_LOCK(cpu); _PR_DEL_SLEEPQ(thr, PR_TRUE); _PR_SLEEPQ_UNLOCK(cpu); PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD)); thr->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thr, cpu, pri); _PR_RUNQ_UNLOCK(cpu); _PR_THREAD_UNLOCK(thr); _PR_MD_WAKEUP_WAITER(thr); } #endif /* !defined(_PR_PTHREADS) */ /* * When a nonblocking connect has completed, determine whether it * succeeded or failed, and if it failed, what the error code is. * * The function returns the error code. An error code of 0 means * that the nonblocking connect succeeded. */ int _MD_unix_get_nonblocking_connect_error(int osfd) { #if defined(NTO) /* Neutrino does not support the SO_ERROR socket option */ PRInt32 rv; PRNetAddr addr; _PRSockLen_t addrlen = sizeof(addr); /* Test to see if we are using the Tiny TCP/IP Stack or the Full one. */ struct statvfs superblock; rv = fstatvfs(osfd, &superblock); if (rv == 0) { if (strcmp(superblock.f_basetype, "ttcpip") == 0) { /* Using the Tiny Stack! */ rv = getpeername(osfd, (struct sockaddr *) &addr, (_PRSockLen_t *) &addrlen); if (rv == -1) { int errno_copy = errno; /* make a copy so I don't * accidentally reset */ if (errno_copy == ENOTCONN) { struct stat StatInfo; rv = fstat(osfd, &StatInfo); if (rv == 0) { time_t current_time = time(NULL); /* * this is a real hack, can't explain why it * works it just does */ if (abs(current_time - StatInfo.st_atime) < 5) { return ECONNREFUSED; } else { return ETIMEDOUT; } } else { return ECONNREFUSED; } } else { return errno_copy; } } else { /* No Error */ return 0; } } else { /* Have the FULL Stack which supports SO_ERROR */ /* Hasn't been written yet, never been tested! */ /* Jerry.Kirk@Nexwarecorp.com */ int err; _PRSockLen_t optlen = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) { return errno; } else { return err; } } } else { return ECONNREFUSED; } #elif defined(UNIXWARE) /* * getsockopt() fails with EPIPE, so use getmsg() instead. */ int rv; int flags = 0; rv = getmsg(osfd, NULL, NULL, &flags); PR_ASSERT(-1 == rv || 0 == rv); if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) { return errno; } return 0; /* no error */ #else int err; _PRSockLen_t optlen = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) == -1) { return errno; } else { return err; } #endif } /************************************************************************/ /* ** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread ** safe. Unfortunately, neither is mozilla. To make these programs work ** in a pre-emptive threaded environment, we need to use a lock. */ void PR_XLock(void) { PR_EnterMonitor(_pr_Xfe_mon); } void PR_XUnlock(void) { PR_ExitMonitor(_pr_Xfe_mon); } PRBool PR_XIsLocked(void) { return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE; } void PR_XWait(int ms) { PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms)); } void PR_XNotify(void) { PR_Notify(_pr_Xfe_mon); } void PR_XNotifyAll(void) { PR_NotifyAll(_pr_Xfe_mon); } #if defined(HAVE_FCNTL_FILE_LOCKING) PRStatus _MD_LockFile(PRInt32 f) { PRInt32 rv; struct flock arg; arg.l_type = F_WRLCK; arg.l_whence = SEEK_SET; arg.l_start = 0; arg.l_len = 0; /* until EOF */ rv = fcntl(f, F_SETLKW, &arg); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_TLockFile(PRInt32 f) { PRInt32 rv; struct flock arg; arg.l_type = F_WRLCK; arg.l_whence = SEEK_SET; arg.l_start = 0; arg.l_len = 0; /* until EOF */ rv = fcntl(f, F_SETLK, &arg); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_UnlockFile(PRInt32 f) { PRInt32 rv; struct flock arg; arg.l_type = F_UNLCK; arg.l_whence = SEEK_SET; arg.l_start = 0; arg.l_len = 0; /* until EOF */ rv = fcntl(f, F_SETLK, &arg); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } #elif defined(HAVE_BSD_FLOCK) #include PRStatus _MD_LockFile(PRInt32 f) { PRInt32 rv; rv = flock(f, LOCK_EX); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_TLockFile(PRInt32 f) { PRInt32 rv; rv = flock(f, LOCK_EX|LOCK_NB); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_UnlockFile(PRInt32 f) { PRInt32 rv; rv = flock(f, LOCK_UN); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO()); return PR_FAILURE; } #else PRStatus _MD_LockFile(PRInt32 f) { PRInt32 rv; rv = lockf(f, F_LOCK, 0); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_TLockFile(PRInt32 f) { PRInt32 rv; rv = lockf(f, F_TLOCK, 0); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_UnlockFile(PRInt32 f) { PRInt32 rv; rv = lockf(f, F_ULOCK, 0); if (rv == 0) return PR_SUCCESS; _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO()); return PR_FAILURE; } #endif PRStatus _MD_gethostname(char *name, PRUint32 namelen) { PRIntn rv; rv = gethostname(name, namelen); if (0 == rv) { return PR_SUCCESS; } _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO()); return PR_FAILURE; } PRStatus _MD_getsysinfo(PRSysInfo cmd, char *name, PRUint32 namelen) { struct utsname info; PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE)); if (uname(&info) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } if (PR_SI_SYSNAME == cmd) (void)PR_snprintf(name, namelen, info.sysname); else if (PR_SI_RELEASE == cmd) (void)PR_snprintf(name, namelen, info.release); else return PR_FAILURE; return PR_SUCCESS; } /* ******************************************************************* * * Memory-mapped files * ******************************************************************* */ PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) { PRFileInfo info; PRUint32 sz; LL_L2UI(sz, size); if (sz) { if (PR_GetOpenFileInfo(fmap->fd, &info) == PR_FAILURE) { return PR_FAILURE; } if (sz > info.size) { /* * Need to extend the file */ if (fmap->prot != PR_PROT_READWRITE) { PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0); return PR_FAILURE; } if (PR_Seek(fmap->fd, sz - 1, PR_SEEK_SET) == -1) { return PR_FAILURE; } if (PR_Write(fmap->fd, "", 1) != 1) { return PR_FAILURE; } } } if (fmap->prot == PR_PROT_READONLY) { fmap->md.prot = PROT_READ; #ifdef OSF1V4_MAP_PRIVATE_BUG /* * Use MAP_SHARED to work around a bug in OSF1 V4.0D * (QAR 70220 in the OSF_QAR database) that results in * corrupted data in the memory-mapped region. This * bug is fixed in V5.0. */ fmap->md.flags = MAP_SHARED; #else fmap->md.flags = MAP_PRIVATE; #endif } else if (fmap->prot == PR_PROT_READWRITE) { fmap->md.prot = PROT_READ | PROT_WRITE; fmap->md.flags = MAP_SHARED; } else { PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY); fmap->md.prot = PROT_READ | PROT_WRITE; fmap->md.flags = MAP_PRIVATE; } return PR_SUCCESS; } void * _MD_MemMap( PRFileMap *fmap, PRInt64 offset, PRUint32 len) { PRInt32 off; void *addr; LL_L2I(off, offset); if ((addr = mmap(0, len, fmap->md.prot, fmap->md.flags, fmap->fd->secret->md.osfd, off)) == (void *) -1) { _PR_MD_MAP_MMAP_ERROR(_MD_ERRNO()); addr = NULL; } return addr; } PRStatus _MD_MemUnmap(void *addr, PRUint32 len) { if (munmap(addr, len) == 0) { return PR_SUCCESS; } _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } PRStatus _MD_CloseFileMap(PRFileMap *fmap) { if ( PR_TRUE == fmap->md.isAnonFM ) { PRStatus rc = PR_Close( fmap->fd ); if ( PR_FAILURE == rc ) { PR_LOG( _pr_io_lm, PR_LOG_DEBUG, ("_MD_CloseFileMap(): error closing anonymnous file map osfd")); return PR_FAILURE; } } PR_DELETE(fmap); return PR_SUCCESS; } PRStatus _MD_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len) { /* msync(..., MS_SYNC) alone is sufficient to flush modified data to disk * synchronously. It is not necessary to call fsync. */ if (msync(addr, len, MS_SYNC) == 0) { return PR_SUCCESS; } _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } #if defined(_PR_NEED_FAKE_POLL) /* * Some platforms don't have poll(). For easier porting of code * that calls poll(), we emulate poll() using select(). */ int poll(struct pollfd *filedes, unsigned long nfds, int timeout) { int i; int rv; int maxfd; fd_set rd, wr, ex; struct timeval tv, *tvp; if (timeout < 0 && timeout != -1) { errno = EINVAL; return -1; } if (timeout == -1) { tvp = NULL; } else { tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; tvp = &tv; } maxfd = -1; FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); for (i = 0; i < nfds; i++) { int osfd = filedes[i].fd; int events = filedes[i].events; PRBool fdHasEvent = PR_FALSE; if (osfd < 0) { continue; /* Skip this osfd. */ } /* * Map the poll events to the select fd_sets. * POLLIN, POLLRDNORM ===> readable * POLLOUT, POLLWRNORM ===> writable * POLLPRI, POLLRDBAND ===> exception * POLLNORM, POLLWRBAND (and POLLMSG on some platforms) * are ignored. * * The output events POLLERR and POLLHUP are never turned on. * POLLNVAL may be turned on. */ if (events & (POLLIN | POLLRDNORM)) { FD_SET(osfd, &rd); fdHasEvent = PR_TRUE; } if (events & (POLLOUT | POLLWRNORM)) { FD_SET(osfd, &wr); fdHasEvent = PR_TRUE; } if (events & (POLLPRI | POLLRDBAND)) { FD_SET(osfd, &ex); fdHasEvent = PR_TRUE; } if (fdHasEvent && osfd > maxfd) { maxfd = osfd; } } rv = select(maxfd + 1, &rd, &wr, &ex, tvp); /* Compute poll results */ if (rv > 0) { rv = 0; for (i = 0; i < nfds; i++) { PRBool fdHasEvent = PR_FALSE; filedes[i].revents = 0; if (filedes[i].fd < 0) { continue; } if (FD_ISSET(filedes[i].fd, &rd)) { if (filedes[i].events & POLLIN) { filedes[i].revents |= POLLIN; } if (filedes[i].events & POLLRDNORM) { filedes[i].revents |= POLLRDNORM; } fdHasEvent = PR_TRUE; } if (FD_ISSET(filedes[i].fd, &wr)) { if (filedes[i].events & POLLOUT) { filedes[i].revents |= POLLOUT; } if (filedes[i].events & POLLWRNORM) { filedes[i].revents |= POLLWRNORM; } fdHasEvent = PR_TRUE; } if (FD_ISSET(filedes[i].fd, &ex)) { if (filedes[i].events & POLLPRI) { filedes[i].revents |= POLLPRI; } if (filedes[i].events & POLLRDBAND) { filedes[i].revents |= POLLRDBAND; } fdHasEvent = PR_TRUE; } if (fdHasEvent) { rv++; } } PR_ASSERT(rv > 0); } else if (rv == -1 && errno == EBADF) { rv = 0; for (i = 0; i < nfds; i++) { filedes[i].revents = 0; if (filedes[i].fd < 0) { continue; } if (fcntl(filedes[i].fd, F_GETFL, 0) == -1) { filedes[i].revents = POLLNVAL; rv++; } } PR_ASSERT(rv > 0); } PR_ASSERT(-1 != timeout || rv != 0); return rv; } #endif /* _PR_NEED_FAKE_POLL */ nspr-4.11/nspr/pr/src/md/unix/unix_errors.c0000644000000000000000000004474512623070344017066 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #if defined(_PR_POLL_AVAILABLE) #include #endif #include void _MD_unix_map_default_error(int err) { PRErrorCode prError; switch (err ) { case EACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case EADDRINUSE: prError = PR_ADDRESS_IN_USE_ERROR; break; case EADDRNOTAVAIL: prError = PR_ADDRESS_NOT_AVAILABLE_ERROR; break; case EAFNOSUPPORT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break; case EAGAIN: prError = PR_WOULD_BLOCK_ERROR; break; /* * On QNX and Neutrino, EALREADY is defined as EBUSY. */ #if EALREADY != EBUSY case EALREADY: prError = PR_ALREADY_INITIATED_ERROR; break; #endif case EBADF: prError = PR_BAD_DESCRIPTOR_ERROR; break; #ifdef EBADMSG case EBADMSG: prError = PR_IO_ERROR; break; #endif case EBUSY: prError = PR_FILESYSTEM_MOUNTED_ERROR; break; case ECONNABORTED: prError = PR_CONNECT_ABORTED_ERROR; break; case ECONNREFUSED: prError = PR_CONNECT_REFUSED_ERROR; break; case ECONNRESET: prError = PR_CONNECT_RESET_ERROR; break; case EDEADLK: prError = PR_DEADLOCK_ERROR; break; #ifdef EDIRCORRUPTED case EDIRCORRUPTED: prError = PR_DIRECTORY_CORRUPTED_ERROR; break; #endif #ifdef EDQUOT case EDQUOT: prError = PR_NO_DEVICE_SPACE_ERROR; break; #endif case EEXIST: prError = PR_FILE_EXISTS_ERROR; break; case EFAULT: prError = PR_ACCESS_FAULT_ERROR; break; case EFBIG: prError = PR_FILE_TOO_BIG_ERROR; break; case EHOSTUNREACH: case EHOSTDOWN: prError = PR_HOST_UNREACHABLE_ERROR; break; case EINPROGRESS: prError = PR_IN_PROGRESS_ERROR; break; case EINTR: prError = PR_PENDING_INTERRUPT_ERROR; break; case EINVAL: prError = PR_INVALID_ARGUMENT_ERROR; break; case EIO: prError = PR_IO_ERROR; break; case EISCONN: prError = PR_IS_CONNECTED_ERROR; break; case EISDIR: prError = PR_IS_DIRECTORY_ERROR; break; case ELOOP: prError = PR_LOOP_ERROR; break; case EMFILE: prError = PR_PROC_DESC_TABLE_FULL_ERROR; break; case EMLINK: prError = PR_MAX_DIRECTORY_ENTRIES_ERROR; break; case EMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break; #ifdef EMULTIHOP case EMULTIHOP: prError = PR_REMOTE_FILE_ERROR; break; #endif case ENAMETOOLONG: prError = PR_NAME_TOO_LONG_ERROR; break; case ENETUNREACH: prError = PR_NETWORK_UNREACHABLE_ERROR; break; case ENFILE: prError = PR_SYS_DESC_TABLE_FULL_ERROR; break; /* * On SCO OpenServer 5, ENOBUFS is defined as ENOSR. */ #if defined(ENOBUFS) && (ENOBUFS != ENOSR) case ENOBUFS: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; #endif case ENODEV: prError = PR_FILE_NOT_FOUND_ERROR; break; case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break; case ENOLCK: prError = PR_FILE_IS_LOCKED_ERROR; break; #ifdef ENOLINK case ENOLINK: prError = PR_REMOTE_FILE_ERROR; break; #endif case ENOMEM: prError = PR_OUT_OF_MEMORY_ERROR; break; case ENOPROTOOPT: prError = PR_INVALID_ARGUMENT_ERROR; break; case ENOSPC: prError = PR_NO_DEVICE_SPACE_ERROR; break; #ifdef ENOSR case ENOSR: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; #endif case ENOSYS: prError = PR_NOT_IMPLEMENTED_ERROR; break; case ENOTCONN: prError = PR_NOT_CONNECTED_ERROR; break; case ENOTDIR: prError = PR_NOT_DIRECTORY_ERROR; break; case ENOTSOCK: prError = PR_NOT_SOCKET_ERROR; break; case ENXIO: prError = PR_FILE_NOT_FOUND_ERROR; break; case EOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break; #ifdef EOVERFLOW case EOVERFLOW: prError = PR_BUFFER_OVERFLOW_ERROR; break; #endif case EPERM: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case EPIPE: prError = PR_CONNECT_RESET_ERROR; break; #ifdef EPROTO case EPROTO: prError = PR_IO_ERROR; break; #endif case EPROTONOSUPPORT: prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR; break; case EPROTOTYPE: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break; case ERANGE: prError = PR_INVALID_METHOD_ERROR; break; case EROFS: prError = PR_READ_ONLY_FILESYSTEM_ERROR; break; case ESPIPE: prError = PR_INVALID_METHOD_ERROR; break; case ETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break; #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: prError = PR_WOULD_BLOCK_ERROR; break; #endif case EXDEV: prError = PR_NOT_SAME_DEVICE_ERROR; break; default: prError = PR_UNKNOWN_ERROR; break; } PR_SetError(prError, err); } void _MD_unix_map_opendir_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_closedir_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_BAD_DESCRIPTOR_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_readdir_error(int err) { PRErrorCode prError; switch (err) { case 0: case ENOENT: prError = PR_NO_MORE_FILES_ERROR; break; #ifdef EOVERFLOW case EOVERFLOW: prError = PR_IO_ERROR; break; #endif case EINVAL: prError = PR_IO_ERROR; break; case ENXIO: prError = PR_IO_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_unlink_error(int err) { PRErrorCode prError; switch (err) { case EPERM: prError = PR_IS_DIRECTORY_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_stat_error(int err) { PRErrorCode prError; switch (err) { case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_fstat_error(int err) { PRErrorCode prError; switch (err) { case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_rename_error(int err) { PRErrorCode prError; switch (err) { case EEXIST: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_access_error(int err) { PRErrorCode prError; switch (err) { case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_mkdir_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_rmdir_error(int err) { PRErrorCode prError; switch (err) { /* * On AIX 4.3, ENOTEMPTY is defined as EEXIST. */ #if ENOTEMPTY != EEXIST case ENOTEMPTY: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break; #endif case EEXIST: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break; case EINVAL: prError = PR_DIRECTORY_NOT_EMPTY_ERROR; break; case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_read_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_INVALID_METHOD_ERROR; break; case ENXIO: prError = PR_INVALID_ARGUMENT_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_write_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_INVALID_METHOD_ERROR; break; case ENXIO: prError = PR_INVALID_METHOD_ERROR; break; case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_lseek_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_fsync_error(int err) { PRErrorCode prError; switch (err) { case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; case EINVAL: prError = PR_INVALID_METHOD_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_close_error(int err) { PRErrorCode prError; switch (err) { case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_socket_error(int err) { PRErrorCode prError; switch (err) { case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_socketavailable_error(int err) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err); } void _MD_unix_map_recv_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_recvfrom_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_send_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_sendto_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_writev_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_accept_error(int err) { PRErrorCode prError; switch (err) { case ENODEV: prError = PR_NOT_TCP_SOCKET_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_connect_error(int err) { PRErrorCode prError; switch (err) { #if defined(UNIXWARE) /* * On some platforms, if we connect to a port on the local host * (the loopback address) that no process is listening on, we get * EIO instead of ECONNREFUSED. */ case EIO: prError = PR_CONNECT_REFUSED_ERROR; break; #endif case ENXIO: prError = PR_IO_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_bind_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_listen_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_shutdown_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_socketpair_error(int err) { PRErrorCode prError; switch (err) { case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_getsockname_error(int err) { PRErrorCode prError; switch (err) { case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_getpeername_error(int err) { PRErrorCode prError; switch (err) { case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_getsockopt_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_BUFFER_OVERFLOW_ERROR; break; case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_setsockopt_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_BUFFER_OVERFLOW_ERROR; break; case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_open_error(int err) { PRErrorCode prError; switch (err) { case EAGAIN: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case EBUSY: prError = PR_IO_ERROR; break; case ENODEV: prError = PR_FILE_NOT_FOUND_ERROR; break; case ENOMEM: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; #ifdef EOVERFLOW case EOVERFLOW: prError = PR_FILE_TOO_BIG_ERROR; break; #endif case ETIMEDOUT: prError = PR_REMOTE_FILE_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_mmap_error(int err) { PRErrorCode prError; switch (err) { case EAGAIN: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case EMFILE: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case ENODEV: prError = PR_OPERATION_NOT_SUPPORTED_ERROR; break; case ENXIO: prError = PR_INVALID_ARGUMENT_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_gethostname_error(int err) { _MD_unix_map_default_error(err); } void _MD_unix_map_select_error(int err) { _MD_unix_map_default_error(err); } #if defined(_PR_POLL_AVAILABLE) || defined(_PR_NEED_FAKE_POLL) void _MD_unix_map_poll_error(int err) { PRErrorCode prError; switch (err) { case EAGAIN: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_poll_revents_error(int err) { if (err & POLLNVAL) PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF); else if (err & POLLHUP) PR_SetError(PR_CONNECT_RESET_ERROR, EPIPE); else if (err & POLLERR) PR_SetError(PR_IO_ERROR, EIO); else PR_SetError(PR_UNKNOWN_ERROR, err); } #endif /* _PR_POLL_AVAILABLE || _PR_NEED_FAKE_POLL */ void _MD_unix_map_flock_error(int err) { PRErrorCode prError; switch (err) { case EINVAL: prError = PR_BAD_DESCRIPTOR_ERROR; break; case EWOULDBLOCK: prError = PR_FILE_IS_LOCKED_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_unix_map_lockf_error(int err) { PRErrorCode prError; switch (err) { case EACCES: prError = PR_FILE_IS_LOCKED_ERROR; break; case EDEADLK: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; default: _MD_unix_map_default_error(err); return; } PR_SetError(prError, err); } #ifdef AIX void _MD_aix_map_sendfile_error(int err) { _MD_unix_map_default_error(err); } #endif /* AIX */ #ifdef HPUX11 void _MD_hpux_map_sendfile_error(int err) { _MD_unix_map_default_error(err); } #endif /* HPUX11 */ #ifdef SOLARIS void _MD_solaris_map_sendfile_error(int err) { PRErrorCode prError; switch (err) { /* * Solaris defines a 0 return value for sendfile to mean end-of-file. */ case 0: prError = PR_END_OF_FILE_ERROR; break; default: _MD_unix_map_default_error(err) ; return; } PR_SetError(prError, err); } #endif /* SOLARIS */ #ifdef LINUX void _MD_linux_map_sendfile_error(int err) { _MD_unix_map_default_error(err) ; } #endif /* LINUX */ nspr-4.11/nspr/pr/src/md/unix/unixware.c0000644000000000000000000003071412623070344016340 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #if !defined (USE_SVR4_THREADS) /* * using only NSPR threads here */ #include void _MD_EarlyInit(void) { } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) setjmp(CONTEXT(t)); } *np = sizeof(CONTEXT(t)) / sizeof(PRWord); return (PRWord *) CONTEXT(t); } #ifdef ALARMS_BREAK_TCP /* I don't think they do */ PRInt32 _MD_connect(PRInt32 osfd, const PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout) { PRInt32 rv; _MD_BLOCK_CLOCK_INTERRUPTS(); rv = _connect(osfd,addr,addrlen); _MD_UNBLOCK_CLOCK_INTERRUPTS(); } PRInt32 _MD_accept(PRInt32 osfd, PRNetAddr *addr, PRInt32 addrlen, PRIntervalTime timeout) { PRInt32 rv; _MD_BLOCK_CLOCK_INTERRUPTS(); rv = _accept(osfd,addr,addrlen); _MD_UNBLOCK_CLOCK_INTERRUPTS(); return(rv); } #endif /* * These are also implemented in pratom.c using NSPR locks. Any reason * this might be better or worse? If you like this better, define * _PR_HAVE_ATOMIC_OPS in include/md/unixware.h */ #ifdef _PR_HAVE_ATOMIC_OPS /* Atomic operations */ #include static FILE *_uw_semf; void _MD_INIT_ATOMIC(void) { /* Sigh. Sure wish SYSV semaphores weren't such a pain to use */ if ((_uw_semf = tmpfile()) == NULL) PR_ASSERT(0); return; } void _MD_ATOMIC_INCREMENT(PRInt32 *val) { flockfile(_uw_semf); (*val)++; unflockfile(_uw_semf); } void _MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) { flockfile(_uw_semf); (*ptr) += val; unflockfile(_uw_semf); } void _MD_ATOMIC_DECREMENT(PRInt32 *val) { flockfile(_uw_semf); (*val)--; unflockfile(_uw_semf); } void _MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) { flockfile(_uw_semf); *val = newval; unflockfile(_uw_semf); } #endif void _MD_SET_PRIORITY(_MDThread *thread, PRUintn newPri) { return; } PRStatus _MD_InitializeThread(PRThread *thread) { return PR_SUCCESS; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); _PR_MD_SWITCH_CONTEXT(thread); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread) { PR_ASSERT(!(thread->flags & _PR_GLOBAL_SCOPE)); } return PR_SUCCESS; } /* These functions should not be called for Unixware */ void _MD_YIELD(void) { PR_NOT_REACHED("_MD_YIELD should not be called for Unixware."); } PRStatus _MD_CREATE_THREAD( PRThread *thread, void (*start) (void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for Unixware."); } #else /* USE_SVR4_THREADS */ /* NOTE: * SPARC v9 (Ultras) do have an atomic test-and-set operation. But * SPARC v8 doesn't. We should detect in the init if we are running on * v8 or v9, and then use assembly where we can. */ #include #include static mutex_t _unixware_atomic = DEFAULTMUTEX; #define TEST_THEN_ADD(where, inc) \ if (mutex_lock(&_unixware_atomic) != 0)\ PR_ASSERT(0);\ *where += inc;\ if (mutex_unlock(&_unixware_atomic) != 0)\ PR_ASSERT(0); #define TEST_THEN_SET(where, val) \ if (mutex_lock(&_unixware_atomic) != 0)\ PR_ASSERT(0);\ *where = val;\ if (mutex_unlock(&_unixware_atomic) != 0)\ PR_ASSERT(0); void _MD_INIT_ATOMIC(void) { } void _MD_ATOMIC_INCREMENT(PRInt32 *val) { TEST_THEN_ADD(val, 1); } void _MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) { TEST_THEN_ADD(ptr, val); } void _MD_ATOMIC_DECREMENT(PRInt32 *val) { TEST_THEN_ADD(val, 0xffffffff); } void _MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) { TEST_THEN_SET(val, newval); } #include #include #include #include #include #include THREAD_KEY_T threadid_key; THREAD_KEY_T cpuid_key; THREAD_KEY_T last_thread_key; static sigset_t set, oldset; void _MD_EarlyInit(void) { THR_KEYCREATE(&threadid_key, NULL); THR_KEYCREATE(&cpuid_key, NULL); THR_KEYCREATE(&last_thread_key, NULL); sigemptyset(&set); sigaddset(&set, SIGALRM); } PRStatus _MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { long flags; /* mask out SIGALRM for native thread creation */ thr_sigsetmask(SIG_BLOCK, &set, &oldset); flags = (state == PR_JOINABLE_THREAD ? THR_SUSPENDED/*|THR_NEW_LWP*/ : THR_SUSPENDED|THR_DETACHED/*|THR_NEW_LWP*/); if (_PR_IS_GCABLE_THREAD(thread) || (scope == PR_GLOBAL_BOUND_THREAD)) flags |= THR_BOUND; if (thr_create(NULL, thread->stack->stackSize, (void *(*)(void *)) start, (void *) thread, flags, &thread->md.handle)) { thr_sigsetmask(SIG_SETMASK, &oldset, NULL); return PR_FAILURE; } /* When the thread starts running, then the lwpid is set to the right * value. Until then we want to mark this as 'uninit' so that * its register state is initialized properly for GC */ thread->md.lwpid = -1; thr_sigsetmask(SIG_SETMASK, &oldset, NULL); _MD_NEW_SEM(&thread->md.waiter_sem, 0); if ((scope == PR_GLOBAL_THREAD) || (scope == PR_GLOBAL_BOUND_THREAD)) { thread->flags |= _PR_GLOBAL_SCOPE; } /* ** Set the thread priority. This will also place the thread on ** the runQ. ** ** Force PR_SetThreadPriority to set the priority by ** setting thread->priority to 100. */ { int pri; pri = thread->priority; thread->priority = 100; PR_SetThreadPriority( thread, pri ); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("(0X%x)[Start]: on to runq at priority %d", thread, thread->priority)); } /* Activate the thread */ if (thr_continue( thread->md.handle ) ) { return PR_FAILURE; } return PR_SUCCESS; } void _MD_cleanup_thread(PRThread *thread) { thread_t hdl; PRMonitor *mon; hdl = thread->md.handle; /* ** First, suspend the thread (unless it's the active one) ** Because we suspend it first, we don't have to use LOCK_SCHEDULER to ** prevent both of us modifying the thread structure at the same time. */ if ( thread != _PR_MD_CURRENT_THREAD() ) { thr_suspend(hdl); } PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("(0X%x)[DestroyThread]\n", thread)); _MD_DESTROY_SEM(&thread->md.waiter_sem); } void _MD_SET_PRIORITY(_MDThread *md_thread, PRUintn newPri) { if(thr_setprio((thread_t)md_thread->handle, newPri)) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("_PR_SetThreadPriority: can't set thread priority\n")); } } void _MD_WAIT_CV( struct _MDCVar *md_cv, struct _MDLock *md_lock, PRIntervalTime timeout) { struct timespec tt; PRUint32 msec; int rv; PRThread *me = _PR_MD_CURRENT_THREAD(); msec = PR_IntervalToMilliseconds(timeout); GETTIME (&tt); tt.tv_sec += msec / PR_MSEC_PER_SEC; tt.tv_nsec += (msec % PR_MSEC_PER_SEC) * PR_NSEC_PER_MSEC; /* Check for nsec overflow - otherwise we'll get an EINVAL */ if (tt.tv_nsec >= PR_NSEC_PER_SEC) { tt.tv_sec++; tt.tv_nsec -= PR_NSEC_PER_SEC; } me->md.sp = unixware_getsp(); /* XXX Solaris 2.5.x gives back EINTR occasionally for no reason * hence ignore EINTR for now */ COND_TIMEDWAIT(&md_cv->cv, &md_lock->lock, &tt); } void _MD_lock(struct _MDLock *md_lock) { mutex_lock(&md_lock->lock); } void _MD_unlock(struct _MDLock *md_lock) { mutex_unlock(&((md_lock)->lock)); } PRThread *_pr_current_thread_tls() { PRThread *ret; thr_getspecific(threadid_key, (void **)&ret); return ret; } PRStatus _MD_WAIT(PRThread *thread, PRIntervalTime ticks) { _MD_WAIT_SEM(&thread->md.waiter_sem); return PR_SUCCESS; } PRStatus _MD_WAKEUP_WAITER(PRThread *thread) { if (thread == NULL) { return PR_SUCCESS; } _MD_POST_SEM(&thread->md.waiter_sem); return PR_SUCCESS; } _PRCPU *_pr_current_cpu_tls() { _PRCPU *ret; thr_getspecific(cpuid_key, (void **)&ret); return ret; } PRThread *_pr_last_thread_tls() { PRThread *ret; thr_getspecific(last_thread_key, (void **)&ret); return ret; } _MDLock _pr_ioq_lock; void _MD_INIT_IO (void) { _MD_NEW_LOCK(&_pr_ioq_lock); } PRStatus _MD_InitializeThread(PRThread *thread) { if (!_PR_IS_NATIVE_THREAD(thread)) return; /* prime the sp; substract 4 so we don't hit the assert that * curr sp > base_stack */ thread->md.sp = (uint_t) thread->stack->allocBase - sizeof(long); thread->md.lwpid = _lwp_self(); thread->md.handle = THR_SELF(); /* all threads on Solaris are global threads from NSPR's perspective * since all of them are mapped to Solaris threads. */ thread->flags |= _PR_GLOBAL_SCOPE; /* For primordial/attached thread, we don't create an underlying native thread. * So, _MD_CREATE_THREAD() does not get called. We need to do initialization * like allocating thread's synchronization variables and set the underlying * native thread's priority. */ if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) { _MD_NEW_SEM(&thread->md.waiter_sem, 0); _MD_SET_PRIORITY(&(thread->md), thread->priority); } return PR_SUCCESS; } static sigset_t old_mask; /* store away original gc thread sigmask */ static int gcprio; /* store away original gc thread priority */ static lwpid_t *all_lwps=NULL; /* list of lwps that we suspended */ static int num_lwps ; static int suspendAllOn = 0; #define VALID_SP(sp, bottom, top) \ (((uint_t)(sp)) > ((uint_t)(bottom)) && ((uint_t)(sp)) < ((uint_t)(top))) void unixware_preempt_off() { sigset_t set; (void)sigfillset(&set); sigprocmask (SIG_SETMASK, &set, &old_mask); } void unixware_preempt_on() { sigprocmask (SIG_SETMASK, &old_mask, NULL); } void _MD_Begin_SuspendAll() { unixware_preempt_off(); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin_SuspendAll\n")); /* run at highest prio so I cannot be preempted */ thr_getprio(thr_self(), &gcprio); thr_setprio(thr_self(), 0x7fffffff); suspendAllOn = 1; } void _MD_End_SuspendAll() { } void _MD_End_ResumeAll() { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End_ResumeAll\n")); thr_setprio(thr_self(), gcprio); unixware_preempt_on(); suspendAllOn = 0; } void _MD_Suspend(PRThread *thr) { int lwp_fd, result; int lwp_main_proc_fd = 0; thr_suspend(thr->md.handle); if (!_PR_IS_GCABLE_THREAD(thr)) return; /* XXX Primordial thread can't be bound to an lwp, hence there is no * way we can assume that we can get the lwp status for primordial * thread reliably. Hence we skip this for primordial thread, hoping * that the SP is saved during lock and cond. wait. * XXX - Again this is concern only for java interpreter, not for the * server, 'cause primordial thread in the server does not do java work */ if (thr->flags & _PR_PRIMORDIAL) return; /* if the thread is not started yet then don't do anything */ if (!suspendAllOn || thr->md.lwpid == -1) return; } void _MD_Resume(PRThread *thr) { if (!_PR_IS_GCABLE_THREAD(thr) || !suspendAllOn){ /*XXX When the suspendAllOn is set, we will be trying to do lwp_suspend * during that time we can't call any thread lib or libc calls. Hence * make sure that no resume is requested for Non gcable thread * during suspendAllOn */ PR_ASSERT(!suspendAllOn); thr_continue(thr->md.handle); return; } if (thr->md.lwpid == -1) return; if ( _lwp_continue(thr->md.lwpid) < 0) { PR_ASSERT(0); /* ARGH, we are hosed! */ } } PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { if (isCurrent) { (void) getcontext(CONTEXT(t)); /* XXX tune me: set md_IRIX.c */ } *np = NGREG; if (t->md.lwpid == -1) memset(&t->md.context.uc_mcontext.gregs[0], 0, NGREG * sizeof(PRWord)); return (PRWord*) &t->md.context.uc_mcontext.gregs[0]; } int _pr_unixware_clock_gettime (struct timespec *tp) { struct timeval tv; gettimeofday(&tv, NULL); tp->tv_sec = tv.tv_sec; tp->tv_nsec = tv.tv_usec * 1000; return 0; } #endif /* USE_SVR4_THREADS */ nspr-4.11/nspr/pr/src/md/unix/uxpoll.c0000644000000000000000000005631112623070344016022 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if defined(_PR_PTHREADS) #error "This file should not be compiled" #else /* defined(_PR_PTHREADS) */ #include "primpl.h" #include #include #ifdef _PR_USE_POLL #include #endif #if defined(_PR_USE_POLL) static PRInt32 NativeThreadPoll( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { /* * This function is mostly duplicated from ptio.s's PR_Poll(). */ PRInt32 ready = 0; /* * For restarting poll() if it is interrupted by a signal. * We use these variables to figure out how much time has * elapsed and how much of the timeout still remains. */ PRIntn index, msecs; struct pollfd *syspoll = NULL; PRIntervalTime start, elapsed, remaining; syspoll = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd)); if (NULL == syspoll) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } for (index = 0; index < npds; ++index) { PRFileDesc *bottom; PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (pds[index].in_flags & PR_POLL_READ) { in_flags_read = (pds[index].fd->methods->poll)( pds[index].fd, pds[index].in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pds[index].in_flags & PR_POLL_WRITE) { in_flags_write = (pds[index].fd->methods->poll)( pds[index].fd, pds[index].in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one is ready right now */ if (0 == ready) { /* * We will return without calling the system * poll function. So zero the out_flags * fields of all the poll descriptors before * this one. */ int i; for (i = 0; i < index; i++) { pds[i].out_flags = 0; } } ready += 1; pds[index].out_flags = out_flags_read | out_flags_write; } else { pds[index].out_flags = 0; /* pre-condition */ /* now locate the NSPR layer at the bottom of the stack */ bottom = PR_GetIdentitiesLayer(pds[index].fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { syspoll[index].fd = bottom->secret->md.osfd; syspoll[index].events = 0; /* pre-condition */ if (in_flags_read & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_READ_SYS_READ; syspoll[index].events |= POLLIN; } if (in_flags_read & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_READ_SYS_WRITE; syspoll[index].events |= POLLOUT; } if (in_flags_write & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_READ; syspoll[index].events |= POLLIN; } if (in_flags_write & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_WRITE; syspoll[index].events |= POLLOUT; } if (pds[index].in_flags & PR_POLL_EXCEPT) syspoll[index].events |= POLLPRI; } } else { if (0 == ready) { int i; for (i = 0; i < index; i++) { pds[i].out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pds[index].out_flags = PR_POLL_NVAL; /* bogii */ } } } else { /* make poll() ignore this entry */ syspoll[index].fd = -1; syspoll[index].events = 0; pds[index].out_flags = 0; } } if (0 == ready) { switch (timeout) { case PR_INTERVAL_NO_WAIT: msecs = 0; break; case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break; default: msecs = PR_IntervalToMilliseconds(timeout); start = PR_IntervalNow(); } retry: ready = _MD_POLL(syspoll, npds, msecs); if (-1 == ready) { PRIntn oserror = errno; if (EINTR == oserror) { if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0; else { elapsed = (PRIntervalTime)(PR_IntervalNow() - start); if (elapsed > timeout) ready = 0; /* timed out */ else { remaining = timeout - elapsed; msecs = PR_IntervalToMilliseconds(remaining); goto retry; } } } else _PR_MD_MAP_POLL_ERROR(oserror); } else if (ready > 0) { for (index = 0; index < npds; ++index) { PRInt16 out_flags = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (0 != syspoll[index].revents) { /* ** Set up the out_flags so that it contains the ** bits that the highest layer thinks are nice ** to have. Then the client of that layer will ** call the appropriate I/O function and maybe ** the protocol will make progress. */ if (syspoll[index].revents & POLLIN) { if (pds[index].out_flags & _PR_POLL_READ_SYS_READ) { out_flags |= PR_POLL_READ; } if (pds[index].out_flags & _PR_POLL_WRITE_SYS_READ) { out_flags |= PR_POLL_WRITE; } } if (syspoll[index].revents & POLLOUT) { if (pds[index].out_flags & _PR_POLL_READ_SYS_WRITE) { out_flags |= PR_POLL_READ; } if (pds[index].out_flags & _PR_POLL_WRITE_SYS_WRITE) { out_flags |= PR_POLL_WRITE; } } if (syspoll[index].revents & POLLPRI) out_flags |= PR_POLL_EXCEPT; if (syspoll[index].revents & POLLERR) out_flags |= PR_POLL_ERR; if (syspoll[index].revents & POLLNVAL) out_flags |= PR_POLL_NVAL; if (syspoll[index].revents & POLLHUP) out_flags |= PR_POLL_HUP; } } pds[index].out_flags = out_flags; } } } PR_DELETE(syspoll); return ready; } /* NativeThreadPoll */ #endif /* defined(_PR_USE_POLL) */ #if !defined(_PR_USE_POLL) static PRInt32 NativeThreadSelect( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { /* * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL(). */ fd_set rd, wt, ex; PRFileDesc *bottom; PRPollDesc *pd, *epd; PRInt32 maxfd = -1, ready, err; PRIntervalTime remaining, elapsed, start; struct timeval tv, *tvp = NULL; FD_ZERO(&rd); FD_ZERO(&wt); FD_ZERO(&ex); ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one's ready right now */ if (0 == ready) { /* * We will have to return without calling the * system poll/select function. So zero the * out_flags fields of all the poll descriptors * before this one. */ PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; pd->out_flags = out_flags_read | out_flags_write; } else { pd->out_flags = 0; /* pre-condition */ /* make sure this is an NSPR supported stack */ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { PRInt32 osfd = bottom->secret->md.osfd; if (osfd > maxfd) maxfd = osfd; if (in_flags_read & PR_POLL_READ) { pd->out_flags |= _PR_POLL_READ_SYS_READ; FD_SET(osfd, &rd); } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; FD_SET(osfd, &wt); } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; FD_SET(osfd, &rd); } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; FD_SET(osfd, &wt); } if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex); } } else { if (0 == ready) { PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pd->out_flags = PR_POLL_NVAL; /* bogii */ } } } else { pd->out_flags = 0; } } if (0 != ready) return ready; /* no need to block */ remaining = timeout; start = PR_IntervalNow(); retry: if (timeout != PR_INTERVAL_NO_TIMEOUT) { PRInt32 ticksPerSecond = PR_TicksPerSecond(); tv.tv_sec = remaining / ticksPerSecond; tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond ); tvp = &tv; } ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp); if (ready == -1 && errno == EINTR) { if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; else { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) ready = 0; /* timed out */ else { remaining = timeout - elapsed; goto retry; } } } /* ** Now to unravel the select sets back into the client's poll ** descriptor list. Is this possibly an area for pissing away ** a few cycles or what? */ if (ready > 0) { ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { PRInt32 osfd; bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); osfd = bottom->secret->md.osfd; if (FD_ISSET(osfd, &rd)) { if (pd->out_flags & _PR_POLL_READ_SYS_READ) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) out_flags |= PR_POLL_WRITE; } if (FD_ISSET(osfd, &wt)) { if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) out_flags |= PR_POLL_WRITE; } if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; } pd->out_flags = out_flags; if (out_flags) ready++; } PR_ASSERT(ready > 0); } else if (ready < 0) { err = _MD_ERRNO(); if (err == EBADF) { /* Find the bad fds */ ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { pd->out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1) { pd->out_flags = PR_POLL_NVAL; ready++; } } } PR_ASSERT(ready > 0); } else _PR_MD_MAP_SELECT_ERROR(err); } return ready; } /* NativeThreadSelect */ #endif /* !defined(_PR_USE_POLL) */ static PRInt32 LocalThreads( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { PRPollDesc *pd, *epd; PRInt32 ready, pdcnt; _PRUnixPollDesc *unixpds, *unixpd; /* * XXX * PRPollDesc has a PRFileDesc field, fd, while the IOQ * is a list of PRPollQueue structures, each of which contains * a _PRUnixPollDesc. A _PRUnixPollDesc struct contains * the OS file descriptor, osfd, and not a PRFileDesc. * So, we have allocate memory for _PRUnixPollDesc structures, * copy the flags information from the pds list and have pq * point to this list of _PRUnixPollDesc structures. * * It would be better if the memory allocation can be avoided. */ unixpd = unixpds = (_PRUnixPollDesc*) PR_MALLOC(npds * sizeof(_PRUnixPollDesc)); if (NULL == unixpds) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } ready = 0; for (pdcnt = 0, pd = pds, epd = pd + npds; pd < epd; pd++) { PRFileDesc *bottom; PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)( pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one's ready right now */ if (0 == ready) { /* * We will have to return without calling the * system poll/select function. So zero the * out_flags fields of all the poll descriptors * before this one. */ PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; pd->out_flags = out_flags_read | out_flags_write; } else { pd->out_flags = 0; /* pre-condition */ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { unixpd->osfd = bottom->secret->md.osfd; unixpd->in_flags = 0; if (in_flags_read & PR_POLL_READ) { unixpd->in_flags |= _PR_UNIX_POLL_READ; pd->out_flags |= _PR_POLL_READ_SYS_READ; } if (in_flags_read & PR_POLL_WRITE) { unixpd->in_flags |= _PR_UNIX_POLL_WRITE; pd->out_flags |= _PR_POLL_READ_SYS_WRITE; } if (in_flags_write & PR_POLL_READ) { unixpd->in_flags |= _PR_UNIX_POLL_READ; pd->out_flags |= _PR_POLL_WRITE_SYS_READ; } if (in_flags_write & PR_POLL_WRITE) { unixpd->in_flags |= _PR_UNIX_POLL_WRITE; pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; } if ((in_flags_read | in_flags_write) & PR_POLL_EXCEPT) { unixpd->in_flags |= _PR_UNIX_POLL_EXCEPT; } unixpd++; pdcnt++; } } else { if (0 == ready) { PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pd->out_flags = PR_POLL_NVAL; /* bogii */ } } } } if (0 != ready) { /* no need to block */ PR_DELETE(unixpds); return ready; } ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout); /* * Copy the out_flags from the _PRUnixPollDesc structures to the * user's PRPollDesc structures and free the allocated memory */ unixpd = unixpds; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { /* * take errors from the poll operation, * the R/W bits from the request */ if (0 != unixpd->out_flags) { if (unixpd->out_flags & _PR_UNIX_POLL_READ) { if (pd->out_flags & _PR_POLL_READ_SYS_READ) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) out_flags |= PR_POLL_WRITE; } if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) { if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) out_flags |= PR_POLL_WRITE; } if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) out_flags |= PR_POLL_EXCEPT; if (unixpd->out_flags & _PR_UNIX_POLL_ERR) out_flags |= PR_POLL_ERR; if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) out_flags |= PR_POLL_NVAL; if (unixpd->out_flags & _PR_UNIX_POLL_HUP) out_flags |= PR_POLL_HUP; } unixpd++; } pd->out_flags = out_flags; } PR_DELETE(unixpds); return ready; } /* LocalThreads */ #if defined(_PR_USE_POLL) #define NativeThreads NativeThreadPoll #else #define NativeThreads NativeThreadSelect #endif PRInt32 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { PRInt32 rv = 0; PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } if (0 == npds) PR_Sleep(timeout); else if (_PR_IS_NATIVE_THREAD(me)) rv = NativeThreads(pds, npds, timeout); else rv = LocalThreads(pds, npds, timeout); return rv; } /* _MD_pr_poll */ #endif /* defined(_PR_PTHREADS) */ /* uxpoll.c */ nspr-4.11/nspr/pr/src/md/unix/uxproces.c0000644000000000000000000005405712623070344016354 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include #include #include #if defined(AIX) #include /* For dlopen, dlsym, dlclose */ #endif #if defined(DARWIN) #if defined(HAVE_CRT_EXTERNS_H) #include #endif #else PR_IMPORT_DATA(char **) environ; #endif /* * HP-UX 9 doesn't have the SA_RESTART flag. */ #ifndef SA_RESTART #define SA_RESTART 0 #endif /* ********************************************************************** * * The Unix process routines * ********************************************************************** */ #define _PR_SIGNALED_EXITSTATUS 256 typedef enum pr_PidState { _PR_PID_DETACHED, _PR_PID_REAPED, _PR_PID_WAITING } pr_PidState; typedef struct pr_PidRecord { pid_t pid; int exitStatus; pr_PidState state; PRCondVar *reapedCV; struct pr_PidRecord *next; } pr_PidRecord; /* * Irix sprocs and LinuxThreads are actually a kind of processes * that can share the virtual address space and file descriptors. */ #if (defined(IRIX) && !defined(_PR_PTHREADS)) \ || ((defined(LINUX) || defined(__GNU__) || defined(__GLIBC__)) \ && defined(_PR_PTHREADS)) #define _PR_SHARE_CLONES #endif /* * The macro _PR_NATIVE_THREADS indicates that we are * using native threads only, so waitpid() blocks just the * calling thread, not the process. In this case, the waitpid * daemon thread can safely block in waitpid(). So we don't * need to catch SIGCHLD, and the pipe to unblock PR_Poll() is * also not necessary. */ #if defined(_PR_GLOBAL_THREADS_ONLY) \ || (defined(_PR_PTHREADS) \ && !defined(LINUX) && !defined(__GNU__) && !defined(__GLIBC__)) #define _PR_NATIVE_THREADS #endif /* * All the static variables used by the Unix process routines are * collected in this structure. */ static struct { PRCallOnceType once; PRThread *thread; PRLock *ml; #if defined(_PR_NATIVE_THREADS) PRInt32 numProcs; PRCondVar *cv; #else int pipefd[2]; #endif pr_PidRecord **pidTable; #ifdef _PR_SHARE_CLONES struct pr_CreateProcOp *opHead, *opTail; #endif #ifdef AIX pid_t (*forkptr)(void); /* Newer versions of AIX (starting in 4.3.2) * have f_fork, which is faster than the * regular fork in a multithreaded process * because it skips calling the fork handlers. * So we look up the f_fork symbol to see if * it's available and fall back on fork. */ #endif /* AIX */ } pr_wp; #ifdef _PR_SHARE_CLONES static int pr_waitpid_daemon_exit; void _MD_unix_terminate_waitpid_daemon(void) { if (pr_wp.thread) { pr_waitpid_daemon_exit = 1; write(pr_wp.pipefd[1], "", 1); PR_JoinThread(pr_wp.thread); } } #endif static PRStatus _MD_InitProcesses(void); #if !defined(_PR_NATIVE_THREADS) static void pr_InstallSigchldHandler(void); #endif static PRProcess * ForkAndExec( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { PRProcess *process; int nEnv, idx; char *const *childEnvp; char **newEnvp = NULL; int flags; process = PR_NEW(PRProcess); if (!process) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } childEnvp = envp; if (attr && attr->fdInheritBuffer) { PRBool found = PR_FALSE; if (NULL == childEnvp) { #ifdef DARWIN #ifdef HAVE_CRT_EXTERNS_H childEnvp = *(_NSGetEnviron()); #else /* _NSGetEnviron() is not available on iOS. */ PR_DELETE(process); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; #endif #else childEnvp = environ; #endif } for (nEnv = 0; childEnvp[nEnv]; nEnv++) { } newEnvp = (char **) PR_MALLOC((nEnv + 2) * sizeof(char *)); if (NULL == newEnvp) { PR_DELETE(process); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } for (idx = 0; idx < nEnv; idx++) { newEnvp[idx] = childEnvp[idx]; if (!found && !strncmp(newEnvp[idx], "NSPR_INHERIT_FDS=", 17)) { newEnvp[idx] = attr->fdInheritBuffer; found = PR_TRUE; } } if (!found) { newEnvp[idx++] = attr->fdInheritBuffer; } newEnvp[idx] = NULL; childEnvp = newEnvp; } #ifdef AIX process->md.pid = (*pr_wp.forkptr)(); #elif defined(NTO) || defined(SYMBIAN) /* * fork() & exec() does not work in a multithreaded process. * Use spawn() instead. */ { int fd_map[3] = { 0, 1, 2 }; if (attr) { if (attr->stdinFd && attr->stdinFd->secret->md.osfd != 0) { fd_map[0] = dup(attr->stdinFd->secret->md.osfd); flags = fcntl(fd_map[0], F_GETFL, 0); if (flags & O_NONBLOCK) fcntl(fd_map[0], F_SETFL, flags & ~O_NONBLOCK); } if (attr->stdoutFd && attr->stdoutFd->secret->md.osfd != 1) { fd_map[1] = dup(attr->stdoutFd->secret->md.osfd); flags = fcntl(fd_map[1], F_GETFL, 0); if (flags & O_NONBLOCK) fcntl(fd_map[1], F_SETFL, flags & ~O_NONBLOCK); } if (attr->stderrFd && attr->stderrFd->secret->md.osfd != 2) { fd_map[2] = dup(attr->stderrFd->secret->md.osfd); flags = fcntl(fd_map[2], F_GETFL, 0); if (flags & O_NONBLOCK) fcntl(fd_map[2], F_SETFL, flags & ~O_NONBLOCK); } PR_ASSERT(attr->currentDirectory == NULL); /* not implemented */ } #ifdef SYMBIAN /* In Symbian OS, we use posix_spawn instead of fork() and exec() */ posix_spawn(&(process->md.pid), path, NULL, NULL, argv, childEnvp); #else process->md.pid = spawn(path, 3, fd_map, NULL, argv, childEnvp); #endif if (fd_map[0] != 0) close(fd_map[0]); if (fd_map[1] != 1) close(fd_map[1]); if (fd_map[2] != 2) close(fd_map[2]); } #else process->md.pid = fork(); #endif if ((pid_t) -1 == process->md.pid) { PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, errno); PR_DELETE(process); if (newEnvp) { PR_DELETE(newEnvp); } return NULL; } else if (0 == process->md.pid) { /* the child process */ /* * If the child process needs to exit, it must call _exit(). * Do not call exit(), because exit() will flush and close * the standard I/O file descriptors, and hence corrupt * the parent process's standard I/O data structures. */ #if !defined(NTO) && !defined(SYMBIAN) if (attr) { /* the osfd's to redirect stdin, stdout, and stderr to */ int in_osfd = -1, out_osfd = -1, err_osfd = -1; if (attr->stdinFd && attr->stdinFd->secret->md.osfd != 0) { in_osfd = attr->stdinFd->secret->md.osfd; if (dup2(in_osfd, 0) != 0) { _exit(1); /* failed */ } flags = fcntl(0, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(0, F_SETFL, flags & ~O_NONBLOCK); } } if (attr->stdoutFd && attr->stdoutFd->secret->md.osfd != 1) { out_osfd = attr->stdoutFd->secret->md.osfd; if (dup2(out_osfd, 1) != 1) { _exit(1); /* failed */ } flags = fcntl(1, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(1, F_SETFL, flags & ~O_NONBLOCK); } } if (attr->stderrFd && attr->stderrFd->secret->md.osfd != 2) { err_osfd = attr->stderrFd->secret->md.osfd; if (dup2(err_osfd, 2) != 2) { _exit(1); /* failed */ } flags = fcntl(2, F_GETFL, 0); if (flags & O_NONBLOCK) { fcntl(2, F_SETFL, flags & ~O_NONBLOCK); } } if (in_osfd != -1) { close(in_osfd); } if (out_osfd != -1 && out_osfd != in_osfd) { close(out_osfd); } if (err_osfd != -1 && err_osfd != in_osfd && err_osfd != out_osfd) { close(err_osfd); } if (attr->currentDirectory) { if (chdir(attr->currentDirectory) < 0) { _exit(1); /* failed */ } } } if (childEnvp) { (void)execve(path, argv, childEnvp); } else { /* Inherit the environment of the parent. */ (void)execv(path, argv); } /* Whoops! It returned. That's a bad sign. */ _exit(1); #endif /* !NTO */ } if (newEnvp) { PR_DELETE(newEnvp); } #if defined(_PR_NATIVE_THREADS) PR_Lock(pr_wp.ml); if (0 == pr_wp.numProcs++) { PR_NotifyCondVar(pr_wp.cv); } PR_Unlock(pr_wp.ml); #endif return process; } #ifdef _PR_SHARE_CLONES struct pr_CreateProcOp { const char *path; char *const *argv; char *const *envp; const PRProcessAttr *attr; PRProcess *process; PRErrorCode prerror; PRInt32 oserror; PRBool done; PRCondVar *doneCV; struct pr_CreateProcOp *next; }; PRProcess * _MD_CreateUnixProcess( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { struct pr_CreateProcOp *op; PRProcess *proc; int rv; if (PR_CallOnce(&pr_wp.once, _MD_InitProcesses) == PR_FAILURE) { return NULL; } op = PR_NEW(struct pr_CreateProcOp); if (NULL == op) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } op->path = path; op->argv = argv; op->envp = envp; op->attr = attr; op->done = PR_FALSE; op->doneCV = PR_NewCondVar(pr_wp.ml); if (NULL == op->doneCV) { PR_DELETE(op); return NULL; } PR_Lock(pr_wp.ml); /* add to the tail of op queue */ op->next = NULL; if (pr_wp.opTail) { pr_wp.opTail->next = op; pr_wp.opTail = op; } else { PR_ASSERT(NULL == pr_wp.opHead); pr_wp.opHead = pr_wp.opTail = op; } /* wake up the daemon thread */ do { rv = write(pr_wp.pipefd[1], "", 1); } while (-1 == rv && EINTR == errno); while (op->done == PR_FALSE) { PR_WaitCondVar(op->doneCV, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(pr_wp.ml); PR_DestroyCondVar(op->doneCV); proc = op->process; if (!proc) { PR_SetError(op->prerror, op->oserror); } PR_DELETE(op); return proc; } #else /* ! _PR_SHARE_CLONES */ PRProcess * _MD_CreateUnixProcess( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { if (PR_CallOnce(&pr_wp.once, _MD_InitProcesses) == PR_FAILURE) { return NULL; } return ForkAndExec(path, argv, envp, attr); } /* _MD_CreateUnixProcess */ #endif /* _PR_SHARE_CLONES */ /* * The pid table is a hashtable. * * The number of buckets in the hashtable (NBUCKETS) must be a power of 2. */ #define NBUCKETS_LOG2 6 #define NBUCKETS (1 << NBUCKETS_LOG2) #define PID_HASH_MASK ((pid_t) (NBUCKETS - 1)) static pr_PidRecord * FindPidTable(pid_t pid) { pr_PidRecord *pRec; int keyHash = (int) (pid & PID_HASH_MASK); pRec = pr_wp.pidTable[keyHash]; while (pRec) { if (pRec->pid == pid) { break; } pRec = pRec->next; } return pRec; } static void InsertPidTable(pr_PidRecord *pRec) { int keyHash = (int) (pRec->pid & PID_HASH_MASK); pRec->next = pr_wp.pidTable[keyHash]; pr_wp.pidTable[keyHash] = pRec; } static void DeletePidTable(pr_PidRecord *pRec) { int keyHash = (int) (pRec->pid & PID_HASH_MASK); if (pr_wp.pidTable[keyHash] == pRec) { pr_wp.pidTable[keyHash] = pRec->next; } else { pr_PidRecord *pred, *cur; /* predecessor and current */ pred = pr_wp.pidTable[keyHash]; cur = pred->next; while (cur) { if (cur == pRec) { pred->next = cur->next; break; } pred = cur; cur = cur->next; } PR_ASSERT(cur != NULL); } } static int ExtractExitStatus(int rawExitStatus) { /* * We did not specify the WCONTINUED and WUNTRACED options * for waitpid, so these two events should not be reported. */ PR_ASSERT(!WIFSTOPPED(rawExitStatus)); #ifdef WIFCONTINUED PR_ASSERT(!WIFCONTINUED(rawExitStatus)); #endif if (WIFEXITED(rawExitStatus)) { return WEXITSTATUS(rawExitStatus); } else { PR_ASSERT(WIFSIGNALED(rawExitStatus)); return _PR_SIGNALED_EXITSTATUS; } } static void ProcessReapedChildInternal(pid_t pid, int status) { pr_PidRecord *pRec; pRec = FindPidTable(pid); if (NULL == pRec) { pRec = PR_NEW(pr_PidRecord); pRec->pid = pid; pRec->state = _PR_PID_REAPED; pRec->exitStatus = ExtractExitStatus(status); pRec->reapedCV = NULL; InsertPidTable(pRec); } else { PR_ASSERT(pRec->state != _PR_PID_REAPED); if (_PR_PID_DETACHED == pRec->state) { PR_ASSERT(NULL == pRec->reapedCV); DeletePidTable(pRec); PR_DELETE(pRec); } else { PR_ASSERT(_PR_PID_WAITING == pRec->state); PR_ASSERT(NULL != pRec->reapedCV); pRec->exitStatus = ExtractExitStatus(status); pRec->state = _PR_PID_REAPED; PR_NotifyCondVar(pRec->reapedCV); } } } #if defined(_PR_NATIVE_THREADS) /* * If all the threads are native threads, the daemon thread is * simpler. We don't need to catch the SIGCHLD signal. We can * just have the daemon thread block in waitpid(). */ static void WaitPidDaemonThread(void *unused) { pid_t pid; int status; while (1) { PR_Lock(pr_wp.ml); while (0 == pr_wp.numProcs) { PR_WaitCondVar(pr_wp.cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(pr_wp.ml); while (1) { do { pid = waitpid((pid_t) -1, &status, 0); } while ((pid_t) -1 == pid && EINTR == errno); /* * waitpid() cannot return 0 because we did not invoke it * with the WNOHANG option. */ PR_ASSERT(0 != pid); /* * The only possible error code is ECHILD. But if we do * our accounting correctly, we should only call waitpid() * when there is a child process to wait for. */ PR_ASSERT((pid_t) -1 != pid); if ((pid_t) -1 == pid) { break; } PR_Lock(pr_wp.ml); ProcessReapedChildInternal(pid, status); pr_wp.numProcs--; while (0 == pr_wp.numProcs) { PR_WaitCondVar(pr_wp.cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(pr_wp.ml); } } } #else /* _PR_NATIVE_THREADS */ static void WaitPidDaemonThread(void *unused) { PRPollDesc pd; PRFileDesc *fd; int rv; char buf[128]; pid_t pid; int status; #ifdef _PR_SHARE_CLONES struct pr_CreateProcOp *op; #endif #ifdef _PR_SHARE_CLONES pr_InstallSigchldHandler(); #endif fd = PR_ImportFile(pr_wp.pipefd[0]); PR_ASSERT(NULL != fd); pd.fd = fd; pd.in_flags = PR_POLL_READ; while (1) { rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(1 == rv); #ifdef _PR_SHARE_CLONES if (pr_waitpid_daemon_exit) { return; } PR_Lock(pr_wp.ml); #endif do { rv = read(pr_wp.pipefd[0], buf, sizeof(buf)); } while (sizeof(buf) == rv || (-1 == rv && EINTR == errno)); #ifdef _PR_SHARE_CLONES PR_Unlock(pr_wp.ml); while ((op = pr_wp.opHead) != NULL) { op->process = ForkAndExec(op->path, op->argv, op->envp, op->attr); if (NULL == op->process) { op->prerror = PR_GetError(); op->oserror = PR_GetOSError(); } PR_Lock(pr_wp.ml); pr_wp.opHead = op->next; if (NULL == pr_wp.opHead) { pr_wp.opTail = NULL; } op->done = PR_TRUE; PR_NotifyCondVar(op->doneCV); PR_Unlock(pr_wp.ml); } #endif while (1) { do { pid = waitpid((pid_t) -1, &status, WNOHANG); } while ((pid_t) -1 == pid && EINTR == errno); if (0 == pid) break; if ((pid_t) -1 == pid) { /* must be because we have no child processes */ PR_ASSERT(ECHILD == errno); break; } PR_Lock(pr_wp.ml); ProcessReapedChildInternal(pid, status); PR_Unlock(pr_wp.ml); } } } static void pr_SigchldHandler(int sig) { int errnoCopy; int rv; errnoCopy = errno; do { rv = write(pr_wp.pipefd[1], "", 1); } while (-1 == rv && EINTR == errno); #ifdef DEBUG if (-1 == rv && EAGAIN != errno && EWOULDBLOCK != errno) { char *msg = "cannot write to pipe\n"; write(2, msg, strlen(msg) + 1); _exit(1); } #endif errno = errnoCopy; } static void pr_InstallSigchldHandler() { #if defined(HPUX) && defined(_PR_DCETHREADS) #error "HP-UX DCE threads have their own SIGCHLD handler" #endif struct sigaction act, oact; int rv; act.sa_handler = pr_SigchldHandler; sigemptyset(&act.sa_mask); act.sa_flags = SA_NOCLDSTOP | SA_RESTART; rv = sigaction(SIGCHLD, &act, &oact); PR_ASSERT(0 == rv); /* Make sure we are not overriding someone else's SIGCHLD handler */ #ifndef _PR_SHARE_CLONES PR_ASSERT(oact.sa_handler == SIG_DFL); #endif } #endif /* !defined(_PR_NATIVE_THREADS) */ static PRStatus _MD_InitProcesses(void) { #if !defined(_PR_NATIVE_THREADS) int rv; int flags; #endif #ifdef AIX { void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); pr_wp.forkptr = (pid_t (*)(void)) dlsym(handle, "f_fork"); if (!pr_wp.forkptr) { pr_wp.forkptr = fork; } dlclose(handle); } #endif /* AIX */ pr_wp.ml = PR_NewLock(); PR_ASSERT(NULL != pr_wp.ml); #if defined(_PR_NATIVE_THREADS) pr_wp.numProcs = 0; pr_wp.cv = PR_NewCondVar(pr_wp.ml); PR_ASSERT(NULL != pr_wp.cv); #else rv = pipe(pr_wp.pipefd); PR_ASSERT(0 == rv); flags = fcntl(pr_wp.pipefd[0], F_GETFL, 0); fcntl(pr_wp.pipefd[0], F_SETFL, flags | O_NONBLOCK); flags = fcntl(pr_wp.pipefd[1], F_GETFL, 0); fcntl(pr_wp.pipefd[1], F_SETFL, flags | O_NONBLOCK); #ifndef _PR_SHARE_CLONES pr_InstallSigchldHandler(); #endif #endif /* !_PR_NATIVE_THREADS */ pr_wp.thread = PR_CreateThread(PR_SYSTEM_THREAD, WaitPidDaemonThread, NULL, PR_PRIORITY_NORMAL, #ifdef _PR_SHARE_CLONES PR_GLOBAL_THREAD, #else PR_LOCAL_THREAD, #endif PR_JOINABLE_THREAD, 0); PR_ASSERT(NULL != pr_wp.thread); pr_wp.pidTable = (pr_PidRecord**)PR_CALLOC(NBUCKETS * sizeof(pr_PidRecord *)); PR_ASSERT(NULL != pr_wp.pidTable); return PR_SUCCESS; } PRStatus _MD_DetachUnixProcess(PRProcess *process) { PRStatus retVal = PR_SUCCESS; pr_PidRecord *pRec; PR_Lock(pr_wp.ml); pRec = FindPidTable(process->md.pid); if (NULL == pRec) { pRec = PR_NEW(pr_PidRecord); if (NULL == pRec) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); retVal = PR_FAILURE; goto done; } pRec->pid = process->md.pid; pRec->state = _PR_PID_DETACHED; pRec->reapedCV = NULL; InsertPidTable(pRec); } else { PR_ASSERT(_PR_PID_REAPED == pRec->state); if (_PR_PID_REAPED != pRec->state) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); retVal = PR_FAILURE; } else { DeletePidTable(pRec); PR_ASSERT(NULL == pRec->reapedCV); PR_DELETE(pRec); } } PR_DELETE(process); done: PR_Unlock(pr_wp.ml); return retVal; } PRStatus _MD_WaitUnixProcess( PRProcess *process, PRInt32 *exitCode) { pr_PidRecord *pRec; PRStatus retVal = PR_SUCCESS; PRBool interrupted = PR_FALSE; PR_Lock(pr_wp.ml); pRec = FindPidTable(process->md.pid); if (NULL == pRec) { pRec = PR_NEW(pr_PidRecord); if (NULL == pRec) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); retVal = PR_FAILURE; goto done; } pRec->pid = process->md.pid; pRec->state = _PR_PID_WAITING; pRec->reapedCV = PR_NewCondVar(pr_wp.ml); if (NULL == pRec->reapedCV) { PR_DELETE(pRec); retVal = PR_FAILURE; goto done; } InsertPidTable(pRec); while (!interrupted && _PR_PID_REAPED != pRec->state) { if (PR_WaitCondVar(pRec->reapedCV, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE && PR_GetError() == PR_PENDING_INTERRUPT_ERROR) { interrupted = PR_TRUE; } } if (_PR_PID_REAPED == pRec->state) { if (exitCode) { *exitCode = pRec->exitStatus; } } else { PR_ASSERT(interrupted); retVal = PR_FAILURE; } DeletePidTable(pRec); PR_DestroyCondVar(pRec->reapedCV); PR_DELETE(pRec); } else { PR_ASSERT(_PR_PID_REAPED == pRec->state); PR_ASSERT(NULL == pRec->reapedCV); DeletePidTable(pRec); if (exitCode) { *exitCode = pRec->exitStatus; } PR_DELETE(pRec); } PR_DELETE(process); done: PR_Unlock(pr_wp.ml); return retVal; } /* _MD_WaitUnixProcess */ PRStatus _MD_KillUnixProcess(PRProcess *process) { PRErrorCode prerror; PRInt32 oserror; #ifdef SYMBIAN /* In Symbian OS, we can not kill other process with Open C */ PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, oserror); return PR_FAILURE; #else if (kill(process->md.pid, SIGKILL) == 0) { return PR_SUCCESS; } oserror = errno; switch (oserror) { case EPERM: prerror = PR_NO_ACCESS_RIGHTS_ERROR; break; case ESRCH: prerror = PR_INVALID_ARGUMENT_ERROR; break; default: prerror = PR_UNKNOWN_ERROR; break; } PR_SetError(prerror, oserror); return PR_FAILURE; #endif } /* _MD_KillUnixProcess */ nspr-4.11/nspr/pr/src/md/unix/uxrng.c0000644000000000000000000001373312623070344015643 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #include #include #if defined(SOLARIS) static size_t GetHighResClock(void *buf, size_t maxbytes) { hrtime_t t; t = gethrtime(); if (t) { return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t)); } return 0; } #elif defined(HPUX) #ifdef __ia64 #include static size_t GetHighResClock(void *buf, size_t maxbytes) { PRUint64 t; #ifdef __GNUC__ __asm__ __volatile__("mov %0 = ar.itc" : "=r" (t)); #else t = _Asm_mov_from_ar(_AREG44); #endif return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t)); } #else static size_t GetHighResClock(void *buf, size_t maxbytes) { extern int ret_cr16(); int cr16val; cr16val = ret_cr16(); return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val))); } #endif #elif defined(OSF1) #include /* * Use the "get the cycle counter" instruction on the alpha. * The low 32 bits completely turn over in less than a minute. * The high 32 bits are some non-counter gunk that changes sometimes. */ static size_t GetHighResClock(void *buf, size_t maxbytes) { unsigned long t; #ifdef __GNUC__ __asm__("rpcc %0" : "=r" (t)); #else t = asm("rpcc %v0"); #endif return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t)); } #elif defined(AIX) static size_t GetHighResClock(void *buf, size_t maxbytes) { return 0; } #elif (defined(LINUX) || defined(FREEBSD) || defined(__FreeBSD_kernel__) \ || defined(NETBSD) || defined(__NetBSD_kernel__) || defined(OPENBSD) \ || defined(SYMBIAN) || defined(__GNU__)) #include #include #include static int fdDevURandom; static PRCallOnceType coOpenDevURandom; static PRStatus OpenDevURandom( void ) { fdDevURandom = open( "/dev/urandom", O_RDONLY ); return((-1 == fdDevURandom)? PR_FAILURE : PR_SUCCESS ); } /* end OpenDevURandom() */ static size_t GetDevURandom( void *buf, size_t size ) { int bytesIn; int rc; rc = PR_CallOnce( &coOpenDevURandom, OpenDevURandom ); if ( PR_FAILURE == rc ) { _PR_MD_MAP_OPEN_ERROR( errno ); return(0); } bytesIn = read( fdDevURandom, buf, size ); if ( -1 == bytesIn ) { _PR_MD_MAP_READ_ERROR( errno ); return(0); } return( bytesIn ); } /* end GetDevURandom() */ static size_t GetHighResClock(void *buf, size_t maxbytes) { return(GetDevURandom( buf, maxbytes )); } #elif defined(IRIX) #include #undef PRIVATE #include #include #include #include #include static size_t GetHighResClock(void *buf, size_t maxbuf) { unsigned phys_addr, raddr, cycleval; static volatile unsigned *iotimer_addr = NULL; static int tries = 0; static int cntr_size; int mfd; unsigned s0[2]; #ifndef SGI_CYCLECNTR_SIZE #define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */ #endif if (iotimer_addr == NULL) { if (tries++ > 1) { /* Don't keep trying if it didn't work */ return 0; } /* ** For SGI machines we can use the cycle counter, if it has one, ** to generate some truly random numbers */ phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval); if (phys_addr) { int pgsz = getpagesize(); int pgoffmask = pgsz - 1; raddr = phys_addr & ~pgoffmask; mfd = open("/dev/mmem", O_RDONLY); if (mfd < 0) { return 0; } iotimer_addr = (unsigned *) mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr); if (iotimer_addr == (unsigned*)-1) { close(mfd); iotimer_addr = NULL; return 0; } iotimer_addr = (unsigned*) ((__psint_t)iotimer_addr | (phys_addr & pgoffmask)); /* * The file 'mfd' is purposefully not closed. */ cntr_size = syssgi(SGI_CYCLECNTR_SIZE); if (cntr_size < 0) { struct utsname utsinfo; /* * We must be executing on a 6.0 or earlier system, since the * SGI_CYCLECNTR_SIZE call is not supported. * * The only pre-6.1 platforms with 64-bit counters are * IP19 and IP21 (Challenge, PowerChallenge, Onyx). */ uname(&utsinfo); if (!strncmp(utsinfo.machine, "IP19", 4) || !strncmp(utsinfo.machine, "IP21", 4)) cntr_size = 64; else cntr_size = 32; } cntr_size /= 8; /* Convert from bits to bytes */ } } s0[0] = *iotimer_addr; if (cntr_size > 4) s0[1] = *(iotimer_addr + 1); memcpy(buf, (char *)&s0[0], cntr_size); return _pr_CopyLowBits(buf, maxbuf, &s0, cntr_size); } #elif defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(NTO) \ || defined(QNX) || defined(DARWIN) || defined(RISCOS) #include static size_t GetHighResClock(void *buf, size_t maxbytes) { int ticks; struct tms buffer; ticks=times(&buffer); return _pr_CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks)); } #else #error! Platform undefined #endif /* defined(SOLARIS) */ extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size ) { struct timeval tv; int n = 0; int s; n += GetHighResClock(buf, size); size -= n; GETTIMEOFDAY(&tv); if ( size > 0 ) { s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec)); size -= s; n += s; } if ( size > 0 ) { s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec)); size -= s; n += s; } return n; } /* end _PR_MD_GetRandomNoise() */ nspr-4.11/nspr/pr/src/md/unix/uxshm.c0000644000000000000000000004431012623070344015637 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** uxshm.c -- Unix Implementations NSPR Named Shared Memory ** ** ** lth. Jul-1999. ** */ #include #include #include #include #include "primpl.h" #include extern PRLogModuleInfo *_pr_shm_lm; #define NSPR_IPC_SHM_KEY 'b' /* ** Implementation for System V */ #if defined PR_HAVE_SYSV_NAMED_SHARED_MEMORY #include #include #include #include #define _MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory #define _MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory #define _MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory #define _MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory #define _MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory extern PRSharedMemory * _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ) { PRStatus rc = PR_SUCCESS; key_t key; PRSharedMemory *shm; char ipcname[PR_IPC_NAME_SIZE]; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name )); return( NULL ); } shm = PR_NEWZAP( PRSharedMemory ); if ( NULL == shm ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory")); return( NULL ); } shm->ipcname = (char*)PR_MALLOC( strlen( ipcname ) + 1 ); if ( NULL == shm->ipcname ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory")); PR_DELETE( shm ); return( NULL ); } /* copy args to struct */ strcpy( shm->ipcname, ipcname ); shm->size = size; shm->mode = mode; shm->flags = flags; shm->ident = _PR_SHM_IDENT; /* create the file first */ if ( flags & PR_SHM_CREATE ) { int osfd = open( shm->ipcname, (O_RDWR | O_CREAT), shm->mode ); if ( -1 == osfd ) { _PR_MD_MAP_OPEN_ERROR( errno ); PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return( NULL ); } if ( close(osfd) == -1 ) { _PR_MD_MAP_CLOSE_ERROR( errno ); PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return( NULL ); } } /* hash the shm.name to an ID */ key = ftok( shm->ipcname, NSPR_IPC_SHM_KEY ); if ( -1 == key ) { rc = PR_FAILURE; _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): ftok() failed on name: %s", shm->ipcname)); PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return( NULL ); } /* get the shared memory */ if ( flags & PR_SHM_CREATE ) { shm->id = shmget( key, shm->size, ( shm->mode | IPC_CREAT|IPC_EXCL)); if ( shm->id >= 0 ) { return( shm ); } if ((errno == EEXIST) && (flags & PR_SHM_EXCL)) { PR_SetError( PR_FILE_EXISTS_ERROR, errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): shmget() exclusive failed, errno: %d", errno)); PR_FREEIF(shm->ipcname); PR_DELETE(shm); return(NULL); } } shm->id = shmget( key, shm->size, shm->mode ); if ( -1 == shm->id ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): shmget() failed, errno: %d", errno)); PR_FREEIF(shm->ipcname); PR_DELETE(shm); return(NULL); } return( shm ); } /* end _MD_OpenSharedMemory() */ extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ) { void *addr; PRUint32 aFlags = shm->mode; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); aFlags |= (flags & PR_SHM_READONLY )? SHM_RDONLY : 0; addr = shmat( shm->id, NULL, aFlags ); if ( (void*)-1 == addr ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_AttachSharedMemory(): shmat() failed on name: %s, OsError: %d", shm->ipcname, PR_GetOSError() )); addr = NULL; } return addr; } extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ) { PRStatus rc = PR_SUCCESS; PRIntn urc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); urc = shmdt( addr ); if ( -1 == urc ) { rc = PR_FAILURE; _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DetachSharedMemory(): shmdt() failed on name: %s", shm->ipcname )); } return rc; } extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ) { PR_ASSERT( shm->ident == _PR_SHM_IDENT ); PR_FREEIF(shm->ipcname); PR_DELETE(shm); return PR_SUCCESS; } extern PRStatus _MD_DeleteSharedMemory( const char *name ) { PRStatus rc = PR_SUCCESS; key_t key; int id; PRIntn urc; char ipcname[PR_IPC_NAME_SIZE]; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) { PR_SetError( PR_UNKNOWN_ERROR , errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name )); return(PR_FAILURE); } /* create the file first */ { int osfd = open( ipcname, (O_RDWR | O_CREAT), 0666 ); if ( -1 == osfd ) { _PR_MD_MAP_OPEN_ERROR( errno ); return( PR_FAILURE ); } if ( close(osfd) == -1 ) { _PR_MD_MAP_CLOSE_ERROR( errno ); return( PR_FAILURE ); } } /* hash the shm.name to an ID */ key = ftok( ipcname, NSPR_IPC_SHM_KEY ); if ( -1 == key ) { rc = PR_FAILURE; _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): ftok() failed on name: %s", ipcname)); } #ifdef SYMBIAN /* In Symbian OS the system imposed minimum is 1 byte, instead of ZERO */ id = shmget( key, 1, 0 ); #else id = shmget( key, 0, 0 ); #endif if ( -1 == id ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): shmget() failed, errno: %d", errno)); return(PR_FAILURE); } urc = shmctl( id, IPC_RMID, NULL ); if ( -1 == urc ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): shmctl() failed on name: %s", ipcname )); return(PR_FAILURE); } urc = unlink( ipcname ); if ( -1 == urc ) { _PR_MD_MAP_UNLINK_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): unlink() failed: %s", ipcname )); return(PR_FAILURE); } return rc; } /* end _MD_DeleteSharedMemory() */ /* ** Implementation for Posix */ #elif defined PR_HAVE_POSIX_NAMED_SHARED_MEMORY #include #define _MD_OPEN_SHARED_MEMORY _MD_OpenSharedMemory #define _MD_ATTACH_SHARED_MEMORY _MD_AttachSharedMemory #define _MD_DETACH_SHARED_MEMORY _MD_DetachSharedMemory #define _MD_CLOSE_SHARED_MEMORY _MD_CloseSharedMemory #define _MD_DELETE_SHARED_MEMORY _MD_DeleteSharedMemory struct _MDSharedMemory { int handle; }; extern PRSharedMemory * _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ) { PRStatus rc = PR_SUCCESS; PRInt32 end; PRSharedMemory *shm; char ipcname[PR_IPC_NAME_SIZE]; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) { PR_SetError( PR_UNKNOWN_ERROR , errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name )); return( NULL ); } shm = PR_NEWZAP( PRSharedMemory ); if ( NULL == shm ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory")); return( NULL ); } shm->ipcname = PR_MALLOC( strlen( ipcname ) + 1 ); if ( NULL == shm->ipcname ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory")); return( NULL ); } /* copy args to struct */ strcpy( shm->ipcname, ipcname ); shm->size = size; shm->mode = mode; shm->flags = flags; shm->ident = _PR_SHM_IDENT; /* ** Create the shared memory */ if ( flags & PR_SHM_CREATE ) { int oflag = (O_CREAT | O_RDWR); if ( flags & PR_SHM_EXCL ) oflag |= O_EXCL; shm->id = shm_open( shm->ipcname, oflag, shm->mode ); } else { shm->id = shm_open( shm->ipcname, O_RDWR, shm->mode ); } if ( -1 == shm->id ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): shm_open failed: %s, OSError: %d", shm->ipcname, PR_GetOSError())); PR_DELETE( shm->ipcname ); PR_DELETE( shm ); return(NULL); } end = ftruncate( shm->id, shm->size ); if ( -1 == end ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): ftruncate failed, OSError: %d", PR_GetOSError())); PR_DELETE( shm->ipcname ); PR_DELETE( shm ); return(NULL); } return(shm); } /* end _MD_OpenSharedMemory() */ extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ) { void *addr; PRIntn prot = (PROT_READ | PROT_WRITE); PR_ASSERT( shm->ident == _PR_SHM_IDENT ); if ( PR_SHM_READONLY == flags) prot ^= PROT_WRITE; addr = mmap( (void*)0, shm->size, prot, MAP_SHARED, shm->id, 0 ); if ((void*)-1 == addr ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_AttachSharedMemory(): mmap failed: %s, errno: %d", shm->ipcname, PR_GetOSError())); addr = NULL; } else { PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_AttachSharedMemory(): name: %s, attached at: %p", shm->ipcname, addr)); } return addr; } extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ) { PRStatus rc = PR_SUCCESS; PRIntn urc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); urc = munmap( addr, shm->size ); if ( -1 == urc ) { rc = PR_FAILURE; _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DetachSharedMemory(): munmap failed: %s, errno: %d", shm->ipcname, PR_GetOSError())); } return rc; } extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ) { int urc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); urc = close( shm->id ); if ( -1 == urc ) { _PR_MD_MAP_CLOSE_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_CloseSharedMemory(): close() failed, error: %d", PR_GetOSError())); return(PR_FAILURE); } PR_DELETE( shm->ipcname ); PR_DELETE( shm ); return PR_SUCCESS; } extern PRStatus _MD_DeleteSharedMemory( const char *name ) { PRStatus rc = PR_SUCCESS; PRUintn urc; char ipcname[PR_IPC_NAME_SIZE]; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) { PR_SetError( PR_UNKNOWN_ERROR , errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_OpenSharedMemory(): _PR_MakeNativeIPCName() failed: %s", name )); return rc; } urc = shm_unlink( ipcname ); if ( -1 == urc ) { rc = PR_FAILURE; _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): shm_unlink failed: %s, errno: %d", ipcname, PR_GetOSError())); } else { PR_LOG( _pr_shm_lm, PR_LOG_DEBUG, ("_MD_DeleteSharedMemory(): %s, success", ipcname)); } return rc; } /* end _MD_DeleteSharedMemory() */ #endif /* ** Unix implementation for anonymous memory (file) mapping */ extern PRLogModuleInfo *_pr_shma_lm; #include extern PRFileMap* _md_OpenAnonFileMap( const char *dirName, PRSize size, PRFileMapProtect prot ) { PRFileMap *fm = NULL; PRFileDesc *fd; int osfd; PRIntn urc; PRIntn mode = 0600; char *genName; pid_t pid = getpid(); /* for generating filename */ PRThread *tid = PR_GetCurrentThread(); /* for generating filename */ int incr; /* for generating filename */ const int maxTries = 20; /* maximum # attempts at a unique filename */ PRInt64 size64; /* 64-bit version of 'size' */ /* ** generate a filename from input and runtime environment ** open the file, unlink the file. ** make maxTries number of attempts at uniqueness in the filename */ for ( incr = 0; incr < maxTries ; incr++ ) { #if defined(SYMBIAN) #define NSPR_AFM_FILENAME "%s\\NSPR-AFM-%d-%p.%d" #else #define NSPR_AFM_FILENAME "%s/.NSPR-AFM-%d-%p.%d" #endif genName = PR_smprintf( NSPR_AFM_FILENAME, dirName, (int) pid, tid, incr ); if ( NULL == genName ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): PR_snprintf(): failed, generating filename")); goto Finished; } /* create the file */ osfd = open( genName, (O_CREAT | O_EXCL | O_RDWR), mode ); if ( -1 == osfd ) { if ( EEXIST == errno ) { PR_smprintf_free( genName ); continue; /* name exists, try again */ } else { _PR_MD_MAP_OPEN_ERROR( errno ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): open(): failed, filename: %s, errno: %d", genName, PR_GetOSError())); PR_smprintf_free( genName ); goto Finished; } } break; /* name generation and open successful, break; */ } /* end for() */ if ( incr == maxTries ) { PR_ASSERT( -1 == osfd ); PR_ASSERT( EEXIST == errno ); _PR_MD_MAP_OPEN_ERROR( errno ); goto Finished; } urc = unlink( genName ); #if defined(SYMBIAN) && defined(__WINS__) /* If it is being used by the system or another process, Symbian OS * Emulator(WINS) considers this an error. */ if ( -1 == urc && EACCES != errno ) { #else if ( -1 == urc ) { #endif _PR_MD_MAP_UNLINK_ERROR( errno ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): failed on unlink(), errno: %d", errno)); PR_smprintf_free( genName ); close( osfd ); goto Finished; } PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): unlink(): %s", genName )); PR_smprintf_free( genName ); fd = PR_ImportFile( osfd ); if ( NULL == fd ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): PR_ImportFile(): failed")); goto Finished; } PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): fd: %p", fd )); urc = ftruncate( fd->secret->md.osfd, size ); if ( -1 == urc ) { _PR_MD_MAP_DEFAULT_ERROR( errno ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): failed on ftruncate(), errno: %d", errno)); PR_Close( fd ); goto Finished; } PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): ftruncate(): size: %d", size )); LL_UI2L(size64, size); /* PRSize (size_t) is unsigned */ fm = PR_CreateFileMap( fd, size64, prot ); if ( NULL == fm ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("PR_OpenAnonFileMap(): failed")); PR_Close( fd ); goto Finished; } fm->md.isAnonFM = PR_TRUE; /* set fd close */ PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): PR_CreateFileMap(): fm: %p", fm )); Finished: return(fm); } /* end md_OpenAnonFileMap() */ /* ** _md_ExportFileMapAsString() ** ** */ extern PRStatus _md_ExportFileMapAsString( PRFileMap *fm, PRSize bufSize, char *buf ) { PRIntn written; PRIntn prot = (PRIntn)fm->prot; written = PR_snprintf( buf, bufSize, "%ld:%d", fm->fd->secret->md.osfd, prot ); return((written == -1)? PR_FAILURE : PR_SUCCESS); } /* end _md_ExportFileMapAsString() */ extern PRFileMap * _md_ImportFileMapFromString( const char *fmstring ) { PRStatus rc; PRInt32 osfd; PRIntn prot; /* really: a PRFileMapProtect */ PRFileDesc *fd; PRFileMap *fm = NULL; /* default return value */ PRFileInfo64 info; PR_sscanf( fmstring, "%ld:%d", &osfd, &prot ); /* import the os file descriptor */ fd = PR_ImportFile( osfd ); if ( NULL == fd ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): PR_ImportFile() failed")); goto Finished; } rc = PR_GetOpenFileInfo64( fd, &info ); if ( PR_FAILURE == rc ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): PR_GetOpenFileInfo64() failed")); goto Finished; } fm = PR_CreateFileMap( fd, info.size, (PRFileMapProtect)prot ); if ( NULL == fm ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): PR_CreateFileMap() failed")); } Finished: return(fm); } /* end _md_ImportFileMapFromString() */ nspr-4.11/nspr/pr/src/md/unix/uxwrap.c0000644000000000000000000003553212623070344016027 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* *------------------------------------------------------------------------ * File: uxwrap.c * * Our wrapped versions of the Unix select() and poll() system calls. * *------------------------------------------------------------------------ */ #include "primpl.h" #if defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) || defined(QNX) /* Do not wrap select() and poll(). */ #else /* defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) */ /* The include files for select() */ #ifdef IRIX #include #include #endif #include #include #include #define ZAP_SET(_to, _width) \ PR_BEGIN_MACRO \ memset(_to, 0, \ ((_width + 8*sizeof(int)-1) / (8*sizeof(int))) \ * sizeof(int) \ ); \ PR_END_MACRO /* see comments in ns/cmd/xfe/mozilla.c (look for "PR_XGetXtHackFD") */ static int _pr_xt_hack_fd = -1; int PR_XGetXtHackFD(void) { int fds[2]; if (_pr_xt_hack_fd == -1) { if (!pipe(fds)) { _pr_xt_hack_fd = fds[0]; } } return _pr_xt_hack_fd; } static int (*_pr_xt_hack_okayToReleaseXLock)(void) = 0; void PR_SetXtHackOkayToReleaseXLockFn(int (*fn)(void)) { _pr_xt_hack_okayToReleaseXLock = fn; } /* *----------------------------------------------------------------------- * select() -- * * Wrap up the select system call so that we can deschedule * a thread that tries to wait for i/o. * *----------------------------------------------------------------------- */ #if defined(HPUX9) int select(size_t width, int *rl, int *wl, int *el, const struct timeval *tv) #elif defined(AIX_RENAME_SELECT) int wrap_select(unsigned long width, void *rl, void *wl, void *el, struct timeval *tv) #elif defined(_PR_SELECT_CONST_TIMEVAL) int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, const struct timeval *tv) #else int select(int width, fd_set *rd, fd_set *wr, fd_set *ex, struct timeval *tv) #endif { int osfd; _PRUnixPollDesc *unixpds, *unixpd, *eunixpd; PRInt32 pdcnt; PRIntervalTime timeout; int retVal; #if defined(HPUX9) || defined(AIX_RENAME_SELECT) fd_set *rd = (fd_set*) rl; fd_set *wr = (fd_set*) wl; fd_set *ex = (fd_set*) el; #endif #if 0 /* * Easy special case: zero timeout. Simply call the native * select() with no fear of blocking. */ if (tv != NULL && tv->tv_sec == 0 && tv->tv_usec == 0) { #if defined(HPUX9) || defined(AIX_RENAME_SELECT) return _MD_SELECT(width, rl, wl, el, tv); #else return _MD_SELECT(width, rd, wr, ex, tv); #endif } #endif if (!_pr_initialized) { _PR_ImplicitInitialization(); } #ifndef _PR_LOCAL_THREADS_ONLY if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) { return _MD_SELECT(width, rd, wr, ex, tv); } #endif if (width < 0 || width > FD_SETSIZE) { errno = EINVAL; return -1; } /* Compute timeout */ if (tv) { /* * These acceptable ranges for t_sec and t_usec are taken * from the select() man pages. */ if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) { errno = EINVAL; return -1; } /* Convert microseconds to ticks */ timeout = PR_MicrosecondsToInterval(1000000*tv->tv_sec + tv->tv_usec); } else { /* tv being a NULL pointer means blocking indefinitely */ timeout = PR_INTERVAL_NO_TIMEOUT; } /* Check for no descriptors case (just doing a timeout) */ if ((!rd && !wr && !ex) || !width) { PR_Sleep(timeout); return 0; } /* * Set up for PR_Poll(). The PRPollDesc array is allocated * dynamically. If this turns out to have high performance * penalty, one can change to use a large PRPollDesc array * on the stack, and allocate dynamically only when it turns * out to be not large enough. * * I allocate an array of size 'width', which is the maximum * number of fds we may need to poll. */ unixpds = (_PRUnixPollDesc *) PR_CALLOC(width * sizeof(_PRUnixPollDesc)); if (!unixpds) { errno = ENOMEM; return -1; } pdcnt = 0; unixpd = unixpds; for (osfd = 0; osfd < width; osfd++) { int in_flags = 0; if (rd && FD_ISSET(osfd, rd)) { in_flags |= _PR_UNIX_POLL_READ; } if (wr && FD_ISSET(osfd, wr)) { in_flags |= _PR_UNIX_POLL_WRITE; } if (ex && FD_ISSET(osfd, ex)) { in_flags |= _PR_UNIX_POLL_EXCEPT; } if (in_flags) { unixpd->osfd = osfd; unixpd->in_flags = in_flags; unixpd->out_flags = 0; unixpd++; pdcnt++; } } /* * see comments in mozilla/cmd/xfe/mozilla.c (look for * "PR_XGetXtHackFD") */ { int needToLockXAgain; needToLockXAgain = 0; if (rd && (_pr_xt_hack_fd != -1) && FD_ISSET(_pr_xt_hack_fd, rd) && PR_XIsLocked() && (!_pr_xt_hack_okayToReleaseXLock || _pr_xt_hack_okayToReleaseXLock())) { PR_XUnlock(); needToLockXAgain = 1; } /* This is the potentially blocking step */ retVal = _PR_WaitForMultipleFDs(unixpds, pdcnt, timeout); if (needToLockXAgain) { PR_XLock(); } } if (retVal > 0) { /* Compute select results */ if (rd) ZAP_SET(rd, width); if (wr) ZAP_SET(wr, width); if (ex) ZAP_SET(ex, width); /* * The return value can be either the number of ready file * descriptors or the number of set bits in the three fd_set's. */ retVal = 0; /* we're going to recompute */ eunixpd = unixpds + pdcnt; for (unixpd = unixpds; unixpd < eunixpd; unixpd++) { if (unixpd->out_flags) { int nbits = 0; /* The number of set bits on for this fd */ if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) { errno = EBADF; PR_LOG(_pr_io_lm, PR_LOG_ERROR, ("select returns EBADF for %d", unixpd->osfd)); retVal = -1; break; } /* * If a socket has a pending error, it is considered * both readable and writable. (See W. Richard Stevens, * Unix Network Programming, Vol. 1, 2nd Ed., Section 6.3, * pp. 153-154.) We also consider a socket readable if * it has a hangup condition. */ if (rd && (unixpd->in_flags & _PR_UNIX_POLL_READ) && (unixpd->out_flags & (_PR_UNIX_POLL_READ | _PR_UNIX_POLL_ERR | _PR_UNIX_POLL_HUP))) { FD_SET(unixpd->osfd, rd); nbits++; } if (wr && (unixpd->in_flags & _PR_UNIX_POLL_WRITE) && (unixpd->out_flags & (_PR_UNIX_POLL_WRITE | _PR_UNIX_POLL_ERR))) { FD_SET(unixpd->osfd, wr); nbits++; } if (ex && (unixpd->in_flags & _PR_UNIX_POLL_WRITE) && (unixpd->out_flags & PR_POLL_EXCEPT)) { FD_SET(unixpd->osfd, ex); nbits++; } PR_ASSERT(nbits > 0); #if defined(HPUX) || defined(SOLARIS) || defined(OSF1) || defined(AIX) retVal += nbits; #else /* IRIX */ retVal += 1; #endif } } } PR_ASSERT(tv || retVal != 0); PR_LOG(_pr_io_lm, PR_LOG_MIN, ("select returns %d", retVal)); PR_DELETE(unixpds); return retVal; } /* * Redefine poll, when supported on platforms, for local threads */ /* * I am commenting out the poll() wrapper for Linux for now * because it is difficult to define _MD_POLL that works on all * Linux varieties. People reported that glibc 2.0.7 on Debian * 2.0 Linux machines doesn't have the __syscall_poll symbol * defined. (WTC 30 Nov. 1998) */ #if defined(_PR_POLL_AVAILABLE) && !defined(LINUX) /* *----------------------------------------------------------------------- * poll() -- * * RETURN VALUES: * -1: fails, errno indicates the error. * 0: timed out, the revents bitmasks are not set. * positive value: the number of file descriptors for which poll() * has set the revents bitmask. * *----------------------------------------------------------------------- */ #include #if defined(AIX_RENAME_SELECT) int wrap_poll(void *listptr, unsigned long nfds, long timeout) #elif (defined(AIX) && !defined(AIX_RENAME_SELECT)) int poll(void *listptr, unsigned long nfds, long timeout) #elif defined(OSF1) || (defined(HPUX) && !defined(HPUX9)) int poll(struct pollfd filedes[], unsigned int nfds, int timeout) #elif defined(HPUX9) int poll(struct pollfd filedes[], int nfds, int timeout) #elif defined(NETBSD) int poll(struct pollfd *filedes, nfds_t nfds, int timeout) #elif defined(OPENBSD) int poll(struct pollfd filedes[], nfds_t nfds, int timeout) #elif defined(FREEBSD) int poll(struct pollfd *filedes, unsigned nfds, int timeout) #else int poll(struct pollfd *filedes, unsigned long nfds, int timeout) #endif { #ifdef AIX struct pollfd *filedes = (struct pollfd *) listptr; #endif struct pollfd *pfd, *epfd; _PRUnixPollDesc *unixpds, *unixpd, *eunixpd; PRIntervalTime ticks; PRInt32 pdcnt; int ready; /* * Easy special case: zero timeout. Simply call the native * poll() with no fear of blocking. */ if (timeout == 0) { #if defined(AIX) return _MD_POLL(listptr, nfds, timeout); #else return _MD_POLL(filedes, nfds, timeout); #endif } if (!_pr_initialized) { _PR_ImplicitInitialization(); } #ifndef _PR_LOCAL_THREADS_ONLY if (_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) { return _MD_POLL(filedes, nfds, timeout); } #endif /* We do not support the pollmsg structures on AIX */ #ifdef AIX PR_ASSERT((nfds & 0xff00) == 0); #endif if (timeout < 0 && timeout != -1) { errno = EINVAL; return -1; } /* Convert timeout from miliseconds to ticks */ if (timeout == -1) { ticks = PR_INTERVAL_NO_TIMEOUT; } else { ticks = PR_MillisecondsToInterval(timeout); } /* Check for no descriptor case (just do a timeout) */ if (nfds == 0) { PR_Sleep(ticks); return 0; } unixpds = (_PRUnixPollDesc *) PR_MALLOC(nfds * sizeof(_PRUnixPollDesc)); if (NULL == unixpds) { errno = EAGAIN; return -1; } pdcnt = 0; epfd = filedes + nfds; unixpd = unixpds; for (pfd = filedes; pfd < epfd; pfd++) { /* * poll() ignores negative fd's. */ if (pfd->fd >= 0) { unixpd->osfd = pfd->fd; #ifdef _PR_USE_POLL unixpd->in_flags = pfd->events; #else /* * Map the poll events to one of the three that can be * represented by the select fd_sets: * POLLIN, POLLRDNORM ===> readable * POLLOUT, POLLWRNORM ===> writable * POLLPRI, POLLRDBAND ===> exception * POLLNORM, POLLWRBAND (and POLLMSG on some platforms) * are ignored. * * The output events POLLERR and POLLHUP are never turned on. * POLLNVAL may be turned on. */ unixpd->in_flags = 0; if (pfd->events & (POLLIN #ifdef POLLRDNORM | POLLRDNORM #endif )) { unixpd->in_flags |= _PR_UNIX_POLL_READ; } if (pfd->events & (POLLOUT #ifdef POLLWRNORM | POLLWRNORM #endif )) { unixpd->in_flags |= _PR_UNIX_POLL_WRITE; } if (pfd->events & (POLLPRI #ifdef POLLRDBAND | POLLRDBAND #endif )) { unixpd->in_flags |= PR_POLL_EXCEPT; } #endif /* _PR_USE_POLL */ unixpd->out_flags = 0; unixpd++; pdcnt++; } } ready = _PR_WaitForMultipleFDs(unixpds, pdcnt, ticks); if (-1 == ready) { if (PR_GetError() == PR_PENDING_INTERRUPT_ERROR) { errno = EINTR; /* XXX we aren't interrupted by a signal, but... */ } else { errno = PR_GetOSError(); } } if (ready <= 0) { goto done; } /* * Copy the out_flags from the _PRUnixPollDesc structures to the * user's pollfd structures and free the allocated memory */ unixpd = unixpds; for (pfd = filedes; pfd < epfd; pfd++) { pfd->revents = 0; if (pfd->fd >= 0) { #ifdef _PR_USE_POLL pfd->revents = unixpd->out_flags; #else if (0 != unixpd->out_flags) { if (unixpd->out_flags & _PR_UNIX_POLL_READ) { if (pfd->events & POLLIN) { pfd->revents |= POLLIN; } #ifdef POLLRDNORM if (pfd->events & POLLRDNORM) { pfd->revents |= POLLRDNORM; } #endif } if (unixpd->out_flags & _PR_UNIX_POLL_WRITE) { if (pfd->events & POLLOUT) { pfd->revents |= POLLOUT; } #ifdef POLLWRNORM if (pfd->events & POLLWRNORM) { pfd->revents |= POLLWRNORM; } #endif } if (unixpd->out_flags & _PR_UNIX_POLL_EXCEPT) { if (pfd->events & POLLPRI) { pfd->revents |= POLLPRI; } #ifdef POLLRDBAND if (pfd->events & POLLRDBAND) { pfd->revents |= POLLRDBAND; } #endif } if (unixpd->out_flags & _PR_UNIX_POLL_ERR) { pfd->revents |= POLLERR; } if (unixpd->out_flags & _PR_UNIX_POLL_NVAL) { pfd->revents |= POLLNVAL; } if (unixpd->out_flags & _PR_UNIX_POLL_HUP) { pfd->revents |= POLLHUP; } } #endif /* _PR_USE_POLL */ unixpd++; } } done: PR_DELETE(unixpds); return ready; } #endif /* !defined(LINUX) */ #endif /* defined(_PR_PTHREADS) || defined(_PR_GLOBAL_THREADS_ONLY) */ /* uxwrap.c */ nspr-4.11/nspr/pr/src/md/windows/.cvsignore0000644000000000000000000000001112623070344017024 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/md/windows/Makefile.in0000644000000000000000000000254312623070344017105 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifeq (,$(filter-out WIN95 WINCE WINMO, $(OS_TARGET))) CSRCS = \ ntmisc.c \ ntsec.c \ ntsem.c \ ntinrval.c \ ntgc.c \ w95thred.c \ w95io.c \ w95cv.c \ w32rng.c \ w95sock.c \ win32_errors.c \ w32ipcsem.c \ w32poll.c \ w32shm.c \ w95dllmain.c \ $(NULL) else CSRCS = \ ntdllmn.c \ ntmisc.c \ ntsec.c \ ntsem.c \ ntinrval.c \ ntgc.c \ ntthread.c \ ntio.c \ win32_errors.c \ w32ipcsem.c \ w32poll.c \ w32rng.c \ w32shm.c \ $(NULL) endif TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) # Bug 122433 workaround: disable global optimization (-Og-) on ntio.c. ifdef MOZ_OPTIMIZE ifeq ($(OS_TARGET), WINNT) ifndef NS_USE_GCC $(OBJDIR)/ntio.$(OBJ_SUFFIX): ntio.c @$(MAKE_OBJDIR) $(CC) -Fo$@ -c $(CFLAGS) -Og- $< endif endif endif nspr-4.11/nspr/pr/src/md/windows/ntdllmn.c0000644000000000000000000000336712623070344016661 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * The DLL entry point (DllMain) for NSPR. * * The only reason we use DLLMain() now is to find out whether * the NSPR DLL is statically or dynamically loaded. When * dynamically loaded, we cannot use static thread-local storage. * However, static TLS is faster than the TlsXXX() functions. * So we want to use static TLS whenever we can. A global * variable _pr_use_static_tls is set in DllMain() during process * attachment to indicate whether it is safe to use static TLS * or not. */ #include #include extern BOOL _pr_use_static_tls; /* defined in ntthread.c */ BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { PRThread *me; switch (fdwReason) { case DLL_PROCESS_ATTACH: /* * If lpvReserved is NULL, we are dynamically loaded * and therefore can't use static thread-local storage. */ if (lpvReserved == NULL) { _pr_use_static_tls = FALSE; } else { _pr_use_static_tls = TRUE; } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: if (_pr_initialized) { me = _MD_GET_ATTACHED_THREAD(); if ((me != NULL) && (me->flags & _PR_ATTACHED)) _PRI_DetachThread(); } break; case DLL_PROCESS_DETACH: break; } return TRUE; } nspr-4.11/nspr/pr/src/md/windows/ntgc.c0000644000000000000000000000615012623070344016135 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * GC related routines * */ #include #include "primpl.h" PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) { #if defined(_X86_) CONTEXT context; context.ContextFlags = CONTEXT_INTEGER; if (_PR_IS_NATIVE_THREAD(t)) { context.ContextFlags |= CONTEXT_CONTROL; if (GetThreadContext(t->md.handle, &context)) { t->md.gcContext[0] = context.Eax; t->md.gcContext[1] = context.Ebx; t->md.gcContext[2] = context.Ecx; t->md.gcContext[3] = context.Edx; t->md.gcContext[4] = context.Esi; t->md.gcContext[5] = context.Edi; t->md.gcContext[6] = context.Esp; t->md.gcContext[7] = context.Ebp; *np = PR_NUM_GCREGS; } else { PR_ASSERT(0);/* XXX */ } } else { /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING * * This code is extremely machine dependant and completely * undocumented by MS. Its only known to work experimentally. * Ready for a walk on the wild * side? * * WARNING WARNING WARNING WARNING WARNING WARNING WARNING */ #if !defined WIN95 // Win95 does not have fibers int *fiberData = t->md.fiber_id; /* I found these offsets by disassembling SwitchToFiber(). * Are your palms sweating yet? */ /* ** EAX is on the stack (ESP+0) ** EDX is on the stack (ESP+4) ** ECX is on the stack (ESP+8) */ t->md.gcContext[0] = 0; /* context.Eax */ t->md.gcContext[1] = fiberData[0x2e]; /* context.Ebx */ t->md.gcContext[2] = 0; /* context.Ecx */ t->md.gcContext[3] = 0; /* context.Edx */ t->md.gcContext[4] = fiberData[0x2d]; /* context.Esi */ t->md.gcContext[5] = fiberData[0x2c]; /* context.Edi */ t->md.gcContext[6] = fiberData[0x36]; /* context.Esp */ t->md.gcContext[7] = fiberData[0x32]; /* context.Ebp */ *np = PR_NUM_GCREGS; #endif } return (PRWord *)&t->md.gcContext; #else PR_NOT_REACHED("not implemented"); return NULL; #endif /* defined(_X86_) */ } /* This function is not used right now, but is left as a reference. * If you ever need to get the fiberID from the currently running fiber, * this is it. */ void * GetMyFiberID() { #if defined(_X86_) && !defined(__MINGW32__) void *fiberData; /* A pointer to our tib entry is found at FS:[18] * At offset 10h is the fiberData pointer. The context of the * fiber is stored in there. */ __asm { mov EDX, FS:[18h] mov EAX, DWORD PTR [EDX+10h] mov [fiberData], EAX } return fiberData; #else PR_NOT_REACHED("not implemented"); return NULL; #endif /* defined(_X86_) */ } nspr-4.11/nspr/pr/src/md/windows/ntinrval.c0000644000000000000000000000177012623070344017042 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * NT interval timers * */ #include "primpl.h" #ifdef WINCE typedef DWORD (*IntervalFuncType)(void); static IntervalFuncType intervalFunc; #endif void _PR_MD_INTERVAL_INIT() { #ifdef WINCE HMODULE mmtimerlib = LoadLibraryW(L"mmtimer.dll"); /* XXX leaked! */ if (mmtimerlib) { intervalFunc = (IntervalFuncType)GetProcAddress(mmtimerlib, "timeGetTime"); } else { intervalFunc = &GetTickCount; } #endif } PRIntervalTime _PR_MD_GET_INTERVAL() { /* milliseconds since system start */ #ifdef WINCE return (*intervalFunc)(); #else return timeGetTime(); #endif } PRIntervalTime _PR_MD_INTERVAL_PER_SEC() { return 1000; } nspr-4.11/nspr/pr/src/md/windows/ntio.c0000644000000000000000000042236512623070344016165 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Windows NT IO module * * This module handles IO for LOCAL_SCOPE and GLOBAL_SCOPE threads. * For LOCAL_SCOPE threads, we're using NT fibers. For GLOBAL_SCOPE threads * we're using NT-native threads. * * When doing IO, we want to use completion ports for optimal performance * with fibers. But if we use completion ports for all IO, it is difficult * to project a blocking model with GLOBAL_SCOPE threads. To handle this * we create an extra thread for completing IO for GLOBAL_SCOPE threads. * We don't really want to complete IO on a separate thread for LOCAL_SCOPE * threads because it means extra context switches, which are really slow * on NT... Since we're using a single completion port, some IO will * be incorrectly completed on the GLOBAL_SCOPE IO thread; this will mean * extra context switching; but I don't think there is anything I can do * about it. */ #include "primpl.h" #include "pprmwait.h" #include #include static HANDLE _pr_completion_port; static PRThread *_pr_io_completion_thread; #define RECYCLE_SIZE 512 static struct _MDLock _pr_recycle_lock; static PRInt32 _pr_recycle_INET_array[RECYCLE_SIZE]; static PRInt32 _pr_recycle_INET_tail = 0; static PRInt32 _pr_recycle_INET6_array[RECYCLE_SIZE]; static PRInt32 _pr_recycle_INET6_tail = 0; __declspec(thread) PRThread *_pr_io_restarted_io = NULL; DWORD _pr_io_restartedIOIndex; /* The thread local storage slot for each * thread is initialized to NULL. */ PRBool _nt_version_gets_lockfile_completion; struct _MDLock _pr_ioq_lock; extern _MDLock _nt_idleLock; extern PRCList _nt_idleList; extern PRUint32 _nt_idleCount; #define CLOSE_TIMEOUT PR_SecondsToInterval(5) /* * NSPR-to-NT access right mapping table for files. */ static DWORD fileAccessTable[] = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE }; /* * NSPR-to-NT access right mapping table for directories. */ static DWORD dirAccessTable[] = { FILE_GENERIC_READ, FILE_GENERIC_WRITE|FILE_DELETE_CHILD, FILE_GENERIC_EXECUTE }; static PRBool IsPrevCharSlash(const char *str, const char *current); #define _NEED_351_FILE_LOCKING_HACK #ifdef _NEED_351_FILE_LOCKING_HACK #define _PR_LOCAL_FILE 1 #define _PR_REMOTE_FILE 2 PRBool IsFileLocalInit(); PRInt32 IsFileLocal(HANDLE hFile); #endif /* _NEED_351_FILE_LOCKING_HACK */ static PRInt32 _md_MakeNonblock(HANDLE); static PROsfd _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr *addr, int *addrlen, PRIntervalTime); static PRInt32 _nt_nonblock_connect(PRFileDesc *fd, struct sockaddr *addr, int addrlen, PRIntervalTime); static PRInt32 _nt_nonblock_recv(PRFileDesc *fd, char *buf, int len, int flags, PRIntervalTime); static PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime); static PRInt32 _nt_nonblock_writev(PRFileDesc *fd, const PRIOVec *iov, int size, PRIntervalTime); static PRInt32 _nt_nonblock_sendto(PRFileDesc *, const char *, int, const struct sockaddr *, int, PRIntervalTime); static PRInt32 _nt_nonblock_recvfrom(PRFileDesc *, char *, int, struct sockaddr *, int *, PRIntervalTime); /* * We cannot associate a fd (a socket) with an I/O completion port * if the fd is nonblocking or inheritable. * * Nonblocking socket I/O won't work if the socket is associated with * an I/O completion port. * * An inheritable fd cannot be associated with an I/O completion port * because the completion notification of async I/O initiated by the * child process is still posted to the I/O completion port in the * parent process. */ #define _NT_USE_NB_IO(fd) \ ((fd)->secret->nonblocking || (fd)->secret->inheritable == _PR_TRI_TRUE) /* * UDP support * * UDP is supported on NT by the continuation thread mechanism. * The code is borrowed from ptio.c in pthreads nspr, hence the * PT and pt prefixes. This mechanism is in fact general and * not limited to UDP. For now, only UDP's recvfrom and sendto * go through the continuation thread if they get WSAEWOULDBLOCK * on first try. Recv and send on a connected UDP socket still * goes through asychronous io. */ #define PT_DEFAULT_SELECT_MSEC 100 typedef struct pt_Continuation pt_Continuation; typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revent); typedef enum pr_ContuationStatus { pt_continuation_sumbitted, pt_continuation_inprogress, pt_continuation_abort, pt_continuation_done } pr_ContuationStatus; struct pt_Continuation { /* These objects are linked in ascending timeout order */ pt_Continuation *next, *prev; /* self linked list of these things */ /* The building of the continuation operation */ ContinuationFn function; /* what function to continue */ union { SOCKET osfd; } arg1; /* #1 - the op's fd */ union { void* buffer; } arg2; /* #2 - primary transfer buffer */ union { PRIntn amount; } arg3; /* #3 - size of 'buffer' */ union { PRIntn flags; } arg4; /* #4 - read/write flags */ union { PRNetAddr *addr; } arg5; /* #5 - send/recv address */ PRIntervalTime timeout; /* representation of the timeout */ PRIntn event; /* flags for select()'s events */ /* ** The representation and notification of the results of the operation. ** These function can either return an int return code or a pointer to ** some object. */ union { PRIntn code; void *object; } result; PRIntn syserrno; /* in case it failed, why (errno) */ pr_ContuationStatus status; /* the status of the operation */ PRCondVar *complete; /* to notify the initiating thread */ }; static struct pt_TimedQueue { PRLock *ml; /* a little protection */ PRThread *thread; /* internal thread's identification */ PRCondVar *new_op; /* new operation supplied */ PRCondVar *finish_op; /* an existing operation finished */ PRUintn op_count; /* number of operations in the list */ pt_Continuation *head, *tail; /* head/tail of list of operations */ pt_Continuation *op; /* timed operation furthest in future */ PRIntervalTime epoch; /* the epoch of 'timed' */ } pt_tq; #if defined(DEBUG) static struct pt_debug_s { PRIntn predictionsFoiled; PRIntn pollingListMax; PRIntn continuationsServed; } pt_debug; #endif /* DEBUG */ static void ContinuationThread(void *arg); static PRInt32 pt_SendTo( SOCKET osfd, const void *buf, PRInt32 amount, PRInt32 flags, const PRNetAddr *addr, PRIntn addrlen, PRIntervalTime timeout); static PRInt32 pt_RecvFrom(SOCKET osfd, void *buf, PRInt32 amount, PRInt32 flags, PRNetAddr *addr, PRIntn *addr_len, PRIntervalTime timeout); /* The key returned from GetQueuedCompletionStatus() is used to determine what * type of completion we have. We differentiate between IO completions and * CVAR completions. */ #define KEY_IO 0xaaaaaaaa #define KEY_CVAR 0xbbbbbbbb PRInt32 _PR_MD_PAUSE_CPU(PRIntervalTime ticks) { int awoken = 0; unsigned long bytes, key; int rv; LPOVERLAPPED olp; _MDOverlapped *mdOlp; PRUint32 timeout; if (_nt_idleCount > 0) { PRThread *deadThread; _MD_LOCK(&_nt_idleLock); while( !PR_CLIST_IS_EMPTY(&_nt_idleList) ) { deadThread = _PR_THREAD_PTR(PR_LIST_HEAD(&_nt_idleList)); PR_REMOVE_LINK(&deadThread->links); PR_ASSERT(deadThread->state == _PR_DEAD_STATE); /* XXXMB - cleanup to do here? */ if ( !_PR_IS_NATIVE_THREAD(deadThread) ){ /* Spinlock while user thread is still running. * There is no way to use a condition variable here. The thread * is dead, and we have to wait until we switch off the dead * thread before we can kill the fiber completely. */ while ( deadThread->no_sched) ; DeleteFiber(deadThread->md.fiber_id); } memset(deadThread, 0xa, sizeof(PRThread)); /* debugging */ if (!deadThread->threadAllocatedOnStack) PR_DELETE(deadThread); _nt_idleCount--; } _MD_UNLOCK(&_nt_idleLock); } if (ticks == PR_INTERVAL_NO_TIMEOUT) #if 0 timeout = INFINITE; #else /* * temporary hack to poll the runq every 5 seconds because of bug in * native threads creating user threads and not poking the right cpu. * * A local thread that was interrupted is bound to its current * cpu but there is no easy way for the interrupter to poke the * right cpu. This is a hack to poll the runq every 5 seconds. */ timeout = 5000; #endif else timeout = PR_IntervalToMilliseconds(ticks); /* * The idea of looping here is to complete as many IOs as possible before * returning. This should minimize trips to the idle thread. */ while(1) { rv = GetQueuedCompletionStatus( _pr_completion_port, &bytes, &key, &olp, timeout); if (rv == 0 && olp == NULL) { /* Error in GetQueuedCompetionStatus */ if (GetLastError() != WAIT_TIMEOUT) { /* ARGH - what can we do here? Log an error? XXXMB */ return -1; } else { /* If awoken == 0, then we just had a timeout */ return awoken; } } if (olp == NULL) return 0; mdOlp = (_MDOverlapped *)olp; if (mdOlp->ioModel == _MD_MultiWaitIO) { PRRecvWait *desc; PRWaitGroup *group; PRThread *thred = NULL; PRMWStatus mwstatus; desc = mdOlp->data.mw.desc; PR_ASSERT(desc != NULL); mwstatus = rv ? PR_MW_SUCCESS : PR_MW_FAILURE; if (InterlockedCompareExchange((PVOID *)&desc->outcome, (PVOID)mwstatus, (PVOID)PR_MW_PENDING) == (PVOID)PR_MW_PENDING) { if (mwstatus == PR_MW_SUCCESS) { desc->bytesRecv = bytes; } else { mdOlp->data.mw.error = GetLastError(); } } group = mdOlp->data.mw.group; PR_ASSERT(group != NULL); _PR_MD_LOCK(&group->mdlock); PR_APPEND_LINK(&mdOlp->data.mw.links, &group->io_ready); PR_ASSERT(desc->fd != NULL); NT_HashRemoveInternal(group, desc->fd); if (!PR_CLIST_IS_EMPTY(&group->wait_list)) { thred = _PR_THREAD_CONDQ_PTR(PR_LIST_HEAD(&group->wait_list)); PR_REMOVE_LINK(&thred->waitQLinks); } _PR_MD_UNLOCK(&group->mdlock); if (thred) { if (!_PR_IS_NATIVE_THREAD(thred)) { int pri = thred->priority; _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU(); _PR_THREAD_LOCK(thred); if (thred->flags & _PR_ON_PAUSEQ) { _PR_SLEEPQ_LOCK(thred->cpu); _PR_DEL_SLEEPQ(thred, PR_TRUE); _PR_SLEEPQ_UNLOCK(thred->cpu); _PR_THREAD_UNLOCK(thred); thred->cpu = lockedCPU; thred->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(lockedCPU); _PR_ADD_RUNQ(thred, lockedCPU, pri); _PR_RUNQ_UNLOCK(lockedCPU); } else { /* * The thread was just interrupted and moved * from the pause queue to the run queue. */ _PR_THREAD_UNLOCK(thred); } } else { _PR_THREAD_LOCK(thred); thred->state = _PR_RUNNABLE; _PR_THREAD_UNLOCK(thred); ReleaseSemaphore(thred->md.blocked_sema, 1, NULL); } } } else { PRThread *completed_io; PR_ASSERT(mdOlp->ioModel == _MD_BlockingIO); completed_io = _PR_THREAD_MD_TO_PTR(mdOlp->data.mdThread); completed_io->md.blocked_io_status = rv; if (rv == 0) completed_io->md.blocked_io_error = GetLastError(); completed_io->md.blocked_io_bytes = bytes; if ( !_PR_IS_NATIVE_THREAD(completed_io) ) { int pri = completed_io->priority; _PRCPU *lockedCPU = _PR_MD_CURRENT_CPU(); /* The KEY_CVAR notification only occurs when a native thread * is notifying a user thread. For user-user notifications * the wakeup occurs by having the notifier place the thread * on the runq directly; for native-native notifications the * wakeup occurs by calling ReleaseSemaphore. */ if ( key == KEY_CVAR ) { PR_ASSERT(completed_io->io_pending == PR_FALSE); PR_ASSERT(completed_io->io_suspended == PR_FALSE); PR_ASSERT(completed_io->md.thr_bound_cpu == NULL); /* Thread has already been deleted from sleepQ */ /* Switch CPU and add to runQ */ completed_io->cpu = lockedCPU; completed_io->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(lockedCPU); _PR_ADD_RUNQ(completed_io, lockedCPU, pri); _PR_RUNQ_UNLOCK(lockedCPU); } else { PR_ASSERT(key == KEY_IO); PR_ASSERT(completed_io->io_pending == PR_TRUE); _PR_THREAD_LOCK(completed_io); completed_io->io_pending = PR_FALSE; /* If io_suspended is true, then this IO has already resumed. * We don't need to do anything; because the thread is * already running. */ if (completed_io->io_suspended == PR_FALSE) { if (completed_io->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) { _PR_SLEEPQ_LOCK(completed_io->cpu); _PR_DEL_SLEEPQ(completed_io, PR_TRUE); _PR_SLEEPQ_UNLOCK(completed_io->cpu); _PR_THREAD_UNLOCK(completed_io); /* * If an I/O operation is suspended, the thread * must be running on the same cpu on which the * I/O operation was issued. */ PR_ASSERT(!completed_io->md.thr_bound_cpu || (completed_io->cpu == completed_io->md.thr_bound_cpu)); if (!completed_io->md.thr_bound_cpu) completed_io->cpu = lockedCPU; completed_io->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(completed_io->cpu); _PR_ADD_RUNQ(completed_io, completed_io->cpu, pri); _PR_RUNQ_UNLOCK(completed_io->cpu); } else { _PR_THREAD_UNLOCK(completed_io); } } else { _PR_THREAD_UNLOCK(completed_io); } } } else { /* For native threads, they are only notified through this loop * when completing IO. So, don't worry about this being a CVAR * notification, because that is not possible. */ _PR_THREAD_LOCK(completed_io); completed_io->io_pending = PR_FALSE; if (completed_io->io_suspended == PR_FALSE) { completed_io->state = _PR_RUNNABLE; _PR_THREAD_UNLOCK(completed_io); rv = ReleaseSemaphore(completed_io->md.blocked_sema, 1, NULL); PR_ASSERT(0 != rv); } else { _PR_THREAD_UNLOCK(completed_io); } } } awoken++; timeout = 0; /* Don't block on subsequent trips through the loop */ } /* never reached */ return 0; } static PRStatus _native_thread_md_wait(PRThread *thread, PRIntervalTime ticks) { DWORD rv; PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? INFINITE : PR_IntervalToMilliseconds(ticks); /* * thread waiting for a cvar or a joining thread */ rv = WaitForSingleObject(thread->md.blocked_sema, msecs); switch(rv) { case WAIT_OBJECT_0: return PR_SUCCESS; break; case WAIT_TIMEOUT: _PR_THREAD_LOCK(thread); PR_ASSERT (thread->state != _PR_IO_WAIT); if (thread->wait.cvar != NULL) { PR_ASSERT(thread->state == _PR_COND_WAIT); thread->wait.cvar = NULL; thread->state = _PR_RUNNING; _PR_THREAD_UNLOCK(thread); } else { /* The CVAR was notified just as the timeout * occurred. This left the semaphore in the * signaled state. Call WaitForSingleObject() * to clear the semaphore. */ _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE); PR_ASSERT(rv == WAIT_OBJECT_0); } return PR_SUCCESS; break; default: return PR_FAILURE; break; } return PR_SUCCESS; } PRStatus _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks) { DWORD rv; if (_native_threads_only) { return(_native_thread_md_wait(thread, ticks)); } if ( thread->flags & _PR_GLOBAL_SCOPE ) { PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? INFINITE : PR_IntervalToMilliseconds(ticks); rv = WaitForSingleObject(thread->md.blocked_sema, msecs); switch(rv) { case WAIT_OBJECT_0: return PR_SUCCESS; break; case WAIT_TIMEOUT: _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { if (thread->io_pending == PR_TRUE) { thread->state = _PR_RUNNING; thread->io_suspended = PR_TRUE; _PR_THREAD_UNLOCK(thread); } else { /* The IO completed just at the same time the timeout * occurred. This left the semaphore in the signaled * state. Call WaitForSingleObject() to clear the * semaphore. */ _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE); PR_ASSERT(rv == WAIT_OBJECT_0); } } else { if (thread->wait.cvar != NULL) { PR_ASSERT(thread->state == _PR_COND_WAIT); thread->wait.cvar = NULL; thread->state = _PR_RUNNING; _PR_THREAD_UNLOCK(thread); } else { /* The CVAR was notified just as the timeout * occurred. This left the semaphore in the * signaled state. Call WaitForSingleObject() * to clear the semaphore. */ _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE); PR_ASSERT(rv == WAIT_OBJECT_0); } } return PR_SUCCESS; break; default: return PR_FAILURE; break; } } else { PRInt32 is; _PR_INTSOFF(is); _PR_MD_SWITCH_CONTEXT(thread); } return PR_SUCCESS; } static void _native_thread_io_nowait( PRThread *thread, int rv, int bytes) { int rc; PR_ASSERT(rv != 0); _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { PR_ASSERT(thread->io_suspended == PR_FALSE); PR_ASSERT(thread->io_pending == PR_TRUE); thread->state = _PR_RUNNING; thread->io_pending = PR_FALSE; _PR_THREAD_UNLOCK(thread); } else { /* The IO completed just at the same time the * thread was interrupted. This left the semaphore * in the signaled state. Call WaitForSingleObject() * to clear the semaphore. */ PR_ASSERT(thread->io_suspended == PR_TRUE); PR_ASSERT(thread->io_pending == PR_TRUE); thread->io_pending = PR_FALSE; _PR_THREAD_UNLOCK(thread); rc = WaitForSingleObject(thread->md.blocked_sema, INFINITE); PR_ASSERT(rc == WAIT_OBJECT_0); } thread->md.blocked_io_status = rv; thread->md.blocked_io_bytes = bytes; rc = ResetEvent(thread->md.thr_event); PR_ASSERT(rc != 0); return; } static PRStatus _native_thread_io_wait(PRThread *thread, PRIntervalTime ticks) { DWORD rv, bytes; #define _NATIVE_IO_WAIT_HANDLES 2 #define _NATIVE_WAKEUP_EVENT_INDEX 0 #define _NATIVE_IO_EVENT_INDEX 1 HANDLE wait_handles[_NATIVE_IO_WAIT_HANDLES]; PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? INFINITE : PR_IntervalToMilliseconds(ticks); PR_ASSERT(thread->flags & _PR_GLOBAL_SCOPE); wait_handles[0] = thread->md.blocked_sema; wait_handles[1] = thread->md.thr_event; rv = WaitForMultipleObjects(_NATIVE_IO_WAIT_HANDLES, wait_handles, FALSE, msecs); switch(rv) { case WAIT_OBJECT_0 + _NATIVE_IO_EVENT_INDEX: /* * I/O op completed */ _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { PR_ASSERT(thread->io_suspended == PR_FALSE); PR_ASSERT(thread->io_pending == PR_TRUE); thread->state = _PR_RUNNING; thread->io_pending = PR_FALSE; _PR_THREAD_UNLOCK(thread); } else { /* The IO completed just at the same time the * thread was interrupted. This led to us being * notified twice. Call WaitForSingleObject() * to clear the semaphore. */ PR_ASSERT(thread->io_suspended == PR_TRUE); PR_ASSERT(thread->io_pending == PR_TRUE); thread->io_pending = PR_FALSE; _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE); PR_ASSERT(rv == WAIT_OBJECT_0); } rv = GetOverlappedResult((HANDLE) thread->io_fd, &thread->md.overlapped.overlapped, &bytes, FALSE); thread->md.blocked_io_status = rv; if (rv != 0) { thread->md.blocked_io_bytes = bytes; } else { thread->md.blocked_io_error = GetLastError(); PR_ASSERT(ERROR_IO_PENDING != thread->md.blocked_io_error); } rv = ResetEvent(thread->md.thr_event); PR_ASSERT(rv != 0); break; case WAIT_OBJECT_0 + _NATIVE_WAKEUP_EVENT_INDEX: /* * I/O interrupted; */ #ifdef DEBUG _PR_THREAD_LOCK(thread); PR_ASSERT(thread->io_suspended == PR_TRUE); _PR_THREAD_UNLOCK(thread); #endif break; case WAIT_TIMEOUT: _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { thread->state = _PR_RUNNING; thread->io_suspended = PR_TRUE; _PR_THREAD_UNLOCK(thread); } else { /* * The thread was interrupted just as the timeout * occurred. This left the semaphore in the signaled * state. Call WaitForSingleObject() to clear the * semaphore. */ PR_ASSERT(thread->io_suspended == PR_TRUE); _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, INFINITE); PR_ASSERT(rv == WAIT_OBJECT_0); } break; default: return PR_FAILURE; break; } return PR_SUCCESS; } static PRStatus _NT_IO_WAIT(PRThread *thread, PRIntervalTime timeout) { PRBool fWait = PR_TRUE; if (_native_threads_only) { return(_native_thread_io_wait(thread, timeout)); } if (!_PR_IS_NATIVE_THREAD(thread)) { _PR_THREAD_LOCK(thread); /* The IO may have already completed; if so, don't add to sleepQ, * since we are already on the runQ! */ if (thread->io_pending == PR_TRUE) { _PR_SLEEPQ_LOCK(thread->cpu); _PR_ADD_SLEEPQ(thread, timeout); _PR_SLEEPQ_UNLOCK(thread->cpu); } else fWait = PR_FALSE; _PR_THREAD_UNLOCK(thread); } if (fWait) return _PR_MD_WAIT(thread, timeout); else return PR_SUCCESS; } /* * Unblock threads waiting for I/O * used when interrupting threads * * NOTE: The thread lock should held when this function is called. * On return, the thread lock is released. */ void _PR_Unblock_IO_Wait(PRThread *thr) { PRStatus rv; _PRCPU *cpu = thr->cpu; PR_ASSERT(thr->state == _PR_IO_WAIT); /* * A thread for which an I/O timed out or was interrupted cannot be * in an IO_WAIT state except as a result of calling PR_Close or * PR_NT_CancelIo for the FD. For these two cases, _PR_IO_WAIT state * is not interruptible */ if (thr->md.interrupt_disabled == PR_TRUE) { _PR_THREAD_UNLOCK(thr); return; } thr->io_suspended = PR_TRUE; thr->state = _PR_RUNNABLE; if (!_PR_IS_NATIVE_THREAD(thr)) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(thr->flags & (_PR_ON_SLEEPQ | _PR_ON_PAUSEQ)); _PR_SLEEPQ_LOCK(cpu); _PR_DEL_SLEEPQ(thr, PR_TRUE); _PR_SLEEPQ_UNLOCK(cpu); /* * this thread will continue to run on the same cpu until the * I/O is aborted by closing the FD or calling CancelIO */ thr->md.thr_bound_cpu = cpu; PR_ASSERT(!(thr->flags & _PR_IDLE_THREAD)); _PR_AddThreadToRunQ(me, thr); } _PR_THREAD_UNLOCK(thr); rv = _PR_MD_WAKEUP_WAITER(thr); PR_ASSERT(PR_SUCCESS == rv); } /* Resume an outstanding IO; requires that after the switch, we disable */ static PRStatus _NT_ResumeIO(PRThread *thread, PRIntervalTime ticks) { PRBool fWait = PR_TRUE; if (!_PR_IS_NATIVE_THREAD(thread)) { if (_pr_use_static_tls) { _pr_io_restarted_io = thread; } else { TlsSetValue(_pr_io_restartedIOIndex, thread); } } else { _PR_THREAD_LOCK(thread); if (!thread->io_pending) fWait = PR_FALSE; thread->io_suspended = PR_FALSE; _PR_THREAD_UNLOCK(thread); } /* We don't put ourselves back on the sleepQ yet; until we * set the suspended bit to false, we can't do that. Just save * the sleep time here, and then continue. The restarted_io handler * will add us to the sleepQ if needed. */ thread->sleep = ticks; if (fWait) { if (!_PR_IS_NATIVE_THREAD(thread)) return _PR_MD_WAIT(thread, ticks); else return _NT_IO_WAIT(thread, ticks); } return PR_SUCCESS; } PRStatus _PR_MD_WAKEUP_WAITER(PRThread *thread) { if (thread == NULL) { /* If thread is NULL, we aren't waking a thread, we're just poking * idle thread */ if ( PostQueuedCompletionStatus(_pr_completion_port, 0, KEY_CVAR, NULL) == FALSE) return PR_FAILURE; return PR_SUCCESS; } if ( _PR_IS_NATIVE_THREAD(thread) ) { if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE) return PR_FAILURE; else return PR_SUCCESS; } else { PRThread *me = _PR_MD_CURRENT_THREAD(); /* When a Native thread has to awaken a user thread, it has to poke * the completion port because all user threads might be idle, and * thus the CPUs are just waiting for a completion. * * XXXMB - can we know when we are truely idle (and not checking * the runq)? */ if ((_PR_IS_NATIVE_THREAD(me) || (thread->cpu != me->cpu)) && (!thread->md.thr_bound_cpu)) { /* The thread should not be in any queue */ PR_ASSERT(thread->queueCount == 0); if ( PostQueuedCompletionStatus(_pr_completion_port, 0, KEY_CVAR, &(thread->md.overlapped.overlapped)) == FALSE) return PR_FAILURE; } return PR_SUCCESS; } } void _PR_MD_INIT_IO() { WORD WSAVersion = 0x0101; WSADATA WSAData; int err; OSVERSIONINFO OSversion; err = WSAStartup( WSAVersion, &WSAData ); PR_ASSERT(0 == err); _pr_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); _MD_NEW_LOCK(&_pr_recycle_lock); _MD_NEW_LOCK(&_pr_ioq_lock); OSversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&OSversion)) { _nt_version_gets_lockfile_completion = PR_FALSE; if (OSversion.dwMajorVersion >= 4) { _nt_version_gets_lockfile_completion = PR_TRUE; } } else PR_ASSERT(0); #ifdef _NEED_351_FILE_LOCKING_HACK IsFileLocalInit(); #endif /* _NEED_351_FILE_LOCKING_HACK */ /* * UDP support: start up the continuation thread */ pt_tq.op_count = 0; pt_tq.head = pt_tq.tail = NULL; pt_tq.ml = PR_NewLock(); PR_ASSERT(NULL != pt_tq.ml); pt_tq.new_op = PR_NewCondVar(pt_tq.ml); PR_ASSERT(NULL != pt_tq.new_op); #if defined(DEBUG) memset(&pt_debug, 0, sizeof(struct pt_debug_s)); #endif pt_tq.thread = PR_CreateThread( PR_SYSTEM_THREAD, ContinuationThread, NULL, PR_PRIORITY_URGENT, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(NULL != pt_tq.thread); #ifdef DEBUG /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */ { SYSTEMTIME systime; union { PRTime prt; FILETIME ft; } filetime; BOOL rv; systime.wYear = 1970; systime.wMonth = 1; /* wDayOfWeek is ignored */ systime.wDay = 1; systime.wHour = 0; systime.wMinute = 0; systime.wSecond = 0; systime.wMilliseconds = 0; rv = SystemTimeToFileTime(&systime, &filetime.ft); PR_ASSERT(0 != rv); PR_ASSERT(filetime.prt == _pr_filetime_offset); } #endif /* DEBUG */ _PR_NT_InitSids(); } /* --- SOCKET IO --------------------------------------------------------- */ /* _md_get_recycled_socket() * Get a socket from the recycle bin; if no sockets are in the bin, * create one. The socket will be passed to AcceptEx() as the * second argument. */ static SOCKET _md_get_recycled_socket(int af) { SOCKET rv; _MD_LOCK(&_pr_recycle_lock); if (af == AF_INET && _pr_recycle_INET_tail) { _pr_recycle_INET_tail--; rv = _pr_recycle_INET_array[_pr_recycle_INET_tail]; _MD_UNLOCK(&_pr_recycle_lock); return rv; } if (af == AF_INET6 && _pr_recycle_INET6_tail) { _pr_recycle_INET6_tail--; rv = _pr_recycle_INET6_array[_pr_recycle_INET6_tail]; _MD_UNLOCK(&_pr_recycle_lock); return rv; } _MD_UNLOCK(&_pr_recycle_lock); rv = _PR_MD_SOCKET(af, SOCK_STREAM, 0); if (rv != INVALID_SOCKET && _md_Associate((HANDLE)rv) == 0) { closesocket(rv); return INVALID_SOCKET; } return rv; } /* _md_put_recycled_socket() * Add a socket to the recycle bin. */ static void _md_put_recycled_socket(SOCKET newsock, int af) { PR_ASSERT(_pr_recycle_INET_tail >= 0); PR_ASSERT(_pr_recycle_INET6_tail >= 0); _MD_LOCK(&_pr_recycle_lock); if (af == AF_INET && _pr_recycle_INET_tail < RECYCLE_SIZE) { _pr_recycle_INET_array[_pr_recycle_INET_tail] = newsock; _pr_recycle_INET_tail++; _MD_UNLOCK(&_pr_recycle_lock); } else if (af == AF_INET6 && _pr_recycle_INET6_tail < RECYCLE_SIZE) { _pr_recycle_INET6_array[_pr_recycle_INET6_tail] = newsock; _pr_recycle_INET6_tail++; _MD_UNLOCK(&_pr_recycle_lock); } else { _MD_UNLOCK(&_pr_recycle_lock); closesocket(newsock); } return; } /* _md_Associate() * Associates a file with the completion port. * Returns 0 on failure, 1 on success. */ PRInt32 _md_Associate(HANDLE file) { HANDLE port; if (!_native_threads_only) { port = CreateIoCompletionPort((HANDLE)file, _pr_completion_port, KEY_IO, 0); /* XXX should map error codes on failures */ return (port == _pr_completion_port); } else { return 1; } } /* * _md_MakeNonblock() * Make a socket nonblocking. * Returns 0 on failure, 1 on success. */ static PRInt32 _md_MakeNonblock(HANDLE file) { int rv; u_long one = 1; rv = ioctlsocket((SOCKET)file, FIONBIO, &one); /* XXX should map error codes on failures */ return (rv == 0); } static int missing_completions = 0; static int max_wait_loops = 0; static PRInt32 _NT_IO_ABORT(PROsfd sock) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRBool fWait; PRInt32 rv; int loop_count; /* This is a clumsy way to abort the IO, but it is all we can do. * It looks a bit racy, but we handle all the cases. * case 1: IO completes before calling closesocket * case 1a: fWait is set to PR_FALSE * This should e the most likely case. We'll properly * not wait call _NT_IO_WAIT, since the closesocket() * won't be forcing a completion. * case 1b: fWait is set to PR_TRUE * This hopefully won't happen much. When it does, this * thread will timeout in _NT_IO_WAIT for CLOSE_INTERVAL * before cleaning up. * case 2: IO does not complete before calling closesocket * case 2a: IO never completes * This is the likely case. We'll close it and wait * for the completion forced by the close. Return should * be immediate. * case 2b: IO completes just after calling closesocket * Since the closesocket is issued, we'll either get a * completion back for the real IO or for the close. We * don't really care. It may not even be possible to get * a real completion here. In any event, we'll awaken * from NT_IO_WAIT immediately. */ _PR_THREAD_LOCK(me); fWait = me->io_pending; if (fWait) { /* * If there's still I/O pending, it should have already timed * out once before this function is called. */ PR_ASSERT(me->io_suspended == PR_TRUE); /* Set up to wait for I/O completion again */ me->state = _PR_IO_WAIT; me->io_suspended = PR_FALSE; me->md.interrupt_disabled = PR_TRUE; } _PR_THREAD_UNLOCK(me); /* Close the socket if there is one */ if (sock != INVALID_SOCKET) { rv = closesocket((SOCKET)sock); } /* If there was I/O pending before the close, wait for it to complete */ if (fWait) { /* Wait and wait for the I/O to complete */ for (loop_count = 0; fWait; ++loop_count) { _NT_IO_WAIT(me, CLOSE_TIMEOUT); _PR_THREAD_LOCK(me); fWait = me->io_pending; if (fWait) { PR_ASSERT(me->io_suspended == PR_TRUE); me->state = _PR_IO_WAIT; me->io_suspended = PR_FALSE; } _PR_THREAD_UNLOCK(me); if (loop_count > max_wait_loops) { max_wait_loops = loop_count; } } if (loop_count > 1) { ++missing_completions; } me->md.interrupt_disabled = PR_FALSE; me->io_pending = PR_FALSE; me->state = _PR_RUNNING; } PR_ASSERT(me->io_pending == PR_FALSE); me->md.thr_bound_cpu = NULL; me->io_suspended = PR_FALSE; return rv; } PROsfd _PR_MD_SOCKET(int af, int type, int flags) { SOCKET sock; sock = socket(af, type, flags); if (sock == INVALID_SOCKET) { _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError()); } return (PROsfd)sock; } struct connect_data_s { PRInt32 status; PRInt32 error; PROsfd osfd; struct sockaddr *addr; PRUint32 addrlen; PRIntervalTime timeout; }; void _PR_MD_connect_thread(void *cdata) { struct connect_data_s *cd = (struct connect_data_s *)cdata; cd->status = connect(cd->osfd, cd->addr, cd->addrlen); if (cd->status == SOCKET_ERROR) cd->error = WSAGetLastError(); return; } PRInt32 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; u_long nbio; PRInt32 rc; if (fd->secret->nonblocking) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) { err = WSAGetLastError(); _PR_MD_MAP_CONNECT_ERROR(err); } return rv; } /* * Temporarily make the socket non-blocking so that we can * initiate a non-blocking connect and wait for its completion * (with a timeout) in select. */ PR_ASSERT(!fd->secret->md.io_model_committed); nbio = 1; rv = ioctlsocket((SOCKET)osfd, FIONBIO, &nbio); PR_ASSERT(0 == rv); rc = _nt_nonblock_connect(fd, (struct sockaddr *) addr, addrlen, timeout); /* Set the socket back to blocking. */ nbio = 0; rv = ioctlsocket((SOCKET)osfd, FIONBIO, &nbio); PR_ASSERT(0 == rv); return rc; } PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv; #if 0 int one = 1; #endif rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen); if (rv == SOCKET_ERROR) { _PR_MD_MAP_BIND_ERROR(WSAGetLastError()); return -1; } #if 0 /* Disable nagle- so far unknown if this is good or not... */ rv = setsockopt(fd->secret->md.osfd, SOL_SOCKET, TCP_NODELAY, (const char *)&one, sizeof(one)); PR_ASSERT(rv == 0); #endif return 0; } void _PR_MD_UPDATE_ACCEPT_CONTEXT(PROsfd accept_sock, PROsfd listen_sock) { /* Sockets accept()'d with AcceptEx need to call this setsockopt before * calling anything other than ReadFile(), WriteFile(), send(), recv(), * Transmitfile(), and closesocket(). In order to call any other * winsock functions, we have to make this setsockopt call. * * XXXMB - For the server, we *NEVER* need this in * the "normal" code path. But now we have to call it. This is a waste * of a system call. We'd like to only call it before calling the * obscure socket calls, but since we don't know at that point what the * original socket was (or even if it is still alive) we can't do it * at that point... */ setsockopt((SOCKET)accept_sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&listen_sock, sizeof(listen_sock)); } #define INET_ADDR_PADDED (sizeof(PRNetAddr) + 16) PROsfd _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg) { PROsfd osfd = fd->secret->md.osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); SOCKET accept_sock; int bytes; PRNetAddr *Laddr; PRNetAddr *Raddr; PRUint32 llen, err; int rv; if (_NT_USE_NB_IO(fd)) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } /* * The accepted socket inherits the nonblocking and * inheritable (HANDLE_FLAG_INHERIT) attributes of * the listening socket. */ accept_sock = _nt_nonblock_accept(fd, (struct sockaddr *)raddr, rlen, timeout); if (!fd->secret->nonblocking) { u_long zero = 0; rv = ioctlsocket(accept_sock, FIONBIO, &zero); PR_ASSERT(0 == rv); } return accept_sock; } if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } if (!fd->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } if (!me->md.acceptex_buf) { me->md.acceptex_buf = PR_MALLOC(2*INET_ADDR_PADDED); if (!me->md.acceptex_buf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } } accept_sock = _md_get_recycled_socket(fd->secret->af); if (accept_sock == INVALID_SOCKET) return -1; memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); closesocket(accept_sock); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = osfd; rv = AcceptEx((SOCKET)osfd, accept_sock, me->md.acceptex_buf, 0, INET_ADDR_PADDED, INET_ADDR_PADDED, &bytes, &(me->md.overlapped.overlapped)); if ( (rv == 0) && ((err = WSAGetLastError()) != ERROR_IO_PENDING)) { /* Argh! The IO failed */ closesocket(accept_sock); _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_ACCEPTEX_ERROR(err); return -1; } if (_native_threads_only && rv) { _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); closesocket(accept_sock); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { closesocket(accept_sock); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } return -1; } if (me->md.blocked_io_status == 0) { closesocket(accept_sock); _PR_MD_MAP_ACCEPTEX_ERROR(me->md.blocked_io_error); return -1; } if (!fast) _PR_MD_UPDATE_ACCEPT_CONTEXT((SOCKET)accept_sock, (SOCKET)osfd); /* IO is done */ GetAcceptExSockaddrs( me->md.acceptex_buf, 0, INET_ADDR_PADDED, INET_ADDR_PADDED, (LPSOCKADDR *)&(Laddr), &llen, (LPSOCKADDR *)&(Raddr), (unsigned int *)rlen); if (raddr != NULL) memcpy((char *)raddr, (char *)&Raddr->inet, *rlen); PR_ASSERT(me->io_pending == PR_FALSE); return accept_sock; } PRInt32 _PR_MD_FAST_ACCEPT_READ(PRFileDesc *sd, PROsfd *newSock, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout, PRBool fast, _PR_AcceptTimeoutCallback callback, void *callbackArg) { PROsfd sock = sd->secret->md.osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); int bytes; PRNetAddr *Laddr; PRUint32 llen, rlen, err; int rv; PRBool isConnected; PRBool madeCallback = PR_FALSE; if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } if (!sd->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)sock); PR_ASSERT(0 != rv); sd->secret->md.io_model_committed = PR_TRUE; } *newSock = _md_get_recycled_socket(sd->secret->af); if (*newSock == INVALID_SOCKET) return -1; memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); closesocket(*newSock); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = sock; rv = AcceptEx((SOCKET)sock, *newSock, buf, amount, INET_ADDR_PADDED, INET_ADDR_PADDED, &bytes, &(me->md.overlapped.overlapped)); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING)) { closesocket(*newSock); _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_ACCEPTEX_ERROR(err); return -1; } if (_native_threads_only && rv) { _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); closesocket(*newSock); return -1; } retry: if (me->io_suspended) { PRInt32 err; INT seconds; INT bytes = sizeof(seconds); PR_ASSERT(timeout != PR_INTERVAL_NO_TIMEOUT); err = getsockopt(*newSock, SOL_SOCKET, SO_CONNECT_TIME, (char *)&seconds, (PINT)&bytes); if ( err == NO_ERROR ) { PRIntervalTime elapsed = PR_SecondsToInterval(seconds); if (seconds == 0xffffffff) isConnected = PR_FALSE; else isConnected = PR_TRUE; if (!isConnected) { if (madeCallback == PR_FALSE && callback) callback(callbackArg); madeCallback = PR_TRUE; me->state = _PR_IO_WAIT; if (_NT_ResumeIO(me, timeout) == PR_FAILURE) { closesocket(*newSock); return -1; } goto retry; } if (elapsed < timeout) { /* Socket is connected but time not elapsed, RESUME IO */ timeout -= elapsed; me->state = _PR_IO_WAIT; if (_NT_ResumeIO(me, timeout) == PR_FAILURE) { closesocket(*newSock); return -1; } goto retry; } } else { /* What to do here? Assume socket not open?*/ PR_ASSERT(0); isConnected = PR_FALSE; } rv = _NT_IO_ABORT(*newSock); PR_ASSERT(me->io_pending == PR_FALSE); PR_ASSERT(me->io_suspended == PR_FALSE); PR_ASSERT(me->md.thr_bound_cpu == NULL); /* If the IO is still suspended, it means we didn't get any * completion from NT_IO_WAIT. This is not disasterous, I hope, * but it may mean we still have an IO outstanding... Try to * recover by just allowing ourselves to continue. */ me->io_suspended = PR_FALSE; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } me->state = _PR_RUNNING; closesocket(*newSock); return -1; } PR_ASSERT(me->io_pending == PR_FALSE); PR_ASSERT(me->io_suspended == PR_FALSE); PR_ASSERT(me->md.thr_bound_cpu == NULL); if (me->md.blocked_io_status == 0) { _PR_MD_MAP_ACCEPTEX_ERROR(me->md.blocked_io_error); closesocket(*newSock); return -1; } if (!fast) _PR_MD_UPDATE_ACCEPT_CONTEXT((SOCKET)*newSock, (SOCKET)sock); /* IO is done */ GetAcceptExSockaddrs( buf, amount, INET_ADDR_PADDED, INET_ADDR_PADDED, (LPSOCKADDR *)&(Laddr), &llen, (LPSOCKADDR *)(raddr), (unsigned int *)&rlen); return me->md.blocked_io_bytes; } PRInt32 _PR_MD_SENDFILE(PRFileDesc *sock, PRSendFileData *sfd, PRInt32 flags, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRInt32 tflags; int rv, err; if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } if (!sock->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)sock->secret->md.osfd); PR_ASSERT(0 != rv); sock->secret->md.io_model_committed = PR_TRUE; } if (!me->md.xmit_bufs) { me->md.xmit_bufs = PR_NEW(TRANSMIT_FILE_BUFFERS); if (!me->md.xmit_bufs) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } } me->md.xmit_bufs->Head = (void *)sfd->header; me->md.xmit_bufs->HeadLength = sfd->hlen; me->md.xmit_bufs->Tail = (void *)sfd->trailer; me->md.xmit_bufs->TailLength = sfd->tlen; memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); me->md.overlapped.overlapped.Offset = sfd->file_offset; if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; tflags = 0; if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) tflags = TF_DISCONNECT | TF_REUSE_SOCKET; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = sock->secret->md.osfd; rv = TransmitFile((SOCKET)sock->secret->md.osfd, (HANDLE)sfd->fd->secret->md.osfd, (DWORD)sfd->file_nbytes, (DWORD)0, (LPOVERLAPPED)&(me->md.overlapped.overlapped), (TRANSMIT_FILE_BUFFERS *)me->md.xmit_bufs, (DWORD)tflags); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_TRANSMITFILE_ERROR(err); return -1; } if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } return -1; } if (me->md.blocked_io_status == 0) { _PR_MD_MAP_TRANSMITFILE_ERROR(me->md.blocked_io_error); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { _md_put_recycled_socket(sock->secret->md.osfd, sock->secret->af); } PR_ASSERT(me->io_pending == PR_FALSE); return me->md.blocked_io_bytes; } PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); int bytes; int rv, err; if (_NT_USE_NB_IO(fd)) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } return _nt_nonblock_recv(fd, buf, amount, flags, timeout); } if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } if (!fd->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = osfd; rv = ReadFile((HANDLE)osfd, buf, amount, &bytes, &(me->md.overlapped.overlapped)); if ( (rv == 0) && (GetLastError() != ERROR_IO_PENDING) ) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); if ((err = GetLastError()) == ERROR_HANDLE_EOF) return 0; _PR_MD_MAP_READ_ERROR(err); return -1; } if (_native_threads_only && rv) { _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } return -1; } if (me->md.blocked_io_status == 0) { if (me->md.blocked_io_error == ERROR_HANDLE_EOF) return 0; _PR_MD_MAP_READ_ERROR(me->md.blocked_io_error); return -1; } PR_ASSERT(me->io_pending == PR_FALSE); return me->md.blocked_io_bytes; } PRInt32 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRThread *me = _PR_MD_CURRENT_THREAD(); int bytes; int rv, err; if (_NT_USE_NB_IO(fd)) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } return _nt_nonblock_send(fd, (char *)buf, amount, timeout); } if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } if (!fd->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = osfd; rv = WriteFile((HANDLE)osfd, buf, amount, &bytes, &(me->md.overlapped.overlapped)); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_WRITE_ERROR(err); return -1; } if (_native_threads_only && rv) { _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, timeout) == PR_FAILURE) { PR_ASSERT(0); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } return -1; } if (me->md.blocked_io_status == 0) { _PR_MD_MAP_WRITE_ERROR(me->md.blocked_io_error); return -1; } PR_ASSERT(me->io_pending == PR_FALSE); return me->md.blocked_io_bytes; } PRInt32 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv; if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } if (_NT_USE_NB_IO(fd)) return _nt_nonblock_sendto(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout); else return pt_SendTo(osfd, buf, amount, flags, addr, addrlen, timeout); } PRInt32 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv; if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } if (_NT_USE_NB_IO(fd)) return _nt_nonblock_recvfrom(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout); else return pt_RecvFrom(osfd, buf, amount, flags, addr, addrlen, timeout); } /* XXXMB - for now this is a sockets call only */ PRInt32 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; int index; int sent = 0; int rv; if (_NT_USE_NB_IO(fd)) { if (!fd->secret->md.io_model_committed) { rv = _md_MakeNonblock((HANDLE)osfd); PR_ASSERT(0 != rv); fd->secret->md.io_model_committed = PR_TRUE; } return _nt_nonblock_writev(fd, iov, iov_size, timeout); } for (index=0; index 0) sent += rv; if ( rv != iov[index].iov_len ) { if (sent <= 0) return -1; return -1; } } return sent; } PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) { PRInt32 rv; rv = listen(fd->secret->md.osfd, backlog); if (rv < 0) _PR_MD_MAP_LISTEN_ERROR(WSAGetLastError()); return(rv); } PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) { PRInt32 rv; rv = shutdown(fd->secret->md.osfd, how); if (rv < 0) _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError()); return(rv); } PRStatus _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) { PRInt32 rv; rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len); if (rv==0) return PR_SUCCESS; else { _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError()); return PR_FAILURE; } } PRStatus _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) { PRInt32 rv; /* * NT has a bug that, when invoked on a socket accepted by * AcceptEx(), getpeername() returns an all-zero peer address. * To work around this bug, we store the peer's address (returned * by AcceptEx()) with the socket fd and use the cached peer * address if the socket is an accepted socket. */ if (fd->secret->md.accepted_socket) { INT seconds; INT bytes = sizeof(seconds); /* * Determine if the socket is connected. */ rv = getsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_CONNECT_TIME, (char *) &seconds, (PINT) &bytes); if (rv == NO_ERROR) { if (seconds == 0xffffffff) { PR_SetError(PR_NOT_CONNECTED_ERROR, 0); return PR_FAILURE; } *len = PR_NETADDR_SIZE(&fd->secret->md.peer_addr); memcpy(addr, &fd->secret->md.peer_addr, *len); return PR_SUCCESS; } else { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return PR_FAILURE; } } else { rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *) addr, len); if (rv == 0) { return PR_SUCCESS; } else { _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError()); return PR_FAILURE; } } } PRStatus _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) { PRInt32 rv; rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen); if (rv==0) return PR_SUCCESS; else { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return PR_FAILURE; } } PRStatus _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen) { PRInt32 rv; rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen); if (rv==0) return PR_SUCCESS; else { _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError()); return PR_FAILURE; } } /* --- FILE IO ----------------------------------------------------------- */ PROsfd _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode) { HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS; else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; flag6 |= FILE_FLAG_OVERLAPPED; file = CreateFile(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, flags, flag6, NULL); if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } if (osflags & PR_APPEND) { if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) { _PR_MD_MAP_LSEEK_ERROR(GetLastError()); CloseHandle(file); return -1; } } return (PROsfd)file; } PROsfd _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, PRIntn mode) { HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) flags = (0 != (osflags & PR_TRUNCATE)) ? CREATE_ALWAYS : OPEN_ALWAYS; else if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; flag6 |= FILE_FLAG_OVERLAPPED; if (osflags & PR_CREATE_FILE) { if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } } file = CreateFile(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, lpSA, flags, flag6, NULL); if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } if (osflags & PR_APPEND) { if ( SetFilePointer(file, 0, 0, FILE_END) == 0xFFFFFFFF ) { _PR_MD_MAP_LSEEK_ERROR(GetLastError()); CloseHandle(file); return -1; } } return (PROsfd)file; } PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) { PROsfd f = fd->secret->md.osfd; PRUint32 bytes; int rv, err; LONG hiOffset = 0; LONG loOffset; if (!fd->secret->md.sync_file_io) { PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, &me->md.overlapped.overlapped.OffsetHigh, FILE_CURRENT); PR_ASSERT((me->md.overlapped.overlapped.Offset != 0xffffffff) || (GetLastError() == NO_ERROR)); if (fd->secret->inheritable == _PR_TRI_TRUE) { rv = ReadFile((HANDLE)f, (LPVOID)buf, len, &bytes, &me->md.overlapped.overlapped); if (rv != 0) { loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); if (err == ERROR_IO_PENDING) { rv = GetOverlappedResult((HANDLE)f, &me->md.overlapped.overlapped, &bytes, TRUE); if (rv != 0) { loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); } if (err == ERROR_HANDLE_EOF) { return 0; } else { _PR_MD_MAP_READ_ERROR(err); return -1; } } else { if (!fd->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)f); PR_ASSERT(rv != 0); fd->secret->md.io_model_committed = PR_TRUE; } if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = f; rv = ReadFile((HANDLE)f, (LPVOID)buf, len, &bytes, &me->md.overlapped.overlapped); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); if (err == ERROR_HANDLE_EOF) { return 0; } _PR_MD_MAP_READ_ERROR(err); return -1; } if (_native_threads_only && rv) { _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { PR_ASSERT(0); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } return -1; } if (me->md.blocked_io_status == 0) { if (me->md.blocked_io_error == ERROR_HANDLE_EOF) { return 0; } _PR_MD_MAP_READ_ERROR(me->md.blocked_io_error); return -1; } SetFilePointer((HANDLE)f, me->md.blocked_io_bytes, 0, FILE_CURRENT); PR_ASSERT(me->io_pending == PR_FALSE); return me->md.blocked_io_bytes; } } else { rv = ReadFile((HANDLE)f, (LPVOID)buf, len, &bytes, NULL); if (rv == 0) { err = GetLastError(); /* ERROR_HANDLE_EOF can only be returned by async io */ PR_ASSERT(err != ERROR_HANDLE_EOF); if (err == ERROR_BROKEN_PIPE) { /* The write end of the pipe has been closed. */ return 0; } _PR_MD_MAP_READ_ERROR(err); return -1; } return bytes; } } PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) { PROsfd f = fd->secret->md.osfd; PRInt32 bytes; int rv, err; LONG hiOffset = 0; LONG loOffset; LARGE_INTEGER offset; /* use for the calculation of the new offset */ if (!fd->secret->md.sync_file_io) { PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return -1; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, &me->md.overlapped.overlapped.OffsetHigh, FILE_CURRENT); PR_ASSERT((me->md.overlapped.overlapped.Offset != 0xffffffff) || (GetLastError() == NO_ERROR)); if (fd->secret->inheritable == _PR_TRI_TRUE) { rv = WriteFile((HANDLE)f, (LPVOID)buf, len, &bytes, &me->md.overlapped.overlapped); if (rv != 0) { loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); if (err == ERROR_IO_PENDING) { rv = GetOverlappedResult((HANDLE)f, &me->md.overlapped.overlapped, &bytes, TRUE); if (rv != 0) { loOffset = SetFilePointer((HANDLE)f, bytes, &hiOffset, FILE_CURRENT); PR_ASSERT((loOffset != 0xffffffff) || (GetLastError() == NO_ERROR)); return bytes; } err = GetLastError(); } _PR_MD_MAP_READ_ERROR(err); return -1; } else { if (!fd->secret->md.io_model_committed) { rv = _md_Associate((HANDLE)f); PR_ASSERT(rv != 0); fd->secret->md.io_model_committed = PR_TRUE; } if (_native_threads_only) me->md.overlapped.overlapped.hEvent = me->md.thr_event; _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); me->io_fd = f; rv = WriteFile((HANDLE)f, buf, len, &bytes, &(me->md.overlapped.overlapped)); if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_WRITE_ERROR(err); return -1; } if (_native_threads_only && rv) { _native_thread_io_nowait(me, rv, bytes); } else if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { PR_ASSERT(0); return -1; } PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE); if (me->io_suspended) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } return -1; } if (me->md.blocked_io_status == 0) { _PR_MD_MAP_WRITE_ERROR(me->md.blocked_io_error); return -1; } /* * Moving the file pointer by a relative offset (FILE_CURRENT) * does not work with a file on a network drive exported by a * Win2K system. We still don't know why. A workaround is to * move the file pointer by an absolute offset (FILE_BEGIN). * (Bugzilla bug 70765) */ offset.LowPart = me->md.overlapped.overlapped.Offset; offset.HighPart = me->md.overlapped.overlapped.OffsetHigh; offset.QuadPart += me->md.blocked_io_bytes; SetFilePointer((HANDLE)f, offset.LowPart, &offset.HighPart, FILE_BEGIN); PR_ASSERT(me->io_pending == PR_FALSE); return me->md.blocked_io_bytes; } } else { rv = WriteFile((HANDLE)f, buf, len, &bytes, NULL); if (rv == 0) { _PR_MD_MAP_WRITE_ERROR(GetLastError()); return -1; } return bytes; } } PRInt32 _PR_MD_SOCKETAVAILABLE(PRFileDesc *fd) { PRInt32 result; if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError()); return -1; } return result; } PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) { if (NULL == fd) PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } PROffset32 _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence) { DWORD moveMethod; PROffset32 rv; switch (whence) { case PR_SEEK_SET: moveMethod = FILE_BEGIN; break; case PR_SEEK_CUR: moveMethod = FILE_CURRENT; break; case PR_SEEK_END: moveMethod = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } rv = SetFilePointer((HANDLE)fd->secret->md.osfd, offset, NULL, moveMethod); /* * If the lpDistanceToMoveHigh argument (third argument) is * NULL, SetFilePointer returns 0xffffffff on failure. */ if (-1 == rv) { _PR_MD_MAP_LSEEK_ERROR(GetLastError()); } return rv; } PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence) { DWORD moveMethod; LARGE_INTEGER li; DWORD err; switch (whence) { case PR_SEEK_SET: moveMethod = FILE_BEGIN; break; case PR_SEEK_CUR: moveMethod = FILE_CURRENT; break; case PR_SEEK_END: moveMethod = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } li.QuadPart = offset; li.LowPart = SetFilePointer((HANDLE)fd->secret->md.osfd, li.LowPart, &li.HighPart, moveMethod); if (0xffffffff == li.LowPart && (err = GetLastError()) != NO_ERROR) { _PR_MD_MAP_LSEEK_ERROR(err); li.QuadPart = -1; } return li.QuadPart; } /* * This is documented to succeed on read-only files, but Win32's * FlushFileBuffers functions fails with "access denied" in such a * case. So we only signal an error if the error is *not* "access * denied". */ PRInt32 _PR_MD_FSYNC(PRFileDesc *fd) { /* * From the documentation: * * On Windows NT, the function FlushFileBuffers fails if hFile * is a handle to console output. That is because console * output is not buffered. The function returns FALSE, and * GetLastError returns ERROR_INVALID_HANDLE. * * On the other hand, on Win95, it returns without error. I cannot * assume that 0, 1, and 2 are console, because if someone closes * System.out and then opens a file, they might get file descriptor * 1. An error on *that* version of 1 should be reported, whereas * an error on System.out (which was the original 1) should be * ignored. So I use isatty() to ensure that such an error was * because of this, and if it was, I ignore the error. */ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd); if (!ok) { DWORD err = GetLastError(); if (err != ERROR_ACCESS_DENIED) { /* from winerror.h */ _PR_MD_MAP_FSYNC_ERROR(err); return -1; } } return 0; } PRInt32 _PR_MD_CLOSE(PROsfd osfd, PRBool socket) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (socket) { rv = closesocket((SOCKET)osfd); if (rv < 0) _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError()); } else { rv = CloseHandle((HANDLE)osfd)?0:-1; if (rv < 0) _PR_MD_MAP_CLOSE_ERROR(GetLastError()); } if (rv == 0 && me->io_suspended) { if (me->io_fd == osfd) { PRBool fWait; _PR_THREAD_LOCK(me); me->state = _PR_IO_WAIT; /* The IO could have completed on another thread just after * calling closesocket while the io_suspended flag was true. * So we now grab the lock to do a safe check on io_pending to * see if we need to wait or not. */ fWait = me->io_pending; me->io_suspended = PR_FALSE; me->md.interrupt_disabled = PR_TRUE; _PR_THREAD_UNLOCK(me); if (fWait) _NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(me->io_suspended == PR_FALSE); PR_ASSERT(me->io_pending == PR_FALSE); /* * I/O operation is no longer pending; the thread can now * run on any cpu */ _PR_THREAD_LOCK(me); me->md.interrupt_disabled = PR_FALSE; me->md.thr_bound_cpu = NULL; me->io_suspended = PR_FALSE; me->io_pending = PR_FALSE; me->state = _PR_RUNNING; _PR_THREAD_UNLOCK(me); } } return rv; } PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) { BOOL rv; if (fd->secret->md.io_model_committed) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } rv = SetHandleInformation( (HANDLE)fd->secret->md.osfd, HANDLE_FLAG_INHERIT, inheritable ? HANDLE_FLAG_INHERIT : 0); if (0 == rv) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } return PR_SUCCESS; } void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported) { if (imported) { fd->secret->inheritable = _PR_TRI_UNKNOWN; } else { fd->secret->inheritable = _PR_TRI_FALSE; } } void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd) { DWORD flags; PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); if (fd->secret->md.io_model_committed) { return; } if (GetHandleInformation((HANDLE)fd->secret->md.osfd, &flags)) { if (flags & HANDLE_FLAG_INHERIT) { fd->secret->inheritable = _PR_TRI_TRUE; } else { fd->secret->inheritable = _PR_TRI_FALSE; } } } /* --- DIR IO ------------------------------------------------------------ */ #define GetFileFromDIR(d) (d)->d_entry.cFileName #define FileIsHidden(d) ((d)->d_entry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) void FlipSlashes(char *cp, int len) { while (--len >= 0) { if (cp[0] == '/') { cp[0] = PR_DIRECTORY_SEPARATOR; } cp = _mbsinc(cp); } } /* end FlipSlashes() */ /* ** ** Local implementations of standard Unix RTL functions which are not provided ** by the VC RTL. ** */ PRInt32 _PR_MD_CLOSE_DIR(_MDDir *d) { if ( d ) { if (FindClose( d->d_hdl )) { d->magic = (PRUint32)-1; return 0; } else { _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError()); return -1; } } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } PRStatus _PR_MD_OPEN_DIR(_MDDir *d, const char *name) { char filename[ MAX_PATH ]; int len; len = strlen(name); /* Need 5 bytes for \*.* and the trailing null byte. */ if (len + 5 > MAX_PATH) { PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); return PR_FAILURE; } strcpy(filename, name); /* * If 'name' ends in a slash or backslash, do not append * another backslash. */ if (IsPrevCharSlash(filename, filename + len)) { len--; } strcpy(&filename[len], "\\*.*"); FlipSlashes( filename, strlen(filename) ); d->d_hdl = FindFirstFile( filename, &(d->d_entry) ); if ( d->d_hdl == INVALID_HANDLE_VALUE ) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return PR_FAILURE; } d->firstEntry = PR_TRUE; d->magic = _MD_MAGIC_DIR; return PR_SUCCESS; } char * _PR_MD_READ_DIR(_MDDir *d, PRIntn flags) { PRInt32 err; BOOL rv; char *fileName; if ( d ) { while (1) { if (d->firstEntry) { d->firstEntry = PR_FALSE; rv = 1; } else { rv = FindNextFile(d->d_hdl, &(d->d_entry)); } if (rv == 0) { break; } fileName = GetFileFromDIR(d); if ( (flags & PR_SKIP_DOT) && (fileName[0] == '.') && (fileName[1] == '\0')) continue; if ( (flags & PR_SKIP_DOT_DOT) && (fileName[0] == '.') && (fileName[1] == '.') && (fileName[2] == '\0')) continue; if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) continue; return fileName; } err = GetLastError(); PR_ASSERT(NO_ERROR != err); _PR_MD_MAP_READDIR_ERROR(err); return NULL; } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } PRInt32 _PR_MD_DELETE(const char *name) { if (DeleteFile(name)) { return 0; } else { _PR_MD_MAP_DELETE_ERROR(GetLastError()); return -1; } } void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) { PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); CopyMemory(prtm, filetime, sizeof(PRTime)); #ifdef __GNUC__ *prtm = (*prtm - _pr_filetime_offset) / 10LL; #else *prtm = (*prtm - _pr_filetime_offset) / 10i64; #endif #ifdef DEBUG /* Doublecheck our calculation. */ { SYSTEMTIME systime; PRExplodedTime etm; PRTime cmp; /* for comparison */ BOOL rv; rv = FileTimeToSystemTime(filetime, &systime); PR_ASSERT(0 != rv); /* * PR_ImplodeTime ignores wday and yday. */ etm.tm_usec = systime.wMilliseconds * PR_USEC_PER_MSEC; etm.tm_sec = systime.wSecond; etm.tm_min = systime.wMinute; etm.tm_hour = systime.wHour; etm.tm_mday = systime.wDay; etm.tm_month = systime.wMonth - 1; etm.tm_year = systime.wYear; /* * It is not well-documented what time zone the FILETIME's * are in. WIN32_FIND_DATA is documented to be in UTC (GMT). * But BY_HANDLE_FILE_INFORMATION is unclear about this. * By our best judgement, we assume that FILETIME is in UTC. */ etm.tm_params.tp_gmt_offset = 0; etm.tm_params.tp_dst_offset = 0; cmp = PR_ImplodeTime(&etm); /* * SYSTEMTIME is in milliseconds precision, so we convert PRTime's * microseconds to milliseconds before doing the comparison. */ PR_ASSERT((cmp / PR_USEC_PER_MSEC) == (*prtm / PR_USEC_PER_MSEC)); } #endif /* DEBUG */ } PRInt32 _PR_MD_STAT(const char *fn, struct stat *info) { PRInt32 rv; rv = _stat(fn, (struct _stat *)info); if (-1 == rv) { /* * Check for MSVC runtime library _stat() bug. * (It's really a bug in FindFirstFile().) * If a pathname ends in a backslash or slash, * e.g., c:\temp\ or c:/temp/, _stat() will fail. * Note: a pathname ending in a slash (e.g., c:/temp/) * can be handled by _stat() on NT but not on Win95. * * We remove the backslash or slash at the end and * try again. */ int len = strlen(fn); if (len > 0 && len <= _MAX_PATH && IsPrevCharSlash(fn, fn + len)) { char newfn[_MAX_PATH + 1]; strcpy(newfn, fn); newfn[len - 1] = '\0'; rv = _stat(newfn, (struct _stat *)info); } } if (-1 == rv) { _PR_MD_MAP_STAT_ERROR(errno); } return rv; } #define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') static PRBool IsPrevCharSlash(const char *str, const char *current) { const char *prev; if (str >= current) return PR_FALSE; prev = _mbsdec(str, current); return (prev == current - 1) && _PR_IS_SLASH(*prev); } /* * IsRootDirectory -- * * Return PR_TRUE if the pathname 'fn' is a valid root directory, * else return PR_FALSE. The char buffer pointed to by 'fn' must * be writable. During the execution of this function, the contents * of the buffer pointed to by 'fn' may be modified, but on return * the original contents will be restored. 'buflen' is the size of * the buffer pointed to by 'fn'. * * Root directories come in three formats: * 1. / or \, meaning the root directory of the current drive. * 2. C:/ or C:\, where C is a drive letter. * 3. \\\\ or * \\\, meaning the root directory * of a UNC (Universal Naming Convention) name. */ static PRBool IsRootDirectory(char *fn, size_t buflen) { char *p; PRBool slashAdded = PR_FALSE; PRBool rv = PR_FALSE; if (_PR_IS_SLASH(fn[0]) && fn[1] == '\0') { return PR_TRUE; } if (isalpha(fn[0]) && fn[1] == ':' && _PR_IS_SLASH(fn[2]) && fn[3] == '\0') { rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE; return rv; } /* The UNC root directory */ if (_PR_IS_SLASH(fn[0]) && _PR_IS_SLASH(fn[1])) { /* The 'server' part should have at least one character. */ p = &fn[2]; if (*p == '\0' || _PR_IS_SLASH(*p)) { return PR_FALSE; } /* look for the next slash */ do { p = _mbsinc(p); } while (*p != '\0' && !_PR_IS_SLASH(*p)); if (*p == '\0') { return PR_FALSE; } /* The 'share' part should have at least one character. */ p++; if (*p == '\0' || _PR_IS_SLASH(*p)) { return PR_FALSE; } /* look for the final slash */ do { p = _mbsinc(p); } while (*p != '\0' && !_PR_IS_SLASH(*p)); if (_PR_IS_SLASH(*p) && p[1] != '\0') { return PR_FALSE; } if (*p == '\0') { /* * GetDriveType() doesn't work correctly if the * path is of the form \\server\share, so we add * a final slash temporarily. */ if ((p + 1) < (fn + buflen)) { *p++ = '\\'; *p = '\0'; slashAdded = PR_TRUE; } else { return PR_FALSE; /* name too long */ } } rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE; /* restore the 'fn' buffer */ if (slashAdded) { *--p = '\0'; } } return rv; } PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) { WIN32_FILE_ATTRIBUTE_DATA findFileData; if (NULL == fn || '\0' == *fn) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (!GetFileAttributesEx(fn, GetFileExInfoStandard, &findFileData)) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { info->type = PR_FILE_DIRECTORY; } else { info->type = PR_FILE_FILE; } info->size = findFileData.nFileSizeHigh; info->size = (info->size << 32) + findFileData.nFileSizeLow; _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime); if (0 == findFileData.ftCreationTime.dwLowDateTime && 0 == findFileData.ftCreationTime.dwHighDateTime) { info->creationTime = info->modifyTime; } else { _PR_FileTimeToPRTime(&findFileData.ftCreationTime, &info->creationTime); } return 0; } PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info) { PRFileInfo64 info64; PRInt32 rv = _PR_MD_GETFILEINFO64(fn, &info64); if (0 == rv) { info->type = info64.type; info->size = (PRUint32) info64.size; info->modifyTime = info64.modifyTime; info->creationTime = info64.creationTime; } return rv; } PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info) { int rv; BY_HANDLE_FILE_INFORMATION hinfo; rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo); if (rv == FALSE) { _PR_MD_MAP_FSTAT_ERROR(GetLastError()); return -1; } if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_FILE; info->size = hinfo.nFileSizeHigh; info->size = (info->size << 32) + hinfo.nFileSizeLow; _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime) ); _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime) ); return 0; } PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info) { int rv; BY_HANDLE_FILE_INFORMATION hinfo; rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo); if (rv == FALSE) { _PR_MD_MAP_FSTAT_ERROR(GetLastError()); return -1; } if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_FILE; info->size = hinfo.nFileSizeLow; _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime) ); _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime) ); return 0; } PRInt32 _PR_MD_RENAME(const char *from, const char *to) { /* Does this work with dot-relative pathnames? */ if (MoveFile(from, to)) { return 0; } else { _PR_MD_MAP_RENAME_ERROR(GetLastError()); return -1; } } PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how) { PRInt32 rv; switch (how) { case PR_ACCESS_WRITE_OK: rv = _access(name, 02); break; case PR_ACCESS_READ_OK: rv = _access(name, 04); break; case PR_ACCESS_EXISTS: rv = _access(name, 00); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (rv < 0) { _PR_MD_MAP_ACCESS_ERROR(errno); } return rv; } PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode) { /* XXXMB - how to translate the "mode"??? */ if (CreateDirectory(name, NULL)) { return 0; } else { _PR_MD_MAP_MKDIR_ERROR(GetLastError()); return -1; } } PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode) { BOOL rv; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } rv = CreateDirectory(name, lpSA); if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (rv) { return 0; } else { _PR_MD_MAP_MKDIR_ERROR(GetLastError()); return -1; } } PRInt32 _PR_MD_RMDIR(const char *name) { if (RemoveDirectory(name)) { return 0; } else { _PR_MD_MAP_RMDIR_ERROR(GetLastError()); return -1; } } PRStatus _PR_MD_LOCKFILE(PROsfd f) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return PR_FAILURE; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); rv = LockFileEx((HANDLE)f, LOCKFILE_EXCLUSIVE_LOCK, 0, 0x7fffffff, 0, &me->md.overlapped.overlapped); if (_native_threads_only) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return PR_FAILURE; } _PR_THREAD_UNLOCK(me); if (rv == FALSE) { err = GetLastError(); PR_ASSERT(err != ERROR_IO_PENDING); _PR_MD_MAP_LOCKF_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; } /* HACK AROUND NT BUG * NT 3.51 has a bug. In NT 3.51, if LockFileEx returns true, you * don't get any completion on the completion port. This is a bug. * * They fixed it on NT4.0 so that you do get a completion. * * If we pretend we won't get a completion, NSPR gets confused later * when the unexpected completion arrives. If we assume we do get * a completion, we hang on 3.51. Worse, Microsoft informs me that the * behavior varies on 3.51 depending on if you are using a network * file system or a local disk! * * Solution: For now, _nt_version_gets_lockfile_completion is set * depending on whether or not this system is EITHER * - running NT 4.0 * - running NT 3.51 with a service pack greater than 5. * * In the meantime, this code may not work on network file systems. * */ if ( rv == FALSE && ((err = GetLastError()) != ERROR_IO_PENDING)) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return PR_FAILURE; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_LOCKF_ERROR(err); return PR_FAILURE; } #ifdef _NEED_351_FILE_LOCKING_HACK else if (rv) { /* If this is NT 3.51 and the file is local, then we won't get a * completion back from LockFile when it succeeded. */ if (_nt_version_gets_lockfile_completion == PR_FALSE) { if ( IsFileLocal((HANDLE)f) == _PR_LOCAL_FILE) { me->io_pending = PR_FALSE; me->state = _PR_RUNNING; return PR_SUCCESS; } } } #endif /* _NEED_351_FILE_LOCKING_HACK */ if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; _PR_THREAD_UNLOCK(me); return PR_FAILURE; } if (me->md.blocked_io_status == 0) { _PR_MD_MAP_LOCKF_ERROR(me->md.blocked_io_error); return PR_FAILURE; } return PR_SUCCESS; } PRStatus _PR_MD_TLOCKFILE(PROsfd f) { PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return PR_FAILURE; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); _PR_THREAD_LOCK(me); if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return -1; } me->io_pending = PR_TRUE; me->state = _PR_IO_WAIT; _PR_THREAD_UNLOCK(me); rv = LockFileEx((HANDLE)f, LOCKFILE_FAIL_IMMEDIATELY|LOCKFILE_EXCLUSIVE_LOCK, 0, 0x7fffffff, 0, &me->md.overlapped.overlapped); if (_native_threads_only) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return PR_FAILURE; } _PR_THREAD_UNLOCK(me); if (rv == FALSE) { err = GetLastError(); PR_ASSERT(err != ERROR_IO_PENDING); _PR_MD_MAP_LOCKF_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; } if ( rv == FALSE && ((err = GetLastError()) != ERROR_IO_PENDING)) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return PR_FAILURE; } _PR_THREAD_UNLOCK(me); _PR_MD_MAP_LOCKF_ERROR(err); return PR_FAILURE; } #ifdef _NEED_351_FILE_LOCKING_HACK else if (rv) { /* If this is NT 3.51 and the file is local, then we won't get a * completion back from LockFile when it succeeded. */ if (_nt_version_gets_lockfile_completion == PR_FALSE) { if ( IsFileLocal((HANDLE)f) == _PR_LOCAL_FILE) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return PR_FAILURE; } _PR_THREAD_UNLOCK(me); return PR_SUCCESS; } } } #endif /* _NEED_351_FILE_LOCKING_HACK */ if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { _PR_THREAD_LOCK(me); me->io_pending = PR_FALSE; me->state = _PR_RUNNING; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); _PR_THREAD_UNLOCK(me); return PR_FAILURE; } _PR_THREAD_UNLOCK(me); return PR_FAILURE; } if (me->md.blocked_io_status == 0) { _PR_MD_MAP_LOCKF_ERROR(me->md.blocked_io_error); return PR_FAILURE; } return PR_SUCCESS; } PRStatus _PR_MD_UNLOCKFILE(PROsfd f) { PRInt32 rv; PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->io_suspended) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return PR_FAILURE; } memset(&(me->md.overlapped.overlapped), 0, sizeof(OVERLAPPED)); rv = UnlockFileEx((HANDLE)f, 0, 0x7fffffff, 0, &me->md.overlapped.overlapped); if (rv) return PR_SUCCESS; else { int err = GetLastError(); _PR_MD_MAP_LOCKF_ERROR(err); return PR_FAILURE; } } void _PR_MD_MAKE_NONBLOCK(PRFileDesc *f) { /* * On NT, we either call _md_Associate() or _md_MakeNonblock(), * depending on whether the socket is blocking or not. * * Once we associate a socket with the io completion port, * there is no way to disassociate it from the io completion * port. So we have to call _md_Associate/_md_MakeNonblock * lazily. */ } #ifdef _NEED_351_FILE_LOCKING_HACK /*************** ** ** Lockfile hacks ** ** The following code is a hack to work around a microsoft bug with lockfile. ** The problem is that on NT 3.51, if LockFileEx() succeeds, you never ** get a completion back for files that are on local disks. So, we need to ** know if a file is local or remote so we can tell if we should expect ** a completion. ** ** The only way to check if a file is local or remote based on the handle is ** to get the serial number for the volume it is mounted on and then to ** compare that with mounted drives. This code caches the volume numbers of ** fixed disks and does a relatively quick check. ** ** Locking: Since the only thing we ever do when multithreaded is a 32bit ** assignment, we probably don't need locking. It is included just ** case anyway. ** ** Limitations: Does not work on floppies because they are too slow ** Unknown if it will work on wierdo 3rd party file systems ** **************** */ /* There can only be 26 drive letters on NT */ #define _PR_MAX_DRIVES 26 _MDLock cachedVolumeLock; DWORD dwCachedVolumeSerialNumbers[_PR_MAX_DRIVES] = {0}; DWORD dwLastCachedDrive = 0; DWORD dwRemoveableDrivesToCheck = 0; /* bitmask for removeable drives */ PRBool IsFileLocalInit() { TCHAR lpBuffer[_PR_MAX_DRIVES*5]; DWORD nBufferLength = _PR_MAX_DRIVES*5; DWORD nBufferNeeded = GetLogicalDriveStrings(0, NULL); DWORD dwIndex = 0; DWORD dwDriveType; DWORD dwVolumeSerialNumber; DWORD dwDriveIndex = 0; DWORD oldmode = (DWORD) -1; _MD_NEW_LOCK(&cachedVolumeLock); nBufferNeeded = GetLogicalDriveStrings(nBufferLength, lpBuffer); if (nBufferNeeded == 0 || nBufferNeeded > nBufferLength) return PR_FALSE; // Calling GetVolumeInformation on a removeable drive where the // disk is currently removed will cause a dialog box to the // console. This is not good. // Temporarily disable the SEM_FAILCRITICALERRORS to avoid the // damn dialog. dwCachedVolumeSerialNumbers[dwDriveIndex] = 0; oldmode = SetErrorMode(SEM_FAILCRITICALERRORS); // now loop through the logical drives while(lpBuffer[dwIndex] != TEXT('\0')) { // skip the floppy drives. This is *SLOW* if ((lpBuffer[dwIndex] == TEXT('A')) || (lpBuffer[dwIndex] == TEXT('B'))) /* Skip over floppies */; else { dwDriveIndex = (lpBuffer[dwIndex] - TEXT('A')); dwDriveType = GetDriveType(&lpBuffer[dwIndex]); switch(dwDriveType) { // Ignore these drive types case 0: case 1: case DRIVE_REMOTE: default: // If the drive type is unknown, ignore it. break; // Removable media drives can have different serial numbers // at different times, so cache the current serial number // but keep track of them so they can be rechecked if necessary. case DRIVE_REMOVABLE: // CDROM is a removable media case DRIVE_CDROM: // no idea if ramdisks can change serial numbers or not // but it doesn't hurt to treat them as removable. case DRIVE_RAMDISK: // Here is where we keep track of removable drives. dwRemoveableDrivesToCheck |= 1 << dwDriveIndex; // removable drives fall through to fixed drives and get cached. case DRIVE_FIXED: // cache volume serial numbers. if (GetVolumeInformation( &lpBuffer[dwIndex], NULL, 0, &dwVolumeSerialNumber, NULL, NULL, NULL, 0) ) { if (dwLastCachedDrive < dwDriveIndex) dwLastCachedDrive = dwDriveIndex; dwCachedVolumeSerialNumbers[dwDriveIndex] = dwVolumeSerialNumber; } break; } } dwIndex += lstrlen(&lpBuffer[dwIndex]) +1; } if (oldmode != (DWORD) -1) { SetErrorMode(oldmode); oldmode = (DWORD) -1; } return PR_TRUE; } PRInt32 IsFileLocal(HANDLE hFile) { DWORD dwIndex = 0, dwMask; BY_HANDLE_FILE_INFORMATION Info; TCHAR szDrive[4] = TEXT("C:\\"); DWORD dwVolumeSerialNumber; DWORD oldmode = (DWORD) -1; int rv = _PR_REMOTE_FILE; if (!GetFileInformationByHandle(hFile, &Info)) return -1; // look to see if the volume serial number has been cached. _MD_LOCK(&cachedVolumeLock); while(dwIndex <= dwLastCachedDrive) if (dwCachedVolumeSerialNumbers[dwIndex++] == Info.dwVolumeSerialNumber) { _MD_UNLOCK(&cachedVolumeLock); return _PR_LOCAL_FILE; } _MD_UNLOCK(&cachedVolumeLock); // volume serial number not found in the cache. Check removable files. // removable drives are noted as a bitmask. If the bit associated with // a specific drive is set, then we should query its volume serial number // as its possible it has changed. dwMask = dwRemoveableDrivesToCheck; dwIndex = 0; while(dwMask) { while(!(dwMask & 1)) { dwIndex++; dwMask = dwMask >> 1; } szDrive[0] = TEXT('A')+ (TCHAR) dwIndex; // Calling GetVolumeInformation on a removeable drive where the // disk is currently removed will cause a dialog box to the // console. This is not good. // Temporarily disable the SEM_FAILCRITICALERRORS to avoid the // dialog. oldmode = SetErrorMode(SEM_FAILCRITICALERRORS); if (GetVolumeInformation( szDrive, NULL, 0, &dwVolumeSerialNumber, NULL, NULL, NULL, 0) ) { if (dwVolumeSerialNumber == Info.dwVolumeSerialNumber) { _MD_LOCK(&cachedVolumeLock); if (dwLastCachedDrive < dwIndex) dwLastCachedDrive = dwIndex; dwCachedVolumeSerialNumbers[dwIndex] = dwVolumeSerialNumber; _MD_UNLOCK(&cachedVolumeLock); rv = _PR_LOCAL_FILE; } } if (oldmode != (DWORD) -1) { SetErrorMode(oldmode); oldmode = (DWORD) -1; } if (rv == _PR_LOCAL_FILE) return _PR_LOCAL_FILE; dwIndex++; dwMask = dwMask >> 1; } return _PR_REMOTE_FILE; } #endif /* _NEED_351_FILE_LOCKING_HACK */ PR_IMPLEMENT(PRStatus) PR_NT_CancelIo(PRFileDesc *fd) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRBool fWait; PRFileDesc *bottom; bottom = PR_GetIdentitiesLayer(fd, PR_NSPR_IO_LAYER); if (!me->io_suspended || (NULL == bottom) || (me->io_fd != bottom->secret->md.osfd)) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return PR_FAILURE; } /* * The CancelIO operation has to be issued by the same NT thread that * issued the I/O operation */ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || (me->cpu == me->md.thr_bound_cpu)); if (me->io_pending) { if (!CancelIo((HANDLE)bottom->secret->md.osfd)) { PR_SetError(PR_INVALID_STATE_ERROR, GetLastError()); return PR_FAILURE; } } _PR_THREAD_LOCK(me); fWait = me->io_pending; me->io_suspended = PR_FALSE; me->state = _PR_IO_WAIT; me->md.interrupt_disabled = PR_TRUE; _PR_THREAD_UNLOCK(me); if (fWait) _NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(me->io_suspended == PR_FALSE); PR_ASSERT(me->io_pending == PR_FALSE); _PR_THREAD_LOCK(me); me->md.interrupt_disabled = PR_FALSE; me->md.thr_bound_cpu = NULL; me->io_suspended = PR_FALSE; me->io_pending = PR_FALSE; me->state = _PR_RUNNING; _PR_THREAD_UNLOCK(me); return PR_SUCCESS; } static PROsfd _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr *addr, int *addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; SOCKET sock; PRInt32 rv, err; fd_set rd; struct timeval tv, *tvp; FD_ZERO(&rd); FD_SET((SOCKET)osfd, &rd); if (timeout == PR_INTERVAL_NO_TIMEOUT) { while ((sock = accept(osfd, addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { if ((rv = _PR_NTFiberSafeSelect(0, &rd, NULL, NULL, NULL)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } } else { _PR_MD_MAP_ACCEPT_ERROR(err); break; } } } else if (timeout == PR_INTERVAL_NO_WAIT) { if ((sock = accept(osfd, addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } else { _PR_MD_MAP_ACCEPT_ERROR(err); } } } else { retry: if ((sock = accept(osfd, addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; rv = _PR_NTFiberSafeSelect(0, &rd, NULL, NULL, tvp); if (rv > 0) { goto retry; } else if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); } else { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); } } else { _PR_MD_MAP_ACCEPT_ERROR(err); } } } return (PROsfd)sock; } static PRInt32 _nt_nonblock_connect(PRFileDesc *fd, struct sockaddr *addr, int addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv; int err; fd_set wr, ex; struct timeval tv, *tvp; int len; if ((rv = connect(osfd, addr, addrlen)) == -1) { if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) { if ( timeout == PR_INTERVAL_NO_TIMEOUT ) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&wr); FD_ZERO(&ex); FD_SET((SOCKET)osfd, &wr); FD_SET((SOCKET)osfd, &ex); if ((rv = _PR_NTFiberSafeSelect(0, NULL, &wr, &ex, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); return rv; } if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); return -1; } /* Call Sleep(0) to work around a Winsock timeing bug. */ Sleep(0); if (FD_ISSET((SOCKET)osfd, &ex)) { len = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == SOCKET_ERROR) { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return -1; } _PR_MD_MAP_CONNECT_ERROR(err); return -1; } PR_ASSERT(FD_ISSET((SOCKET)osfd, &wr)); rv = 0; } else { _PR_MD_MAP_CONNECT_ERROR(err); } } return rv; } static PRInt32 _nt_nonblock_recv(PRFileDesc *fd, char *buf, int len, int flags, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; struct timeval tv, *tvp; fd_set rd; int osflags; if (0 == flags) { osflags = 0; } else { PR_ASSERT(PR_MSG_PEEK == flags); osflags = MSG_PEEK; } while ((rv = recv(osfd,buf,len,osflags)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { FD_ZERO(&rd); FD_SET((SOCKET)osfd, &rd); if (timeout == PR_INTERVAL_NO_TIMEOUT) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } if ((rv = _PR_NTFiberSafeSelect(0, &rd, NULL, NULL, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } else if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } } else { _PR_MD_MAP_RECV_ERROR(err); break; } } return(rv); } static PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; struct timeval tv, *tvp; fd_set wd; PRInt32 bytesSent = 0; while(bytesSent < len) { while ((rv = send(osfd,buf,len,0)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { if ( timeout == PR_INTERVAL_NO_TIMEOUT ) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&wd); FD_SET((SOCKET)osfd, &wd); if ((rv = _PR_NTFiberSafeSelect(0, NULL, &wd, NULL, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); return -1; } if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); return -1; } } else { _PR_MD_MAP_SEND_ERROR(err); return -1; } } bytesSent += rv; if (fd->secret->nonblocking) { break; } if (bytesSent < len) { if ( timeout == PR_INTERVAL_NO_TIMEOUT ) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&wd); FD_SET((SOCKET)osfd, &wd); if ((rv = _PR_NTFiberSafeSelect(0, NULL, &wd, NULL, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); return -1; } if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); return -1; } } } return bytesSent; } static PRInt32 _nt_nonblock_writev(PRFileDesc *fd, const PRIOVec *iov, int size, PRIntervalTime timeout) { int index; int sent = 0; int rv; for (index=0; index 0) sent += rv; if ( rv != iov[index].iov_len ) { if (rv < 0) { if (fd->secret->nonblocking && (PR_GetError() == PR_WOULD_BLOCK_ERROR) && (sent > 0)) { return sent; } else { return -1; } } /* Only a nonblocking socket can have partial sends */ PR_ASSERT(fd->secret->nonblocking); return sent; } } return sent; } static PRInt32 _nt_nonblock_sendto( PRFileDesc *fd, const char *buf, int len, const struct sockaddr *addr, int addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; struct timeval tv, *tvp; fd_set wd; PRInt32 bytesSent = 0; while(bytesSent < len) { while ((rv = sendto(osfd,buf,len,0, addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { if ( timeout == PR_INTERVAL_NO_TIMEOUT ) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&wd); FD_SET((SOCKET)osfd, &wd); if ((rv = _PR_NTFiberSafeSelect(0, NULL, &wd, NULL, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); return -1; } if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); return -1; } } else { _PR_MD_MAP_SENDTO_ERROR(err); return -1; } } bytesSent += rv; if (fd->secret->nonblocking) { break; } if (bytesSent < len) { if ( timeout == PR_INTERVAL_NO_TIMEOUT ) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&wd); FD_SET((SOCKET)osfd, &wd); if ((rv = _PR_NTFiberSafeSelect(0, NULL, &wd, NULL, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); return -1; } if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); return -1; } } } return bytesSent; } static PRInt32 _nt_nonblock_recvfrom(PRFileDesc *fd, char *buf, int len, struct sockaddr *addr, int *addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; struct timeval tv, *tvp; fd_set rd; while ((rv = recvfrom(osfd,buf,len,0,addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { if (timeout == PR_INTERVAL_NO_TIMEOUT) { tvp = NULL; } else { tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; } FD_ZERO(&rd); FD_SET((SOCKET)osfd, &rd); if ((rv = _PR_NTFiberSafeSelect(0, &rd, NULL, NULL, tvp)) == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } else if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } } else { _PR_MD_MAP_RECVFROM_ERROR(err); break; } } return(rv); } /* * UDP support: the continuation thread functions and recvfrom and sendto. */ static void pt_InsertTimedInternal(pt_Continuation *op) { PRInt32 delta = 0; pt_Continuation *t_op = NULL; PRIntervalTime now = PR_IntervalNow(), op_tmo, qd_tmo; /* * If this element operation isn't timed, it gets queued at the * end of the list (just after pt_tq.tail) and we're * finishd early. */ if (PR_INTERVAL_NO_TIMEOUT == op->timeout) { t_op = pt_tq.tail; /* put it at the end */ goto done; } /* * The rest of this routine actaully deals with timed ops. */ if (NULL != pt_tq.op) { /* * To find where in the list to put the new operation, form * the absolute time the operations in question will expire. * * The new operation ('op') will expire at now() + op->timeout. * * The operation that will time out furthest in the future will * do so at pt_tq.epoch + pt_tq.op->timeout. * * Subsequently earlier timeouts are computed based on the latter * knowledge by subracting the timeout deltas that are stored in * the operation list. There are operation[n]->timeout ticks * between the expiration of operation[n-1] and operation[n].e e * * Therefore, the operation[n-1] will expire operation[n]->timeout * ticks prior to operation[n]. * * This should be easy! */ t_op = pt_tq.op; /* running pointer to queued op */ op_tmo = now + op->timeout; /* that's in absolute ticks */ qd_tmo = pt_tq.epoch + t_op->timeout; /* likewise */ do { /* * If 'op' expires later than t_op, then insert 'op' just * ahead of t_op. Otherwise, compute when operation[n-1] * expires and try again. * * The actual different between the expiriation of 'op' * and the current operation what becomes the new operaton's * timeout interval. That interval is also subtracted from * the interval of the operation immediately following where * we stick 'op' (unless the next one isn't timed). The new * timeout assigned to 'op' takes into account the values of * now() and when the previous intervals were compured. */ delta = op_tmo - qd_tmo; if (delta >= 0) { op->timeout += (now - pt_tq.epoch); goto done; } qd_tmo -= t_op->timeout; /* previous operaton expiration */ t_op = t_op->prev; /* point to previous operation */ if (NULL != t_op) qd_tmo += t_op->timeout; } while (NULL != t_op); /* * If we got here we backed off the head of the list. That means that * this timed entry has to go at the head of the list. This is just * about like having an empty timer list. */ delta = op->timeout; /* $$$ is this right? */ } done: /* * Insert 'op' into the queue just after t_op or if t_op is null, * at the head of the list. * * If t_op is NULL, the list is currently empty and this is pretty * easy. */ if (NULL == t_op) { op->prev = NULL; op->next = pt_tq.head; pt_tq.head = op; if (NULL == pt_tq.tail) pt_tq.tail = op; else op->next->prev = op; } else { op->prev = t_op; op->next = t_op->next; if (NULL != op->prev) op->prev->next = op; if (NULL != op->next) op->next->prev = op; if (t_op == pt_tq.tail) pt_tq.tail = op; } /* * Are we adjusting our epoch, etc? Are we replacing * what was previously the element due to expire furthest * out in the future? Is this even a timed operation? */ if (PR_INTERVAL_NO_TIMEOUT != op->timeout) { if ((NULL == pt_tq.op) /* we're the one and only */ || (t_op == pt_tq.op)) /* we're replacing */ { pt_tq.op = op; pt_tq.epoch = now; } } pt_tq.op_count += 1; } /* pt_InsertTimedInternal */ /* * function: pt_FinishTimed * * Takes the finished operation out of the timed queue. It * notifies the initiating thread that the opertions is * complete and returns to the caller the value of the next * operation in the list (or NULL). */ static pt_Continuation *pt_FinishTimedInternal(pt_Continuation *op) { pt_Continuation *next; /* remove this one from the list */ if (NULL == op->prev) pt_tq.head = op->next; else op->prev->next = op->next; if (NULL == op->next) pt_tq.tail = op->prev; else op->next->prev = op->prev; /* did we happen to hit the timed op? */ if (op == pt_tq.op) pt_tq.op = op->prev; next = op->next; op->next = op->prev = NULL; op->status = pt_continuation_done; pt_tq.op_count -= 1; #if defined(DEBUG) pt_debug.continuationsServed += 1; #endif PR_NotifyCondVar(op->complete); return next; } /* pt_FinishTimedInternal */ static void ContinuationThread(void *arg) { /* initialization */ fd_set readSet, writeSet, exceptSet; struct timeval tv; SOCKET *pollingList = 0; /* list built for polling */ PRIntn pollingListUsed; /* # entries used in the list */ PRIntn pollingListNeeded; /* # entries needed this time */ PRIntn pollingSlotsAllocated = 0; /* # entries available in list */ PRIntervalTime mx_select_ticks = PR_MillisecondsToInterval(PT_DEFAULT_SELECT_MSEC); /* do some real work */ while (1) { PRIntn rv; PRStatus status; PRIntn pollIndex; pt_Continuation *op; PRIntervalTime now = PR_IntervalNow(); PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; PR_Lock(pt_tq.ml); while (NULL == pt_tq.head) { status = PR_WaitCondVar(pt_tq.new_op, PR_INTERVAL_NO_TIMEOUT); if ((PR_FAILURE == status) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break; } pollingListNeeded = pt_tq.op_count; PR_Unlock(pt_tq.ml); /* Okay. We're history */ if ((PR_FAILURE == status) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break; /* * We are not holding the pt_tq.ml lock now, so more items may * get added to pt_tq during this window of time. We hope * that 10 more spaces in the polling list should be enough. */ FD_ZERO(&readSet); FD_ZERO(&writeSet); FD_ZERO(&exceptSet); pollingListNeeded += 10; if (pollingListNeeded > pollingSlotsAllocated) { if (NULL != pollingList) PR_DELETE(pollingList); pollingList = PR_MALLOC(pollingListNeeded * sizeof(PRPollDesc)); PR_ASSERT(NULL != pollingList); pollingSlotsAllocated = pollingListNeeded; } #if defined(DEBUG) if (pollingListNeeded > pt_debug.pollingListMax) pt_debug.pollingListMax = pollingListUsed; #endif /* * Build up a polling list. * This list is sorted on time. Operations that have been * interrupted are completed and not included in the list. * There is an assertion that the operation is in progress. */ pollingListUsed = 0; PR_Lock(pt_tq.ml); for (op = pt_tq.head; NULL != op;) { if (pt_continuation_abort == op->status) { op->result.code = -1; op->syserrno = WSAEINTR; op = pt_FinishTimedInternal(op); } else { PR_ASSERT(pt_continuation_done != op->status); op->status = pt_continuation_inprogress; if (op->event & PR_POLL_READ) { FD_SET(op->arg1.osfd, &readSet); } if (op->event & PR_POLL_WRITE) { FD_SET(op->arg1.osfd, &writeSet); } if (op->event & PR_POLL_EXCEPT) { FD_SET(op->arg1.osfd, &exceptSet); } pollingList[pollingListUsed] = op->arg1.osfd; pollingListUsed += 1; if (pollingListUsed == pollingSlotsAllocated) break; op = op->next; } } PR_Unlock(pt_tq.ml); /* * If 'op' isn't NULL at this point, then we didn't get to * the end of the list. That means that more items got added * to the list than we anticipated. So, forget this iteration, * go around the horn again. * One would hope this doesn't happen all that often. */ if (NULL != op) { #if defined(DEBUG) pt_debug.predictionsFoiled += 1; /* keep track */ #endif continue; /* make it rethink things */ } /* there's a chance that all ops got blown away */ if (NULL == pt_tq.head) continue; /* if not, we know this is the shortest timeout */ timeout = pt_tq.head->timeout; /* * We don't want to wait forever on this poll. So keep * the interval down. The operations, if they are timed, * still have to timeout, while those that are not timed * should persist forever. But they may be aborted. That's * what this anxiety is all about. */ if (timeout > mx_select_ticks) timeout = mx_select_ticks; if (PR_INTERVAL_NO_TIMEOUT != pt_tq.head->timeout) pt_tq.head->timeout -= timeout; tv.tv_sec = PR_IntervalToSeconds(timeout); tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC; rv = select(0, &readSet, &writeSet, &exceptSet, &tv); if (0 == rv) /* poll timed out - what about leading op? */ { if (0 == pt_tq.head->timeout) { /* * The leading element of the timed queue has timed * out. Get rid of it. In any case go around the * loop again, computing the polling list, checking * for interrupted operations. */ PR_Lock(pt_tq.ml); do { pt_tq.head->result.code = -1; pt_tq.head->syserrno = WSAETIMEDOUT; op = pt_FinishTimedInternal(pt_tq.head); } while ((NULL != op) && (0 == op->timeout)); PR_Unlock(pt_tq.ml); } continue; } if (-1 == rv && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS)) { continue; /* go around the loop again */ } /* * select() says that something in our list is ready for some more * action or is an invalid fd. Find it, load up the operation and * see what happens. */ PR_ASSERT(rv > 0 || WSAGetLastError() == WSAENOTSOCK); /* * $$$ There's a problem here. I'm running the operations list * and I'm not holding any locks. I don't want to hold the lock * and do the operation, so this is really messed up.. * * This may work out okay. The rule is that only this thread, * the continuation thread, can remove elements from the list. * Therefore, the list is at worst, longer than when we built * the polling list. */ op = pt_tq.head; for (pollIndex = 0; pollIndex < pollingListUsed; ++pollIndex) { PRInt16 revents = 0; PR_ASSERT(NULL != op); /* * This one wants attention. Redo the operation. * We know that there can only be more elements * in the op list than we knew about when we created * the poll list. Therefore, we might have to skip * a few ops to find the right one to operation on. */ while (pollingList[pollIndex] != op->arg1.osfd ) { op = op->next; PR_ASSERT(NULL != op); } if (FD_ISSET(op->arg1.osfd, &readSet)) { revents |= PR_POLL_READ; } if (FD_ISSET(op->arg1.osfd, &writeSet)) { revents |= PR_POLL_WRITE; } if (FD_ISSET(op->arg1.osfd, &exceptSet)) { revents |= PR_POLL_EXCEPT; } /* * Sip over all those not in progress. They'll be * pruned next time we build a polling list. Call * the continuation function. If it reports completion, * finish off the operation. */ if (revents && (pt_continuation_inprogress == op->status) && (op->function(op, revents))) { PR_Lock(pt_tq.ml); op = pt_FinishTimedInternal(op); PR_Unlock(pt_tq.ml); } } } if (NULL != pollingList) PR_DELETE(pollingList); } /* ContinuationThread */ static int pt_Continue(pt_Continuation *op) { PRStatus rv; /* Finish filling in the blank slots */ op->status = pt_continuation_sumbitted; op->complete = PR_NewCondVar(pt_tq.ml); PR_Lock(pt_tq.ml); /* we provide the locking */ pt_InsertTimedInternal(op); /* insert in the structure */ PR_NotifyCondVar(pt_tq.new_op); /* notify the continuation thread */ while (pt_continuation_done != op->status) /* wait for completion */ { rv = PR_WaitCondVar(op->complete, PR_INTERVAL_NO_TIMEOUT); /* * If we get interrupted, we set state the continuation thread will * see and allow it to finish the I/O operation w/ error. That way * the rule that only the continuation thread is removing elements * from the list is still valid. * * Don't call interrupt on the continuation thread. That'll just * piss him off. He's cycling around at least every mx_select_ticks * anyhow and should notice the request in there. */ if ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) op->status = pt_continuation_abort; /* our status */ } PR_Unlock(pt_tq.ml); /* we provide the locking */ PR_DestroyCondVar(op->complete); return op->result.code; /* and the primary answer */ } /* pt_Continue */ static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents) { PRIntn bytes = sendto( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags, (struct sockaddr*)op->arg5.addr, sizeof(*(op->arg5.addr))); op->syserrno = WSAGetLastError(); if (bytes > 0) /* this is progress */ { char *bp = op->arg2.buffer; bp += bytes; /* adjust the buffer pointer */ op->arg2.buffer = bp; op->result.code += bytes; /* accumulate the number sent */ op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else return ((-1 == bytes) && (WSAEWOULDBLOCK == op->syserrno)) ? PR_FALSE : PR_TRUE; } /* pt_sendto_cont */ static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents) { PRIntn addr_len = sizeof(*(op->arg5.addr)); op->result.code = recvfrom( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags, (struct sockaddr*)op->arg5.addr, &addr_len); op->syserrno = WSAGetLastError(); return ((-1 == op->result.code) && (WSAEWOULDBLOCK == op->syserrno)) ? PR_FALSE : PR_TRUE; } /* pt_recvfrom_cont */ static PRInt32 pt_SendTo( SOCKET osfd, const void *buf, PRInt32 amount, PRInt32 flags, const PRNetAddr *addr, PRIntn addrlen, PRIntervalTime timeout) { PRInt32 bytes = -1, err; PRBool fNeedContinue = PR_FALSE; bytes = sendto( osfd, buf, amount, flags, (struct sockaddr*)addr, PR_NETADDR_SIZE(addr)); if (bytes == -1) { if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) fNeedContinue = PR_TRUE; else _PR_MD_MAP_SENDTO_ERROR(err); } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.arg4.flags = flags; op.arg5.addr = (PRNetAddr*)addr; op.timeout = timeout; op.result.code = 0; /* initialize the number sent */ op.function = pt_sendto_cont; op.event = PR_POLL_WRITE | PR_POLL_EXCEPT; bytes = pt_Continue(&op); if (bytes < 0) { WSASetLastError(op.syserrno); _PR_MD_MAP_SENDTO_ERROR(op.syserrno); } } return bytes; } /* pt_SendTo */ static PRInt32 pt_RecvFrom(SOCKET osfd, void *buf, PRInt32 amount, PRInt32 flags, PRNetAddr *addr, PRIntn *addr_len, PRIntervalTime timeout) { PRInt32 bytes = -1, err; PRBool fNeedContinue = PR_FALSE; bytes = recvfrom( osfd, buf, amount, flags, (struct sockaddr*)addr, addr_len); if (bytes == -1) { if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) fNeedContinue = PR_TRUE; else _PR_MD_MAP_RECVFROM_ERROR(err); } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.arg4.flags = flags; op.arg5.addr = addr; op.timeout = timeout; op.function = pt_recvfrom_cont; op.event = PR_POLL_READ | PR_POLL_EXCEPT; bytes = pt_Continue(&op); if (bytes < 0) { WSASetLastError(op.syserrno); _PR_MD_MAP_RECVFROM_ERROR(op.syserrno); } } return bytes; } /* pt_RecvFrom */ nspr-4.11/nspr/pr/src/md/windows/ntmisc.c0000644000000000000000000010056412623070344016503 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * ntmisc.c * */ #include "primpl.h" #include /* for fabs() */ #include char *_PR_MD_GET_ENV(const char *name) { return getenv(name); } /* ** _PR_MD_PUT_ENV() -- add or change environment variable ** ** */ PRIntn _PR_MD_PUT_ENV(const char *name) { return(putenv(name)); } /* ************************************************************************** ************************************************************************** ** ** Date and time routines ** ************************************************************************** ************************************************************************** */ /* * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME. * We store the value in a PRTime variable for convenience. */ #ifdef __GNUC__ const PRTime _pr_filetime_offset = 116444736000000000LL; const PRTime _pr_filetime_divisor = 10LL; #else const PRTime _pr_filetime_offset = 116444736000000000i64; const PRTime _pr_filetime_divisor = 10i64; #endif #ifdef WINCE #define FILETIME_TO_INT64(ft) \ (((PRInt64)ft.dwHighDateTime) << 32 | (PRInt64)ft.dwLowDateTime) static void LowResTime(LPFILETIME lpft) { GetCurrentFT(lpft); } typedef struct CalibrationData { long double freq; /* The performance counter frequency */ long double offset; /* The low res 'epoch' */ long double timer_offset; /* The high res 'epoch' */ /* The last high res time that we returned since recalibrating */ PRInt64 last; PRBool calibrated; CRITICAL_SECTION data_lock; CRITICAL_SECTION calibration_lock; PRInt64 granularity; } CalibrationData; static CalibrationData calibration; typedef void (*GetSystemTimeAsFileTimeFcn)(LPFILETIME); static GetSystemTimeAsFileTimeFcn ce6_GetSystemTimeAsFileTime = NULL; static void NowCalibrate(void) { FILETIME ft, ftStart; LARGE_INTEGER liFreq, now; if (calibration.freq == 0.0) { if(!QueryPerformanceFrequency(&liFreq)) { /* High-performance timer is unavailable */ calibration.freq = -1.0; } else { calibration.freq = (long double) liFreq.QuadPart; } } if (calibration.freq > 0.0) { PRInt64 calibrationDelta = 0; /* * By wrapping a timeBegin/EndPeriod pair of calls around this loop, * the loop seems to take much less time (1 ms vs 15ms) on Vista. */ timeBeginPeriod(1); LowResTime(&ftStart); do { LowResTime(&ft); } while (memcmp(&ftStart,&ft, sizeof(ft)) == 0); timeEndPeriod(1); calibration.granularity = (FILETIME_TO_INT64(ft) - FILETIME_TO_INT64(ftStart))/10; QueryPerformanceCounter(&now); calibration.offset = (long double) FILETIME_TO_INT64(ft); calibration.timer_offset = (long double) now.QuadPart; /* * The windows epoch is around 1600. The unix epoch is around 1970. * _pr_filetime_offset is the difference (in windows time units which * are 10 times more highres than the JS time unit) */ calibration.offset -= _pr_filetime_offset; calibration.offset *= 0.1; calibration.last = 0; calibration.calibrated = PR_TRUE; } } #define CALIBRATIONLOCK_SPINCOUNT 0 #define DATALOCK_SPINCOUNT 4096 #define LASTLOCK_SPINCOUNT 4096 void _MD_InitTime(void) { /* try for CE6 GetSystemTimeAsFileTime first */ HANDLE h = GetModuleHandleW(L"coredll.dll"); ce6_GetSystemTimeAsFileTime = (GetSystemTimeAsFileTimeFcn) GetProcAddressA(h, "GetSystemTimeAsFileTime"); /* otherwise go the slow route */ if (ce6_GetSystemTimeAsFileTime == NULL) { memset(&calibration, 0, sizeof(calibration)); NowCalibrate(); InitializeCriticalSection(&calibration.calibration_lock); InitializeCriticalSection(&calibration.data_lock); } } void _MD_CleanupTime(void) { if (ce6_GetSystemTimeAsFileTime == NULL) { DeleteCriticalSection(&calibration.calibration_lock); DeleteCriticalSection(&calibration.data_lock); } } #define MUTEX_SETSPINCOUNT(m, c) /* *----------------------------------------------------------------------- * * PR_Now -- * * Returns the current time in microseconds since the epoch. * The epoch is midnight January 1, 1970 GMT. * The implementation is machine dependent. This is the * implementation for Windows. * Cf. time_t time(time_t *tp) * *----------------------------------------------------------------------- */ PR_IMPLEMENT(PRTime) PR_Now(void) { long double lowresTime, highresTimerValue; FILETIME ft; LARGE_INTEGER now; PRBool calibrated = PR_FALSE; PRBool needsCalibration = PR_FALSE; PRInt64 returnedTime; long double cachedOffset = 0.0; if (ce6_GetSystemTimeAsFileTime) { union { FILETIME ft; PRTime prt; } currentTime; PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); ce6_GetSystemTimeAsFileTime(¤tTime.ft); /* written this way on purpose, since the second term becomes * a constant, and the entire expression is faster to execute. */ return currentTime.prt/_pr_filetime_divisor - _pr_filetime_offset/_pr_filetime_divisor; } do { if (!calibration.calibrated || needsCalibration) { EnterCriticalSection(&calibration.calibration_lock); EnterCriticalSection(&calibration.data_lock); /* Recalibrate only if no one else did before us */ if (calibration.offset == cachedOffset) { /* * Since calibration can take a while, make any other * threads immediately wait */ MUTEX_SETSPINCOUNT(&calibration.data_lock, 0); NowCalibrate(); calibrated = PR_TRUE; /* Restore spin count */ MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT); } LeaveCriticalSection(&calibration.data_lock); LeaveCriticalSection(&calibration.calibration_lock); } /* Calculate a low resolution time */ LowResTime(&ft); lowresTime = ((long double)(FILETIME_TO_INT64(ft) - _pr_filetime_offset)) * 0.1; if (calibration.freq > 0.0) { long double highresTime, diff; DWORD timeAdjustment, timeIncrement; BOOL timeAdjustmentDisabled; /* Default to 15.625 ms if the syscall fails */ long double skewThreshold = 15625.25; /* Grab high resolution time */ QueryPerformanceCounter(&now); highresTimerValue = (long double)now.QuadPart; EnterCriticalSection(&calibration.data_lock); highresTime = calibration.offset + 1000000L * (highresTimerValue-calibration.timer_offset)/calibration.freq; cachedOffset = calibration.offset; /* * On some dual processor/core systems, we might get an earlier * time so we cache the last time that we returned. */ calibration.last = PR_MAX(calibration.last,(PRInt64)highresTime); returnedTime = calibration.last; LeaveCriticalSection(&calibration.data_lock); /* Get an estimate of clock ticks per second from our own test */ skewThreshold = calibration.granularity; /* Check for clock skew */ diff = lowresTime - highresTime; /* * For some reason that I have not determined, the skew can be * up to twice a kernel tick. This does not seem to happen by * itself, but I have only seen it triggered by another program * doing some kind of file I/O. The symptoms are a negative diff * followed by an equally large positive diff. */ if (fabs(diff) > 2*skewThreshold) { if (calibrated) { /* * If we already calibrated once this instance, and the * clock is still skewed, then either the processor(s) are * wildly changing clockspeed or the system is so busy that * we get switched out for long periods of time. In either * case, it would be infeasible to make use of high * resolution results for anything, so let's resort to old * behavior for this call. It's possible that in the * future, the user will want the high resolution timer, so * we don't disable it entirely. */ returnedTime = (PRInt64)lowresTime; needsCalibration = PR_FALSE; } else { /* * It is possible that when we recalibrate, we will return * a value less than what we have returned before; this is * unavoidable. We cannot tell the different between a * faulty QueryPerformanceCounter implementation and user * changes to the operating system time. Since we must * respect user changes to the operating system time, we * cannot maintain the invariant that Date.now() never * decreases; the old implementation has this behavior as * well. */ needsCalibration = PR_TRUE; } } else { /* No detectable clock skew */ returnedTime = (PRInt64)highresTime; needsCalibration = PR_FALSE; } } else { /* No high resolution timer is available, so fall back */ returnedTime = (PRInt64)lowresTime; } } while (needsCalibration); return returnedTime; } #else PR_IMPLEMENT(PRTime) PR_Now(void) { PRTime prt; FILETIME ft; SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); _PR_FileTimeToPRTime(&ft, &prt); return prt; } #endif /* *********************************************************************** *********************************************************************** * * Process creation routines * *********************************************************************** *********************************************************************** */ /* * Assemble the command line by concatenating the argv array. * On success, this function returns 0 and the resulting command * line is returned in *cmdLine. On failure, it returns -1. */ static int assembleCmdLine(char *const *argv, char **cmdLine) { char *const *arg; char *p, *q; size_t cmdLineSize; int numBackslashes; int i; int argNeedQuotes; /* * Find out how large the command line buffer should be. */ cmdLineSize = 0; for (arg = argv; *arg; arg++) { /* * \ and " need to be escaped by a \. In the worst case, * every character is a \ or ", so the string of length * may double. If we quote an argument, that needs two ". * Finally, we need a space between arguments, and * a null byte at the end of command line. */ cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */ + 2 /* we quote every argument */ + 1; /* space in between, or final null */ } p = *cmdLine = PR_MALLOC((PRUint32) cmdLineSize); if (p == NULL) { return -1; } for (arg = argv; *arg; arg++) { /* Add a space to separates the arguments */ if (arg != argv) { *p++ = ' '; } q = *arg; numBackslashes = 0; argNeedQuotes = 0; /* * If the argument is empty or contains white space, it needs to * be quoted. */ if (**arg == '\0' || strpbrk(*arg, " \f\n\r\t\v")) { argNeedQuotes = 1; } if (argNeedQuotes) { *p++ = '"'; } while (*q) { if (*q == '\\') { numBackslashes++; q++; } else if (*q == '"') { if (numBackslashes) { /* * Double the backslashes since they are followed * by a quote */ for (i = 0; i < 2 * numBackslashes; i++) { *p++ = '\\'; } numBackslashes = 0; } /* To escape the quote */ *p++ = '\\'; *p++ = *q++; } else { if (numBackslashes) { /* * Backslashes are not followed by a quote, so * don't need to double the backslashes. */ for (i = 0; i < numBackslashes; i++) { *p++ = '\\'; } numBackslashes = 0; } *p++ = *q++; } } /* Now we are at the end of this argument */ if (numBackslashes) { /* * Double the backslashes if we have a quote string * delimiter at the end. */ if (argNeedQuotes) { numBackslashes *= 2; } for (i = 0; i < numBackslashes; i++) { *p++ = '\\'; } } if (argNeedQuotes) { *p++ = '"'; } } *p = '\0'; return 0; } /* * Assemble the environment block by concatenating the envp array * (preserving the terminating null byte in each array element) * and adding a null byte at the end. * * Returns 0 on success. The resulting environment block is returned * in *envBlock. Note that if envp is NULL, a NULL pointer is returned * in *envBlock. Returns -1 on failure. */ static int assembleEnvBlock(char **envp, char **envBlock) { char *p; char *q; char **env; char *curEnv; char *cwdStart, *cwdEnd; size_t envBlockSize; if (envp == NULL) { *envBlock = NULL; return 0; } #ifdef WINCE { PRUnichar *wideCurEnv = mozce_GetEnvString(); int len = WideCharToMultiByte(CP_ACP, 0, wideCurEnv, -1, NULL, 0, NULL, NULL); curEnv = (char *) PR_MALLOC(len * sizeof(char)); WideCharToMultiByte(CP_ACP, 0, wideCurEnv, -1, curEnv, len, NULL, NULL); free(wideCurEnv); } #else curEnv = GetEnvironmentStrings(); #endif cwdStart = curEnv; while (*cwdStart) { if (cwdStart[0] == '=' && cwdStart[1] != '\0' && cwdStart[2] == ':' && cwdStart[3] == '=') { break; } cwdStart += strlen(cwdStart) + 1; } cwdEnd = cwdStart; if (*cwdEnd) { cwdEnd += strlen(cwdEnd) + 1; while (*cwdEnd) { if (cwdEnd[0] != '=' || cwdEnd[1] == '\0' || cwdEnd[2] != ':' || cwdEnd[3] != '=') { break; } cwdEnd += strlen(cwdEnd) + 1; } } envBlockSize = cwdEnd - cwdStart; for (env = envp; *env; env++) { envBlockSize += strlen(*env) + 1; } envBlockSize++; p = *envBlock = PR_MALLOC((PRUint32) envBlockSize); if (p == NULL) { #ifdef WINCE PR_Free(curEnv); #else FreeEnvironmentStrings(curEnv); #endif return -1; } q = cwdStart; while (q < cwdEnd) { *p++ = *q++; } #ifdef WINCE PR_Free(curEnv); #else FreeEnvironmentStrings(curEnv); #endif for (env = envp; *env; env++) { q = *env; while (*q) { *p++ = *q++; } *p++ = '\0'; } *p = '\0'; return 0; } /* * For qsort. We sort (case-insensitive) the environment strings * before generating the environment block. */ static int compare(const void *arg1, const void *arg2) { return _stricmp(* (char**)arg1, * (char**)arg2); } PRProcess * _PR_CreateWindowsProcess( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { #ifdef WINCE STARTUPINFOW startupInfo; PRUnichar *wideCmdLine; PRUnichar *wideCwd; int len = 0; #else STARTUPINFO startupInfo; #endif DWORD creationFlags = 0; PROCESS_INFORMATION procInfo; BOOL retVal; char *cmdLine = NULL; char *envBlock = NULL; char **newEnvp = NULL; const char *cwd = NULL; /* current working directory */ PRProcess *proc = NULL; PRBool hasFdInheritBuffer; proc = PR_NEW(PRProcess); if (!proc) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } if (assembleCmdLine(argv, &cmdLine) == -1) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } #ifndef WINCE /* * If attr->fdInheritBuffer is not NULL, we need to insert * it into the envp array, so envp cannot be NULL. */ hasFdInheritBuffer = (attr && attr->fdInheritBuffer); if ((envp == NULL) && hasFdInheritBuffer) { envp = environ; } if (envp != NULL) { int idx; int numEnv; PRBool found = PR_FALSE; numEnv = 0; while (envp[numEnv]) { numEnv++; } newEnvp = (char **) PR_MALLOC((numEnv + 2) * sizeof(char *)); for (idx = 0; idx < numEnv; idx++) { newEnvp[idx] = envp[idx]; if (hasFdInheritBuffer && !found && !strncmp(newEnvp[idx], "NSPR_INHERIT_FDS=", 17)) { newEnvp[idx] = attr->fdInheritBuffer; found = PR_TRUE; } } if (hasFdInheritBuffer && !found) { newEnvp[idx++] = attr->fdInheritBuffer; } newEnvp[idx] = NULL; qsort((void *) newEnvp, (size_t) idx, sizeof(char *), compare); } if (assembleEnvBlock(newEnvp, &envBlock) == -1) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } ZeroMemory(&startupInfo, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); if (attr) { PRBool redirected = PR_FALSE; /* * XXX the default value for stdin, stdout, and stderr * should probably be the console input and output, not * those of the parent process. */ startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); if (attr->stdinFd) { startupInfo.hStdInput = (HANDLE) attr->stdinFd->secret->md.osfd; redirected = PR_TRUE; } if (attr->stdoutFd) { startupInfo.hStdOutput = (HANDLE) attr->stdoutFd->secret->md.osfd; redirected = PR_TRUE; /* * If stdout is redirected, we can assume that the process will * not write anything useful to the console windows, and therefore * automatically set the CREATE_NO_WINDOW flag. */ creationFlags |= CREATE_NO_WINDOW; } if (attr->stderrFd) { startupInfo.hStdError = (HANDLE) attr->stderrFd->secret->md.osfd; redirected = PR_TRUE; } if (redirected) { startupInfo.dwFlags |= STARTF_USESTDHANDLES; } cwd = attr->currentDirectory; } #endif #ifdef WINCE len = MultiByteToWideChar(CP_ACP, 0, cmdLine, -1, NULL, 0); wideCmdLine = (PRUnichar *)PR_MALLOC(len * sizeof(PRUnichar)); MultiByteToWideChar(CP_ACP, 0, cmdLine, -1, wideCmdLine, len); len = MultiByteToWideChar(CP_ACP, 0, cwd, -1, NULL, 0); wideCwd = PR_MALLOC(len * sizeof(PRUnichar)); MultiByteToWideChar(CP_ACP, 0, cwd, -1, wideCwd, len); retVal = CreateProcessW(NULL, wideCmdLine, NULL, /* security attributes for the new * process */ NULL, /* security attributes for the primary * thread in the new process */ TRUE, /* inherit handles */ creationFlags, envBlock, /* an environment block, consisting * of a null-terminated block of * null-terminated strings. Each * string is in the form: * name=value * XXX: usually NULL */ wideCwd, /* current drive and directory */ &startupInfo, &procInfo ); PR_Free(wideCmdLine); PR_Free(wideCwd); #else retVal = CreateProcess(NULL, cmdLine, NULL, /* security attributes for the new * process */ NULL, /* security attributes for the primary * thread in the new process */ TRUE, /* inherit handles */ creationFlags, envBlock, /* an environment block, consisting * of a null-terminated block of * null-terminated strings. Each * string is in the form: * name=value * XXX: usually NULL */ cwd, /* current drive and directory */ &startupInfo, &procInfo ); #endif if (retVal == FALSE) { /* XXX what error code? */ PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); goto errorExit; } CloseHandle(procInfo.hThread); proc->md.handle = procInfo.hProcess; proc->md.id = procInfo.dwProcessId; PR_DELETE(cmdLine); if (newEnvp) { PR_DELETE(newEnvp); } if (envBlock) { PR_DELETE(envBlock); } return proc; errorExit: if (cmdLine) { PR_DELETE(cmdLine); } if (newEnvp) { PR_DELETE(newEnvp); } if (envBlock) { PR_DELETE(envBlock); } if (proc) { PR_DELETE(proc); } return NULL; } /* _PR_CreateWindowsProcess */ PRStatus _PR_DetachWindowsProcess(PRProcess *process) { CloseHandle(process->md.handle); PR_DELETE(process); return PR_SUCCESS; } /* * XXX: This implementation is a temporary quick solution. * It can be called by native threads only (not by fibers). */ PRStatus _PR_WaitWindowsProcess(PRProcess *process, PRInt32 *exitCode) { DWORD dwRetVal; dwRetVal = WaitForSingleObject(process->md.handle, INFINITE); if (dwRetVal == WAIT_FAILED) { PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); return PR_FAILURE; } PR_ASSERT(dwRetVal == WAIT_OBJECT_0); if (exitCode != NULL && GetExitCodeProcess(process->md.handle, exitCode) == FALSE) { PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); return PR_FAILURE; } CloseHandle(process->md.handle); PR_DELETE(process); return PR_SUCCESS; } PRStatus _PR_KillWindowsProcess(PRProcess *process) { /* * On Unix, if a process terminates normally, its exit code is * between 0 and 255. So here on Windows, we use the exit code * 256 to indicate that the process is killed. */ if (TerminateProcess(process->md.handle, 256)) { return PR_SUCCESS; } PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); return PR_FAILURE; } PRStatus _MD_WindowsGetHostName(char *name, PRUint32 namelen) { PRIntn rv; PRInt32 syserror; rv = gethostname(name, (PRInt32) namelen); if (0 == rv) { return PR_SUCCESS; } syserror = WSAGetLastError(); PR_ASSERT(WSANOTINITIALISED != syserror); _PR_MD_MAP_GETHOSTNAME_ERROR(syserror); return PR_FAILURE; } PRStatus _MD_WindowsGetSysInfo(PRSysInfo cmd, char *name, PRUint32 namelen) { OSVERSIONINFO osvi; PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE)); ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (! GetVersionEx (&osvi) ) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } switch (osvi.dwPlatformId) { case VER_PLATFORM_WIN32_NT: if (PR_SI_SYSNAME == cmd) (void)PR_snprintf(name, namelen, "Windows_NT"); else if (PR_SI_RELEASE == cmd) (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion, osvi.dwMinorVersion); break; case VER_PLATFORM_WIN32_WINDOWS: if (PR_SI_SYSNAME == cmd) { if ((osvi.dwMajorVersion > 4) || ((osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0))) (void)PR_snprintf(name, namelen, "Windows_98"); else (void)PR_snprintf(name, namelen, "Windows_95"); } else if (PR_SI_RELEASE == cmd) { (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion, osvi.dwMinorVersion); } break; #ifdef VER_PLATFORM_WIN32_CE case VER_PLATFORM_WIN32_CE: if (PR_SI_SYSNAME == cmd) (void)PR_snprintf(name, namelen, "Windows_CE"); else if (PR_SI_RELEASE == cmd) (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion, osvi.dwMinorVersion); break; #endif default: if (PR_SI_SYSNAME == cmd) (void)PR_snprintf(name, namelen, "Windows_Unknown"); else if (PR_SI_RELEASE == cmd) (void)PR_snprintf(name, namelen, "%d.%d",0,0); break; } return PR_SUCCESS; } PRStatus _MD_WindowsGetReleaseName(char *name, PRUint32 namelen) { OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (! GetVersionEx (&osvi) ) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } switch (osvi.dwPlatformId) { case VER_PLATFORM_WIN32_NT: case VER_PLATFORM_WIN32_WINDOWS: (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVersion, osvi.dwMinorVersion); break; default: (void)PR_snprintf(name, namelen, "%d.%d",0,0); break; } return PR_SUCCESS; } /* ********************************************************************** * * Memory-mapped files * ********************************************************************** */ PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) { DWORD dwHi, dwLo; DWORD flProtect; PROsfd osfd; osfd = ( fmap->fd == (PRFileDesc*)-1 )? -1 : fmap->fd->secret->md.osfd; dwLo = (DWORD) (size & 0xffffffff); dwHi = (DWORD) (((PRUint64) size >> 32) & 0xffffffff); if (fmap->prot == PR_PROT_READONLY) { flProtect = PAGE_READONLY; fmap->md.dwAccess = FILE_MAP_READ; } else if (fmap->prot == PR_PROT_READWRITE) { flProtect = PAGE_READWRITE; fmap->md.dwAccess = FILE_MAP_WRITE; } else { PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY); #ifdef WINCE /* WINCE does not have FILE_MAP_COPY. */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; #else flProtect = PAGE_WRITECOPY; fmap->md.dwAccess = FILE_MAP_COPY; #endif } fmap->md.hFileMap = CreateFileMapping( (HANDLE) osfd, NULL, flProtect, dwHi, dwLo, NULL); if (fmap->md.hFileMap == NULL) { PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); return PR_FAILURE; } return PR_SUCCESS; } PRInt32 _MD_GetMemMapAlignment(void) { SYSTEM_INFO info; GetSystemInfo(&info); return info.dwAllocationGranularity; } extern PRLogModuleInfo *_pr_shma_lm; void * _MD_MemMap( PRFileMap *fmap, PROffset64 offset, PRUint32 len) { DWORD dwHi, dwLo; void *addr; dwLo = (DWORD) (offset & 0xffffffff); dwHi = (DWORD) (((PRUint64) offset >> 32) & 0xffffffff); if ((addr = MapViewOfFile(fmap->md.hFileMap, fmap->md.dwAccess, dwHi, dwLo, len)) == NULL) { { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("md_memmap(): %s", lpMsgBuf )); } PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); } return addr; } PRStatus _MD_MemUnmap(void *addr, PRUint32 len) { if (UnmapViewOfFile(addr)) { return PR_SUCCESS; } _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } PRStatus _MD_CloseFileMap(PRFileMap *fmap) { CloseHandle(fmap->md.hFileMap); PR_DELETE(fmap); return PR_SUCCESS; } PRStatus _MD_SyncMemMap( PRFileDesc *fd, void *addr, PRUint32 len) { PROsfd osfd = fd->secret->md.osfd; /* The FlushViewOfFile page on MSDN says: * To flush all the dirty pages plus the metadata for the file and * ensure that they are physically written to disk, call * FlushViewOfFile and then call the FlushFileBuffers function. */ if (FlushViewOfFile(addr, len) && FlushFileBuffers((HANDLE) osfd)) { return PR_SUCCESS; } _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } /* *********************************************************************** * * Atomic increment and decrement operations for x86 processors * * We don't use InterlockedIncrement and InterlockedDecrement * because on NT 3.51 and Win95, they return a number with * the same sign as the incremented/decremented result, rather * than the result itself. On NT 4.0 these functions do return * the incremented/decremented result. * * The result is returned in the eax register by the inline * assembly code. We disable the harmless "no return value" * warning (4035) for these two functions. * *********************************************************************** */ #if defined(_M_IX86) || defined(_X86_) #pragma warning(disable: 4035) PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val) { #if defined(__GNUC__) PRInt32 result; asm volatile ("lock ; xadd %0, %1" : "=r"(result), "=m"(*val) : "0"(1), "m"(*val)); return result + 1; #else __asm { mov ecx, val mov eax, 1 lock xadd dword ptr [ecx], eax inc eax } #endif /* __GNUC__ */ } #pragma warning(default: 4035) #pragma warning(disable: 4035) PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) { #if defined(__GNUC__) PRInt32 result; asm volatile ("lock ; xadd %0, %1" : "=r"(result), "=m"(*val) : "0"(-1), "m"(*val)); //asm volatile("lock ; xadd %0, %1" : "=m" (val), "=a" (result) : "-1" (1)); return result - 1; #else __asm { mov ecx, val mov eax, 0ffffffffh lock xadd dword ptr [ecx], eax dec eax } #endif /* __GNUC__ */ } #pragma warning(default: 4035) #pragma warning(disable: 4035) PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val) { #if defined(__GNUC__) PRInt32 result; //asm volatile("lock ; xadd %1, %0" : "=m" (intp), "=a" (result) : "1" (val)); asm volatile ("lock ; xadd %0, %1" : "=r"(result), "=m"(*intp) : "0"(val), "m"(*intp)); return result + val; #else __asm { mov ecx, intp mov eax, val mov edx, eax lock xadd dword ptr [ecx], eax add eax, edx } #endif /* __GNUC__ */ } #pragma warning(default: 4035) #ifdef _PR_HAVE_ATOMIC_CAS #pragma warning(disable: 4035) void PR_StackPush(PRStack *stack, PRStackElem *stack_elem) { #if defined(__GNUC__) void **tos = (void **) stack; void *tmp; retry: if (*tos == (void *) -1) goto retry; __asm__("xchg %0,%1" : "=r" (tmp), "=m"(*tos) : "0" (-1), "m"(*tos)); if (tmp == (void *) -1) goto retry; *(void **)stack_elem = tmp; __asm__("" : : : "memory"); *tos = stack_elem; #else __asm { mov ebx, stack mov ecx, stack_elem retry: mov eax,[ebx] cmp eax,-1 je retry mov eax,-1 xchg dword ptr [ebx], eax cmp eax,-1 je retry mov [ecx],eax mov [ebx],ecx } #endif /* __GNUC__ */ } #pragma warning(default: 4035) #pragma warning(disable: 4035) PRStackElem * PR_StackPop(PRStack *stack) { #if defined(__GNUC__) void **tos = (void **) stack; void *tmp; retry: if (*tos == (void *) -1) goto retry; __asm__("xchg %0,%1" : "=r" (tmp), "=m"(*tos) : "0" (-1), "m"(*tos)); if (tmp == (void *) -1) goto retry; if (tmp != (void *) 0) { void *next = *(void **)tmp; *tos = next; *(void **)tmp = 0; } else *tos = tmp; return tmp; #else __asm { mov ebx, stack retry: mov eax,[ebx] cmp eax,-1 je retry mov eax,-1 xchg dword ptr [ebx], eax cmp eax,-1 je retry cmp eax,0 je empty mov ecx,[eax] mov [ebx],ecx mov [eax],0 jmp done empty: mov [ebx],eax done: } #endif /* __GNUC__ */ } #pragma warning(default: 4035) #endif /* _PR_HAVE_ATOMIC_CAS */ #endif /* x86 processors */ nspr-4.11/nspr/pr/src/md/windows/ntsec.c0000644000000000000000000001746612623070344016332 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /* * ntsec.c * * Implement the POSIX-style mode bits (access permissions) for * files and other securable objects in Windows NT using Windows * NT's security descriptors with appropriate discretionary * access-control lists. */ /* * The security identifiers (SIDs) for owner, primary group, * and the Everyone (World) group. * * These SIDs are looked up during NSPR initialization and * saved in this global structure (see _PR_NT_InitSids) so * that _PR_NT_MakeSecurityDescriptorACL doesn't need to * look them up every time. */ static struct { PSID owner; PSID group; PSID everyone; } _pr_nt_sids; /* * Initialize the SIDs for owner, primary group, and the Everyone * group in the _pr_nt_sids structure. * * This function needs to be called by NSPR initialization. */ void _PR_NT_InitSids(void) { #ifdef WINCE /* not supported */ return; #else SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; HANDLE hToken = NULL; /* initialized to an arbitrary value to * silence a Purify UMR warning */ PSID infoBuffer[1024/sizeof(PSID)]; /* defined as an array of PSIDs * to force proper alignment */ PTOKEN_OWNER pTokenOwner = (PTOKEN_OWNER) infoBuffer; PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup = (PTOKEN_PRIMARY_GROUP) infoBuffer; DWORD dwLength; BOOL rv; /* * Look up and make a copy of the owner and primary group * SIDs in the access token of the calling process. */ rv = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); if (rv == 0) { /* * On non-NT systems, this function is not implemented * (error code ERROR_CALL_NOT_IMPLEMENTED), and neither are * the other security functions. There is no point in * going further. * * A process with insufficient access permissions may fail * with the error code ERROR_ACCESS_DENIED. */ PR_LOG(_pr_io_lm, PR_LOG_DEBUG, ("_PR_NT_InitSids: OpenProcessToken() failed. Error: %d", GetLastError())); return; } rv = GetTokenInformation(hToken, TokenOwner, infoBuffer, sizeof(infoBuffer), &dwLength); PR_ASSERT(rv != 0); dwLength = GetLengthSid(pTokenOwner->Owner); _pr_nt_sids.owner = (PSID) PR_Malloc(dwLength); PR_ASSERT(_pr_nt_sids.owner != NULL); rv = CopySid(dwLength, _pr_nt_sids.owner, pTokenOwner->Owner); PR_ASSERT(rv != 0); rv = GetTokenInformation(hToken, TokenPrimaryGroup, infoBuffer, sizeof(infoBuffer), &dwLength); PR_ASSERT(rv != 0); dwLength = GetLengthSid(pTokenPrimaryGroup->PrimaryGroup); _pr_nt_sids.group = (PSID) PR_Malloc(dwLength); PR_ASSERT(_pr_nt_sids.group != NULL); rv = CopySid(dwLength, _pr_nt_sids.group, pTokenPrimaryGroup->PrimaryGroup); PR_ASSERT(rv != 0); rv = CloseHandle(hToken); PR_ASSERT(rv != 0); /* Create a well-known SID for the Everyone group. */ rv = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &_pr_nt_sids.everyone); PR_ASSERT(rv != 0); #endif } /* * Free the SIDs for owner, primary group, and the Everyone group * in the _pr_nt_sids structure. * * This function needs to be called by NSPR cleanup. */ void _PR_NT_FreeSids(void) { #ifdef WINCE return; #else if (_pr_nt_sids.owner) { PR_Free(_pr_nt_sids.owner); } if (_pr_nt_sids.group) { PR_Free(_pr_nt_sids.group); } if (_pr_nt_sids.everyone) { FreeSid(_pr_nt_sids.everyone); } #endif } /* * Construct a security descriptor whose discretionary access-control * list implements the specified mode bits. The SIDs for owner, group, * and everyone are obtained from the global _pr_nt_sids structure. * Both the security descriptor and access-control list are returned * and should be freed by a _PR_NT_FreeSecurityDescriptorACL call. * * The accessTable array maps NSPR's read, write, and execute access * rights to the corresponding NT access rights for the securable * object. */ PRStatus _PR_NT_MakeSecurityDescriptorACL( PRIntn mode, DWORD accessTable[], PSECURITY_DESCRIPTOR *resultSD, PACL *resultACL) { #ifdef WINCE PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; #else PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; DWORD cbACL; /* size of ACL */ DWORD accessMask; if (_pr_nt_sids.owner == NULL) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } pSD = (PSECURITY_DESCRIPTOR) PR_Malloc(SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } if (!SetSecurityDescriptorOwner(pSD, _pr_nt_sids.owner, FALSE)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } if (!SetSecurityDescriptorGroup(pSD, _pr_nt_sids.group, FALSE)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } /* * Construct a discretionary access-control list with three * access-control entries, one each for owner, primary group, * and Everyone. */ cbACL = sizeof(ACL) + 3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetLengthSid(_pr_nt_sids.owner) + GetLengthSid(_pr_nt_sids.group) + GetLengthSid(_pr_nt_sids.everyone); pACL = (PACL) PR_Malloc(cbACL); if (pACL == NULL) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } accessMask = 0; if (mode & 00400) accessMask |= accessTable[0]; if (mode & 00200) accessMask |= accessTable[1]; if (mode & 00100) accessMask |= accessTable[2]; if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask, _pr_nt_sids.owner)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } accessMask = 0; if (mode & 00040) accessMask |= accessTable[0]; if (mode & 00020) accessMask |= accessTable[1]; if (mode & 00010) accessMask |= accessTable[2]; if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask, _pr_nt_sids.group)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } accessMask = 0; if (mode & 00004) accessMask |= accessTable[0]; if (mode & 00002) accessMask |= accessTable[1]; if (mode & 00001) accessMask |= accessTable[2]; if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask, _pr_nt_sids.everyone)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); goto failed; } *resultSD = pSD; *resultACL = pACL; return PR_SUCCESS; failed: if (pSD) { PR_Free(pSD); } if (pACL) { PR_Free(pACL); } return PR_FAILURE; #endif } /* * Free the specified security descriptor and access-control list * previously created by _PR_NT_MakeSecurityDescriptorACL. */ void _PR_NT_FreeSecurityDescriptorACL(PSECURITY_DESCRIPTOR pSD, PACL pACL) { if (pSD) { PR_Free(pSD); } if (pACL) { PR_Free(pACL); } } nspr-4.11/nspr/pr/src/md/windows/ntsem.c0000644000000000000000000000175612623070344016337 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * NT-specific semaphore handling code. * */ #include "primpl.h" void _PR_MD_NEW_SEM(_MDSemaphore *md, PRUintn value) { md->sem = CreateSemaphore(NULL, value, 0x7fffffff, NULL); } void _PR_MD_DESTROY_SEM(_MDSemaphore *md) { CloseHandle(md->sem); } PRStatus _PR_MD_TIMED_WAIT_SEM(_MDSemaphore *md, PRIntervalTime ticks) { int rv; rv = WaitForSingleObject(md->sem, PR_IntervalToMilliseconds(ticks)); if (rv == WAIT_OBJECT_0) return PR_SUCCESS; else return PR_FAILURE; } PRStatus _PR_MD_WAIT_SEM(_MDSemaphore *md) { return _PR_MD_TIMED_WAIT_SEM(md, PR_INTERVAL_NO_TIMEOUT); } void _PR_MD_POST_SEM(_MDSemaphore *md) { ReleaseSemaphore(md->sem, 1, NULL); } nspr-4.11/nspr/pr/src/md/windows/ntthread.c0000644000000000000000000003432112623070344017014 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* for _beginthreadex() */ /* --- globals ------------------------------------------------ */ PRLock *_pr_schedLock = NULL; _PRInterruptTable _pr_interruptTable[] = { { 0 } }; BOOL _pr_use_static_tls = TRUE; __declspec(thread) PRThread *_pr_current_fiber; __declspec(thread) PRThread *_pr_fiber_last_run; __declspec(thread) _PRCPU *_pr_current_cpu; __declspec(thread) PRUintn _pr_ints_off; DWORD _pr_currentFiberIndex; DWORD _pr_lastFiberIndex; DWORD _pr_currentCPUIndex; DWORD _pr_intsOffIndex; _MDLock _nt_idleLock; PRCList _nt_idleList; PRUint32 _nt_idleCount; extern __declspec(thread) PRThread *_pr_io_restarted_io; extern DWORD _pr_io_restartedIOIndex; /* Must check the restarted_io *before* decrementing no_sched to 0 */ #define POST_SWITCH_WORK() \ PR_BEGIN_MACRO \ PRThread *restarted_io = \ (_pr_use_static_tls ? _pr_io_restarted_io \ : (PRThread *) TlsGetValue(_pr_io_restartedIOIndex)); \ if (restarted_io) { \ _nt_handle_restarted_io(restarted_io); \ } \ _PR_MD_LAST_THREAD()->no_sched = 0; \ PR_END_MACRO void _nt_handle_restarted_io(PRThread *restarted_io) { /* After the switch we can resume an IO if needed. * XXXMB - this needs to be done in create thread, since that could * be the result for a context switch too.. */ PR_ASSERT(restarted_io->io_suspended == PR_TRUE); PR_ASSERT(restarted_io->md.thr_bound_cpu == restarted_io->cpu); _PR_THREAD_LOCK(restarted_io); if (restarted_io->io_pending == PR_FALSE) { /* The IO already completed, put us back on the runq. */ int pri = restarted_io->priority; restarted_io->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(restarted_io->cpu); _PR_ADD_RUNQ(restarted_io, restarted_io->cpu, pri); _PR_RUNQ_UNLOCK(restarted_io->cpu); } else { _PR_SLEEPQ_LOCK(restarted_io->cpu); _PR_ADD_SLEEPQ(restarted_io, restarted_io->sleep); _PR_SLEEPQ_UNLOCK(restarted_io->cpu); } restarted_io->io_suspended = PR_FALSE; restarted_io->md.thr_bound_cpu = NULL; _PR_THREAD_UNLOCK(restarted_io); if (_pr_use_static_tls) { _pr_io_restarted_io = NULL; } else { TlsSetValue(_pr_io_restartedIOIndex, NULL); } } void _PR_MD_EARLY_INIT() { _MD_NEW_LOCK( &_nt_idleLock ); _nt_idleCount = 0; PR_INIT_CLIST(&_nt_idleList); #if 0 /* Make the clock tick at least once per millisecond */ if ( timeBeginPeriod(1) == TIMERR_NOCANDO) { /* deep yoghurt; clock doesn't tick fast enough! */ PR_ASSERT(0); } #endif if (!_pr_use_static_tls) { _pr_currentFiberIndex = TlsAlloc(); _pr_lastFiberIndex = TlsAlloc(); _pr_currentCPUIndex = TlsAlloc(); _pr_intsOffIndex = TlsAlloc(); _pr_io_restartedIOIndex = TlsAlloc(); } } void _PR_MD_CLEANUP_BEFORE_EXIT(void) { _PR_NT_FreeSids(); WSACleanup(); if (!_pr_use_static_tls) { TlsFree(_pr_currentFiberIndex); TlsFree(_pr_lastFiberIndex); TlsFree(_pr_currentCPUIndex); TlsFree(_pr_intsOffIndex); TlsFree(_pr_io_restartedIOIndex); } } PRStatus _PR_MD_INIT_THREAD(PRThread *thread) { thread->md.overlapped.ioModel = _MD_BlockingIO; thread->md.overlapped.data.mdThread = &thread->md; if (thread->flags & _PR_GLOBAL_SCOPE) { if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) { /* ** Warning: ** -------- ** NSPR requires a real handle to every thread. ** GetCurrentThread() returns a pseudo-handle which ** is not suitable for some thread operations (e.g., ** suspending). Therefore, get a real handle from ** the pseudo handle via DuplicateHandle(...) */ DuplicateHandle( GetCurrentProcess(), /* Process of source handle */ GetCurrentThread(), /* Pseudo Handle to dup */ GetCurrentProcess(), /* Process of handle */ &(thread->md.handle), /* resulting handle */ 0L, /* access flags */ FALSE, /* Inheritable */ DUPLICATE_SAME_ACCESS); /* Options */ } /* Create the blocking IO semaphore */ thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL); if (thread->md.blocked_sema == NULL) { return PR_FAILURE; } if (_native_threads_only) { /* Create the blocking IO semaphore */ thread->md.thr_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (thread->md.thr_event == NULL) { return PR_FAILURE; } } } return PR_SUCCESS; } static unsigned __stdcall pr_root(void *arg) { PRThread *thread = (PRThread *)arg; thread->md.start(thread); return 0; } PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { thread->md.start = start; thread->md.handle = (HANDLE) _beginthreadex( NULL, thread->stack->stackSize, pr_root, (void *)thread, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, &(thread->id)); if(!thread->md.handle) { PRErrorCode prerror; thread->md.fiber_last_error = GetLastError(); switch (errno) { case ENOMEM: prerror = PR_OUT_OF_MEMORY_ERROR; break; case EAGAIN: prerror = PR_INSUFFICIENT_RESOURCES_ERROR; break; case EINVAL: prerror = PR_INVALID_ARGUMENT_ERROR; break; default: prerror = PR_UNKNOWN_ERROR; } PR_SetError(prerror, errno); return PR_FAILURE; } thread->md.id = thread->id; /* * On windows, a thread is created with a thread priority of * THREAD_PRIORITY_NORMAL. */ if (priority != PR_PRIORITY_NORMAL) { _PR_MD_SET_PRIORITY(&(thread->md), priority); } /* Activate the thread */ if ( ResumeThread( thread->md.handle ) != -1) return PR_SUCCESS; PR_SetError(PR_UNKNOWN_ERROR, GetLastError()); return PR_FAILURE; } void _PR_MD_JOIN_THREAD(_MDThread *md) { DWORD rv; rv = WaitForSingleObject(md->handle, INFINITE); PR_ASSERT(WAIT_OBJECT_0 == rv); } void _PR_MD_END_THREAD(void) { _endthreadex(0); } void _PR_MD_YIELD(void) { /* Can NT really yield at all? */ Sleep(0); } void _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri) { int nativePri; BOOL rv; if (newPri < PR_PRIORITY_FIRST) { newPri = PR_PRIORITY_FIRST; } else if (newPri > PR_PRIORITY_LAST) { newPri = PR_PRIORITY_LAST; } switch (newPri) { case PR_PRIORITY_LOW: nativePri = THREAD_PRIORITY_BELOW_NORMAL; break; case PR_PRIORITY_NORMAL: nativePri = THREAD_PRIORITY_NORMAL; break; case PR_PRIORITY_HIGH: nativePri = THREAD_PRIORITY_ABOVE_NORMAL; break; case PR_PRIORITY_URGENT: nativePri = THREAD_PRIORITY_HIGHEST; } rv = SetThreadPriority(thread->handle, nativePri); PR_ASSERT(rv); if (!rv) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_SetThreadPriority: can't set thread priority\n")); } return; } const DWORD MS_VC_EXCEPTION = 0x406D1388; #pragma pack(push,8) typedef struct tagTHREADNAME_INFO { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1=caller thread). DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) void _PR_MD_SET_CURRENT_THREAD_NAME(const char *name) { #ifdef _MSC_VER THREADNAME_INFO info; if (!IsDebuggerPresent()) return; info.dwType = 0x1000; info.szName = (char*) name; info.dwThreadID = -1; info.dwFlags = 0; __try { RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); } __except(EXCEPTION_CONTINUE_EXECUTION) { } #endif } void _PR_MD_CLEAN_THREAD(PRThread *thread) { BOOL rv; if (thread->md.acceptex_buf) { PR_DELETE(thread->md.acceptex_buf); } if (thread->md.xmit_bufs) { PR_DELETE(thread->md.xmit_bufs); } if (thread->md.blocked_sema) { rv = CloseHandle(thread->md.blocked_sema); PR_ASSERT(rv); thread->md.blocked_sema = 0; } if (_native_threads_only) { if (thread->md.thr_event) { rv = CloseHandle(thread->md.thr_event); PR_ASSERT(rv); thread->md.thr_event = 0; } } if (thread->md.handle) { rv = CloseHandle(thread->md.handle); PR_ASSERT(rv); thread->md.handle = 0; } /* Don't call DeleteFiber on current fiber or we'll kill the whole thread. * Don't call free(thread) until we've switched off the thread. * So put this fiber (or thread) on a list to be deleted by the idle * fiber next time we have a chance. */ if (!(thread->flags & (_PR_ATTACHED|_PR_GLOBAL_SCOPE))) { _MD_LOCK(&_nt_idleLock); _nt_idleCount++; PR_APPEND_LINK(&thread->links, &_nt_idleList); _MD_UNLOCK(&_nt_idleLock); } } void _PR_MD_EXIT_THREAD(PRThread *thread) { BOOL rv; if (thread->md.acceptex_buf) { PR_DELETE(thread->md.acceptex_buf); } if (thread->md.xmit_bufs) { PR_DELETE(thread->md.xmit_bufs); } if (thread->md.blocked_sema) { rv = CloseHandle(thread->md.blocked_sema); PR_ASSERT(rv); thread->md.blocked_sema = 0; } if (_native_threads_only) { if (thread->md.thr_event) { rv = CloseHandle(thread->md.thr_event); PR_ASSERT(rv); thread->md.thr_event = 0; } } if (thread->md.handle) { rv = CloseHandle(thread->md.handle); PR_ASSERT(rv); thread->md.handle = 0; } if (thread->flags & _PR_GLOBAL_SCOPE) { _MD_SET_CURRENT_THREAD(NULL); } } void _PR_MD_EXIT(PRIntn status) { _exit(status); } #ifdef HAVE_FIBERS void _pr_fiber_mainline(void *unused) { PRThread *fiber = _PR_MD_CURRENT_THREAD(); POST_SWITCH_WORK(); fiber->md.fiber_fn(fiber->md.fiber_arg); } PRThread *_PR_MD_CREATE_USER_THREAD( PRUint32 stacksize, void (*start)(void *), void *arg) { PRThread *thread; if ( (thread = PR_NEW(PRThread)) == NULL ) { return NULL; } memset(thread, 0, sizeof(PRThread)); thread->md.fiber_fn = start; thread->md.fiber_arg = arg; thread->md.fiber_stacksize = stacksize; return thread; } void _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(PRThread *thread) { thread->md.fiber_id = ConvertThreadToFiber(NULL); PR_ASSERT(thread->md.fiber_id); _MD_SET_CURRENT_THREAD(thread); _MD_SET_LAST_THREAD(thread); thread->no_sched = 1; return; } void _PR_MD_INIT_CONTEXT(PRThread *thread, char *top, void (*start) (void), PRBool *status) { thread->md.fiber_fn = (void (*)(void *))start; thread->md.fiber_id = CreateFiber(thread->md.fiber_stacksize, (LPFIBER_START_ROUTINE)_pr_fiber_mainline, NULL); if (thread->md.fiber_id != 0) *status = PR_TRUE; else { DWORD oserror = GetLastError(); PRErrorCode prerror; if (oserror == ERROR_NOT_ENOUGH_MEMORY) { prerror = PR_OUT_OF_MEMORY_ERROR; } else { prerror = PR_UNKNOWN_ERROR; } PR_SetError(prerror, oserror); *status = PR_FALSE; } } void _PR_MD_SWITCH_CONTEXT(PRThread *thread) { PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) ); thread->md.fiber_last_error = GetLastError(); _PR_Schedule(); } void _PR_MD_RESTORE_CONTEXT(PRThread *thread) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) ); /* The user-level code for yielding will happily add ourselves to the runq * and then switch to ourselves; the NT fibers can't handle switching to * ourselves. */ if (thread != me) { SetLastError(thread->md.fiber_last_error); _MD_SET_CURRENT_THREAD(thread); _PR_MD_SET_LAST_THREAD(me); thread->no_sched = 1; SwitchToFiber(thread->md.fiber_id); POST_SWITCH_WORK(); } } #endif /* HAVE_FIBERS */ PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ) { int rv; rv = SetThreadAffinityMask(thread->md.handle, mask); return rv?0:-1; } PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask) { PRInt32 rv, system_mask; rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask); return rv?0:-1; } void _PR_MD_SUSPEND_CPU(_PRCPU *cpu) { _PR_MD_SUSPEND_THREAD(cpu->thread); } void _PR_MD_RESUME_CPU(_PRCPU *cpu) { _PR_MD_RESUME_THREAD(cpu->thread); } void _PR_MD_SUSPEND_THREAD(PRThread *thread) { if (_PR_IS_NATIVE_THREAD(thread)) { /* ** There seems to be some doubt about whether or not SuspendThread ** is a synchronous function. The test afterwards is to help veriry ** that it is, which is what Microsoft says it is. */ PRUintn rv = SuspendThread(thread->md.handle); PR_ASSERT(0xffffffffUL != rv); } } void _PR_MD_RESUME_THREAD(PRThread *thread) { if (_PR_IS_NATIVE_THREAD(thread)) { ResumeThread(thread->md.handle); } } PRThread* _MD_CURRENT_THREAD(void) { PRThread *thread; thread = _MD_GET_ATTACHED_THREAD(); if (NULL == thread) { thread = _PRI_AttachThread( PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0); } PR_ASSERT(thread != NULL); return thread; } nspr-4.11/nspr/pr/src/md/windows/objs.mk0000644000000000000000000000156412623070344016330 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ifeq ($(OS_TARGET),WINNT) CSRCS = ntmisc.c \ ntsec.c \ ntsem.c \ ntinrval.c \ ntgc.c \ ntio.c \ ntthread.c \ ntdllmn.c \ win32_errors.c \ w32ipcsem.c \ w32poll.c \ w32rng.c \ w32shm.c else ifeq (,$(filter-out WIN95 WINCE WINMO, $(OS_TARGET))) CSRCS = ntmisc.c \ ntsec.c \ ntsem.c \ ntinrval.c \ ntgc.c \ w95thred.c \ w95io.c \ w95cv.c \ w95sock.c \ win32_errors.c \ w32ipcsem.c \ w32poll.c \ w32rng.c \ w32shm.c \ w95dllmain.c else endif # win95 endif # winnt CSRCS += $(PR_MD_CSRCS) ASFILES += $(PR_MD_ASFILES) OBJS += $(addprefix md/windows/$(OBJDIR)/,$(CSRCS:.c=.$(OBJ_SUFFIX))) \ $(addprefix md/windows/$(OBJDIR)/,$(ASFILES:.s=.$(OBJ_SUFFIX))) nspr-4.11/nspr/pr/src/md/windows/w32ipcsem.c0000644000000000000000000001472312623070344017023 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: w32ipcsem.c * Description: implements named semaphores for NT and WIN95. */ #include "primpl.h" #ifdef WINCE static HANDLE OpenSemaphore(DWORD inDesiredAccess, BOOL inInheritHandle, const char *inName) { HANDLE retval = NULL; HANDLE semaphore = NULL; PRUnichar wideName[MAX_PATH]; /* name size is limited to MAX_PATH */ MultiByteToWideChar(CP_ACP, 0, inName, -1, wideName, MAX_PATH); /* 0x7fffffff is the max count for our semaphore */ semaphore = CreateSemaphoreW(NULL, 0, 0x7fffffff, wideName); if (NULL != semaphore) { DWORD lastErr = GetLastError(); if (ERROR_ALREADY_EXISTS != lastErr) CloseHandle(semaphore); else retval = semaphore; } return retval; } #endif /* * NSPR-to-NT access right mapping table for semaphore objects. * * The SYNCHRONIZE access is required by WaitForSingleObject. * The SEMAPHORE_MODIFY_STATE access is required by ReleaseSemaphore. * The OR of these three access masks must equal SEMAPHORE_ALL_ACCESS. * This is because if a semaphore object with the specified name * exists, CreateSemaphore requests SEMAPHORE_ALL_ACCESS access to * the existing object. */ static DWORD semAccessTable[] = { STANDARD_RIGHTS_REQUIRED|0x1, /* read (0x1 is "query state") */ STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, /* write */ 0 /* execute */ }; #ifndef _PR_GLOBAL_THREADS_ONLY /* * A fiber cannot call WaitForSingleObject because that * will block the other fibers running on the same thread. * If a fiber needs to wait on a (semaphore) handle, we * create a native thread to call WaitForSingleObject and * have the fiber join the native thread. */ /* * Arguments, return value, and error code for WaitForSingleObject */ struct WaitSingleArg { HANDLE handle; DWORD timeout; DWORD rv; DWORD error; }; static void WaitSingleThread(void *arg) { struct WaitSingleArg *warg = (struct WaitSingleArg *) arg; warg->rv = WaitForSingleObject(warg->handle, warg->timeout); if (warg->rv == WAIT_FAILED) { warg->error = GetLastError(); } } static DWORD FiberSafeWaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ) { PRThread *me = _PR_MD_CURRENT_THREAD(); if (_PR_IS_NATIVE_THREAD(me)) { return WaitForSingleObject(hHandle, dwMilliseconds); } else { PRThread *waitThread; struct WaitSingleArg warg; PRStatus rv; warg.handle = hHandle; warg.timeout = dwMilliseconds; waitThread = PR_CreateThread( PR_USER_THREAD, WaitSingleThread, &warg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (waitThread == NULL) { return WAIT_FAILED; } rv = PR_JoinThread(waitThread); PR_ASSERT(rv == PR_SUCCESS); if (rv == PR_FAILURE) { return WAIT_FAILED; } if (warg.rv == WAIT_FAILED) { SetLastError(warg.error); } return warg.rv; } } #endif /* !_PR_GLOBAL_THREADS_ONLY */ PRSem *_PR_MD_OPEN_SEMAPHORE( const char *osname, PRIntn flags, PRIntn mode, PRUintn value) { PRSem *sem; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; sem = PR_NEW(PRSem); if (sem == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } if (flags & PR_SEM_CREATE) { if (_PR_NT_MakeSecurityDescriptorACL(mode, semAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } #ifdef WINCE { /* The size of a sem's name is limited to MAX_PATH. */ PRUnichar wosname[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, osname, -1, wosname, MAX_PATH); sem->sem = CreateSemaphoreW(lpSA, value, 0x7fffffff, wosname); } #else sem->sem = CreateSemaphoreA(lpSA, value, 0x7fffffff, osname); #endif if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (sem->sem == NULL) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); PR_DELETE(sem); return NULL; } if ((flags & PR_SEM_EXCL) && (GetLastError() == ERROR_ALREADY_EXISTS)) { PR_SetError(PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS); CloseHandle(sem->sem); PR_DELETE(sem); return NULL; } } else { sem->sem = OpenSemaphore( SEMAPHORE_MODIFY_STATE|SYNCHRONIZE, FALSE, osname); if (sem->sem == NULL) { DWORD err = GetLastError(); /* * If we open a nonexistent named semaphore, NT * returns ERROR_FILE_NOT_FOUND, while Win95 * returns ERROR_INVALID_NAME */ if (err == ERROR_INVALID_NAME) { PR_SetError(PR_FILE_NOT_FOUND_ERROR, err); } else { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); } PR_DELETE(sem); return NULL; } } return sem; } PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem) { DWORD rv; #ifdef _PR_GLOBAL_THREADS_ONLY rv = WaitForSingleObject(sem->sem, INFINITE); #else rv = FiberSafeWaitForSingleObject(sem->sem, INFINITE); #endif PR_ASSERT(rv == WAIT_FAILED || rv == WAIT_OBJECT_0); if (rv == WAIT_FAILED) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } if (rv != WAIT_OBJECT_0) { /* Should not happen */ PR_SetError(PR_UNKNOWN_ERROR, 0); return PR_FAILURE; } return PR_SUCCESS; } PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem) { if (ReleaseSemaphore(sem->sem, 1, NULL) == FALSE) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } return PR_SUCCESS; } PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem) { if (CloseHandle(sem->sem) == FALSE) { _PR_MD_MAP_CLOSE_ERROR(GetLastError()); return PR_FAILURE; } PR_DELETE(sem); return PR_SUCCESS; } nspr-4.11/nspr/pr/src/md/windows/w32poll.c0000644000000000000000000002403112623070344016502 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file implements _PR_MD_PR_POLL for Win32. */ /* The default value of FD_SETSIZE is 64. */ #define FD_SETSIZE 1024 #include "primpl.h" #if !defined(_PR_GLOBAL_THREADS_ONLY) struct select_data_s { PRInt32 status; PRInt32 error; fd_set *rd, *wt, *ex; const struct timeval *tv; }; static void _PR_MD_select_thread(void *cdata) { struct select_data_s *cd = (struct select_data_s *)cdata; cd->status = select(0, cd->rd, cd->wt, cd->ex, cd->tv); if (cd->status == SOCKET_ERROR) { cd->error = WSAGetLastError(); } } int _PR_NTFiberSafeSelect( int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); int ready; if (_PR_IS_NATIVE_THREAD(me)) { ready = _MD_SELECT(nfds, readfds, writefds, exceptfds, timeout); } else { /* ** Creating a new thread on each call!! ** I guess web server doesn't use non-block I/O. */ PRThread *selectThread; struct select_data_s data; data.status = 0; data.error = 0; data.rd = readfds; data.wt = writefds; data.ex = exceptfds; data.tv = timeout; selectThread = PR_CreateThread( PR_USER_THREAD, _PR_MD_select_thread, &data, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (selectThread == NULL) return -1; PR_JoinThread(selectThread); ready = data.status; if (ready == SOCKET_ERROR) WSASetLastError(data.error); } return ready; } #endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { int ready, err; fd_set rd, wt, ex; fd_set *rdp, *wtp, *exp; int nrd, nwt, nex; PRFileDesc *bottom; PRPollDesc *pd, *epd; PRThread *me = _PR_MD_CURRENT_THREAD(); struct timeval tv, *tvp = NULL; if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); return -1; } /* ** Is it an empty set? If so, just sleep for the timeout and return */ if (0 == npds) { PR_Sleep(timeout); return 0; } nrd = nwt = nex = 0; FD_ZERO(&rd); FD_ZERO(&wt); FD_ZERO(&ex); ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { SOCKET osfd; PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { if (pd->in_flags & PR_POLL_READ) { in_flags_read = (pd->fd->methods->poll)( pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_WRITE), &out_flags_read); } if (pd->in_flags & PR_POLL_WRITE) { in_flags_write = (pd->fd->methods->poll)( pd->fd, (PRInt16)(pd->in_flags & ~PR_POLL_READ), &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one's ready right now (buffered input) */ if (0 == ready) { /* * We will have to return without calling the * system poll/select function. So zero the * out_flags fields of all the poll descriptors * before this one. */ PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; pd->out_flags = out_flags_read | out_flags_write; } else { pd->out_flags = 0; /* pre-condition */ /* make sure this is an NSPR supported stack */ bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { osfd = (SOCKET) bottom->secret->md.osfd; if (in_flags_read & PR_POLL_READ) { pd->out_flags |= _PR_POLL_READ_SYS_READ; FD_SET(osfd, &rd); nrd++; } if (in_flags_read & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_READ_SYS_WRITE; FD_SET(osfd, &wt); nwt++; } if (in_flags_write & PR_POLL_READ) { pd->out_flags |= _PR_POLL_WRITE_SYS_READ; FD_SET(osfd, &rd); nrd++; } if (in_flags_write & PR_POLL_WRITE) { pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE; FD_SET(osfd, &wt); nwt++; } if (pd->in_flags & PR_POLL_EXCEPT) { FD_SET(osfd, &ex); nex++; } } } else { if (0 == ready) { PRPollDesc *prev; for (prev = pds; prev < pd; prev++) { prev->out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pd->out_flags = PR_POLL_NVAL; /* bogii */ } } } else { pd->out_flags = 0; } } if (0 != ready) return ready; /* no need to block */ /* * FD_SET does nothing if the fd_set's internal fd_array is full. If * nrd, nwt, or nex is greater than FD_SETSIZE, we know FD_SET must * have failed to insert an osfd into the corresponding fd_set, and * therefore we should fail. */ if ((nrd > FD_SETSIZE) || (nwt > FD_SETSIZE) || (nex > FD_SETSIZE)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } rdp = (0 == nrd) ? NULL : &rd; wtp = (0 == nwt) ? NULL : &wt; exp = (0 == nex) ? NULL : &ex; if ((NULL == rdp) && (NULL == wtp) && (NULL == exp)) { PR_Sleep(timeout); return 0; } if (timeout != PR_INTERVAL_NO_TIMEOUT) { PRInt32 ticksPerSecond = PR_TicksPerSecond(); tv.tv_sec = timeout / ticksPerSecond; tv.tv_usec = PR_IntervalToMicroseconds( timeout % ticksPerSecond ); tvp = &tv; } #if defined(_PR_GLOBAL_THREADS_ONLY) ready = _MD_SELECT(0, rdp, wtp, exp, tvp); #else ready = _PR_NTFiberSafeSelect(0, rdp, wtp, exp, tvp); #endif /* ** Now to unravel the select sets back into the client's poll ** descriptor list. Is this possibly an area for pissing away ** a few cycles or what? */ if (ready > 0) { ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { PRInt16 out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { SOCKET osfd; bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); osfd = (SOCKET) bottom->secret->md.osfd; if (FD_ISSET(osfd, &rd)) { if (pd->out_flags & _PR_POLL_READ_SYS_READ) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_READ) out_flags |= PR_POLL_WRITE; } if (FD_ISSET(osfd, &wt)) { if (pd->out_flags & _PR_POLL_READ_SYS_WRITE) out_flags |= PR_POLL_READ; if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE) out_flags |= PR_POLL_WRITE; } if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT; } pd->out_flags = out_flags; if (out_flags) ready++; } PR_ASSERT(ready > 0); } else if (ready == SOCKET_ERROR) { err = WSAGetLastError(); if (err == WSAENOTSOCK) { /* Find the bad fds */ int optval; int optlen = sizeof(optval); ready = 0; for (pd = pds, epd = pd + npds; pd < epd; pd++) { pd->out_flags = 0; if ((NULL != pd->fd) && (0 != pd->in_flags)) { bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET, SO_TYPE, (char *) &optval, &optlen) == -1) { PR_ASSERT(WSAGetLastError() == WSAENOTSOCK); if (WSAGetLastError() == WSAENOTSOCK) { pd->out_flags = PR_POLL_NVAL; ready++; } } } } PR_ASSERT(ready > 0); } else _PR_MD_MAP_SELECT_ERROR(err); } return ready; } nspr-4.11/nspr/pr/src/md/windows/w32rng.c0000644000000000000000000000344612623070344016331 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include static BOOL CurrentClockTickTime(LPDWORD lpdwHigh, LPDWORD lpdwLow) { LARGE_INTEGER liCount; if (!QueryPerformanceCounter(&liCount)) return FALSE; *lpdwHigh = liCount.u.HighPart; *lpdwLow = liCount.u.LowPart; return TRUE; } extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size ) { DWORD dwHigh, dwLow, dwVal; size_t n = 0; size_t nBytes; time_t sTime; if (size <= 0) return 0; CurrentClockTickTime(&dwHigh, &dwLow); // get the maximally changing bits first nBytes = sizeof(dwLow) > size ? size : sizeof(dwLow); memcpy((char *)buf, &dwLow, nBytes); n += nBytes; size -= nBytes; if (size <= 0) return n; nBytes = sizeof(dwHigh) > size ? size : sizeof(dwHigh); memcpy(((char *)buf) + n, &dwHigh, nBytes); n += nBytes; size -= nBytes; if (size <= 0) return n; // get the number of milliseconds that have elapsed since Windows started dwVal = GetTickCount(); nBytes = sizeof(dwVal) > size ? size : sizeof(dwVal); memcpy(((char *)buf) + n, &dwVal, nBytes); n += nBytes; size -= nBytes; if (size <= 0) return n; // get the time in seconds since midnight Jan 1, 1970 time(&sTime); nBytes = sizeof(sTime) > size ? size : sizeof(sTime); memcpy(((char *)buf) + n, &sTime, nBytes); n += nBytes; return n; } nspr-4.11/nspr/pr/src/md/windows/w32shm.c0000644000000000000000000002414512623070344016331 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #if defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY) extern PRLogModuleInfo *_pr_shm_lm; /* * NSPR-to-NT access right mapping table for file-mapping objects. * * The OR of these three access masks must equal FILE_MAP_ALL_ACCESS. * This is because if a file-mapping object with the specified name * exists, CreateFileMapping requests full access to the existing * object. */ static DWORD filemapAccessTable[] = { FILE_MAP_ALL_ACCESS & ~FILE_MAP_WRITE, /* read */ FILE_MAP_ALL_ACCESS & ~FILE_MAP_READ, /* write */ 0 /* execute */ }; extern PRSharedMemory * _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ) { char ipcname[PR_IPC_NAME_SIZE]; PRStatus rc = PR_SUCCESS; DWORD dwHi, dwLo; PRSharedMemory *shm; DWORD flProtect = ( PAGE_READWRITE ); SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) { PR_SetError(PR_UNKNOWN_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: name is invalid")); return(NULL); } shm = PR_NEWZAP( PRSharedMemory ); if ( NULL == shm ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory")); return(NULL); } shm->ipcname = PR_MALLOC( (PRUint32) (strlen( ipcname ) + 1) ); if ( NULL == shm->ipcname ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory")); PR_DELETE(shm); return(NULL); } /* copy args to struct */ strcpy( shm->ipcname, ipcname ); shm->size = size; shm->mode = mode; shm->flags = flags; shm->ident = _PR_SHM_IDENT; if (flags & PR_SHM_CREATE ) { dwHi = (DWORD) (((PRUint64) shm->size >> 32) & 0xffffffff); dwLo = (DWORD) (shm->size & 0xffffffff); if (_PR_NT_MakeSecurityDescriptorACL(mode, filemapAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } #ifdef WINCE { /* * This is assuming that the name will never be larger than * MAX_PATH. Should we dynamically allocate? */ PRUnichar wideIpcName[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, shm->ipcname, -1, wideIpcName, MAX_PATH); shm->handle = CreateFileMappingW( (HANDLE)-1 , lpSA, flProtect, dwHi, dwLo, wideIpcName); } #else shm->handle = CreateFileMappingA( (HANDLE)-1 , lpSA, flProtect, dwHi, dwLo, shm->ipcname); #endif if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if ( NULL == shm->handle ) { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: CreateFileMapping() failed: %s", shm->ipcname )); _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_FREEIF( shm->ipcname ) PR_DELETE( shm ); return(NULL); } else { if (( flags & PR_SHM_EXCL) && ( GetLastError() == ERROR_ALREADY_EXISTS )) { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: Request exclusive & already exists", shm->ipcname )); PR_SetError( PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS ); CloseHandle( shm->handle ); PR_FREEIF( shm->ipcname ) PR_DELETE( shm ); return(NULL); } else { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d", shm->ipcname, shm->handle )); return(shm); } } } else { #ifdef WINCE PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); shm->handle = NULL; /* OpenFileMapping not supported */ #else shm->handle = OpenFileMapping( FILE_MAP_WRITE, TRUE, shm->ipcname ); #endif if ( NULL == shm->handle ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: OpenFileMapping() failed: %s, error: %d", shm->ipcname, PR_GetOSError())); PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return(NULL); } else { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d", shm->ipcname, shm->handle )); return(shm); } } /* returns from separate paths */ } extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ) { PRUint32 access = FILE_MAP_WRITE; void *addr; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); if ( PR_SHM_READONLY & flags ) access = FILE_MAP_READ; addr = MapViewOfFile( shm->handle, access, 0, 0, shm->size ); if ( NULL == addr ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG( _pr_shm_lm, PR_LOG_ERROR, ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d", PR_GetOSError())); } return( addr ); } /* end _MD_ATTACH_SHARED_MEMORY() */ extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ) { PRStatus rc = PR_SUCCESS; BOOL wrc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); wrc = UnmapViewOfFile( addr ); if ( FALSE == wrc ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG( _pr_shm_lm, PR_LOG_ERROR, ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d", PR_GetOSError())); rc = PR_FAILURE; } return( rc ); } extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ) { PRStatus rc = PR_SUCCESS; BOOL wrc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); wrc = CloseHandle( shm->handle ); if ( FALSE == wrc ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG( _pr_shm_lm, PR_LOG_ERROR, ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d", PR_GetOSError())); rc = PR_FAILURE; } PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return( rc ); } /* end _MD_CLOSE_SHARED_MEMORY() */ extern PRStatus _MD_DeleteSharedMemory( const char *name ) { return( PR_SUCCESS ); } /* ** Windows implementation of anonymous memory (file) map */ extern PRLogModuleInfo *_pr_shma_lm; extern PRFileMap* _md_OpenAnonFileMap( const char *dirName, PRSize size, PRFileMapProtect prot ) { PRFileMap *fm; HANDLE hFileMap; fm = PR_CreateFileMap( (PRFileDesc*)-1, size, prot ); if ( NULL == fm ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed")); goto Finished; } /* ** Make fm->md.hFileMap inheritable. We can't use ** GetHandleInformation and SetHandleInformation ** because these two functions fail with ** ERROR_CALL_NOT_IMPLEMENTED on Win95. */ if (DuplicateHandle(GetCurrentProcess(), fm->md.hFileMap, GetCurrentProcess(), &hFileMap, 0, TRUE /* inheritable */, DUPLICATE_SAME_ACCESS) == FALSE) { PR_SetError( PR_UNKNOWN_ERROR, GetLastError() ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): DuplicateHandle(): failed")); PR_CloseFileMap( fm ); fm = NULL; goto Finished; } CloseHandle(fm->md.hFileMap); fm->md.hFileMap = hFileMap; Finished: return(fm); } /* end md_OpenAnonFileMap() */ /* ** _md_ExportFileMapAsString() ** */ extern PRStatus _md_ExportFileMapAsString( PRFileMap *fm, PRSize bufSize, char *buf ) { PRIntn written; written = PR_snprintf( buf, (PRUint32) bufSize, "%d:%" PR_PRIdOSFD ":%ld", (PRIntn)fm->prot, (PROsfd)fm->md.hFileMap, (PRInt32)fm->md.dwAccess ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ExportFileMapAsString(): prot: %x, hFileMap: %x, dwAccess: %x", fm->prot, fm->md.hFileMap, fm->md.dwAccess )); return((written == -1)? PR_FAILURE : PR_SUCCESS); } /* end _md_ExportFileMapAsString() */ /* ** _md_ImportFileMapFromString() ** */ extern PRFileMap * _md_ImportFileMapFromString( const char *fmstring ) { PRIntn prot; PROsfd hFileMap; PRInt32 dwAccess; PRFileMap *fm = NULL; PR_sscanf( fmstring, "%d:%" PR_SCNdOSFD ":%ld", &prot, &hFileMap, &dwAccess ); fm = PR_NEWZAP(PRFileMap); if ( NULL == fm ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed")); return(fm); } fm->prot = (PRFileMapProtect)prot; fm->md.hFileMap = (HANDLE)hFileMap; fm->md.dwAccess = (DWORD)dwAccess; fm->fd = (PRFileDesc*)-1; PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): fm: %p, prot: %d, hFileMap: %8.8x, dwAccess: %8.8x, fd: %x", fm, prot, fm->md.hFileMap, fm->md.dwAccess, fm->fd)); return(fm); } /* end _md_ImportFileMapFromString() */ #else Error! Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY not defined? #endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */ /* --- end w32shm.c --- */ nspr-4.11/nspr/pr/src/md/windows/w95cv.c0000644000000000000000000002666012623070344016167 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * w95cv.c -- Windows 95 Machine-Dependent Code for Condition Variables * * We implement our own condition variable wait queue. Each thread * has a semaphore object (thread->md.blocked_sema) to block on while * waiting on a condition variable. * * We use a deferred condition notify algorithm. When PR_NotifyCondVar * or PR_NotifyAllCondVar is called, the condition notifies are simply * recorded in the _MDLock structure. We defer the condition notifies * until right after we unlock the lock. This way the awakened threads * have a better chance to reaquire the lock. */ #include "primpl.h" /* * AddThreadToCVWaitQueueInternal -- * * Add the thread to the end of the condition variable's wait queue. * The CV's lock must be locked when this function is called. */ static void AddThreadToCVWaitQueueInternal(PRThread *thred, struct _MDCVar *cv) { PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL) || (cv->waitTail == NULL && cv->waitHead == NULL)); cv->nwait += 1; thred->md.inCVWaitQueue = PR_TRUE; thred->md.next = NULL; thred->md.prev = cv->waitTail; if (cv->waitHead == NULL) { cv->waitHead = thred; } else { cv->waitTail->md.next = thred; } cv->waitTail = thred; } /* * md_UnlockAndPostNotifies -- * * Unlock the lock, and then do the deferred condition notifies. * If waitThred and waitCV are not NULL, waitThred is added to * the wait queue of waitCV before the lock is unlocked. * * This function is called by _PR_MD_WAIT_CV and _PR_MD_UNLOCK, * the two places where a lock is unlocked. */ static void md_UnlockAndPostNotifies( _MDLock *lock, PRThread *waitThred, _MDCVar *waitCV) { PRIntn index; _MDNotified post; _MDNotified *notified, *prev = NULL; /* * Time to actually notify any conditions that were affected * while the lock was held. Get a copy of the list that's in * the lock structure and then zero the original. If it's * linked to other such structures, we own that storage. */ post = lock->notified; /* a safe copy; we own the lock */ #if defined(DEBUG) ZeroMemory(&lock->notified, sizeof(_MDNotified)); /* reset */ #else lock->notified.length = 0; /* these are really sufficient */ lock->notified.link = NULL; #endif /* * Figure out how many threads we need to wake up. */ notified = &post; /* this is where we start */ do { for (index = 0; index < notified->length; ++index) { _MDCVar *cv = notified->cv[index].cv; PRThread *thred; int i; /* Fast special case: no waiting threads */ if (cv->waitHead == NULL) { notified->cv[index].notifyHead = NULL; continue; } /* General case */ if (-1 == notified->cv[index].times) { /* broadcast */ thred = cv->waitHead; while (thred != NULL) { thred->md.inCVWaitQueue = PR_FALSE; thred = thred->md.next; } notified->cv[index].notifyHead = cv->waitHead; cv->waitHead = cv->waitTail = NULL; cv->nwait = 0; } else { thred = cv->waitHead; i = notified->cv[index].times; while (thred != NULL && i > 0) { thred->md.inCVWaitQueue = PR_FALSE; thred = thred->md.next; i--; } notified->cv[index].notifyHead = cv->waitHead; cv->waitHead = thred; if (cv->waitHead == NULL) { cv->waitTail = NULL; } else { if (cv->waitHead->md.prev != NULL) { cv->waitHead->md.prev->md.next = NULL; cv->waitHead->md.prev = NULL; } } cv->nwait -= notified->cv[index].times - i; } } notified = notified->link; } while (NULL != notified); if (waitThred) { AddThreadToCVWaitQueueInternal(waitThred, waitCV); } /* Release the lock before notifying */ LeaveCriticalSection(&lock->mutex); notified = &post; /* this is where we start */ do { for (index = 0; index < notified->length; ++index) { PRThread *thred; PRThread *next; thred = notified->cv[index].notifyHead; while (thred != NULL) { BOOL rv; next = thred->md.next; thred->md.prev = thred->md.next = NULL; rv = ReleaseSemaphore(thred->md.blocked_sema, 1, NULL); PR_ASSERT(rv != 0); thred = next; } } prev = notified; notified = notified->link; if (&post != prev) PR_DELETE(prev); } while (NULL != notified); } /* * Notifies just get posted to the protecting mutex. The * actual notification is done when the lock is released so that * MP systems don't contend for a lock that they can't have. */ static void md_PostNotifyToCvar(_MDCVar *cvar, _MDLock *lock, PRBool broadcast) { PRIntn index = 0; _MDNotified *notified = &lock->notified; while (1) { for (index = 0; index < notified->length; ++index) { if (notified->cv[index].cv == cvar) { if (broadcast) { notified->cv[index].times = -1; } else if (-1 != notified->cv[index].times) { notified->cv[index].times += 1; } return; } } /* if not full, enter new CV in this array */ if (notified->length < _MD_CV_NOTIFIED_LENGTH) break; /* if there's no link, create an empty array and link it */ if (NULL == notified->link) { notified->link = PR_NEWZAP(_MDNotified); } notified = notified->link; } /* A brand new entry in the array */ notified->cv[index].times = (broadcast) ? -1 : 1; notified->cv[index].cv = cvar; notified->length += 1; } /* * _PR_MD_NEW_CV() -- Creating new condition variable * ... Solaris uses cond_init() in similar function. * * returns: -1 on failure * 0 when it succeeds. * */ PRInt32 _PR_MD_NEW_CV(_MDCVar *cv) { cv->magic = _MD_MAGIC_CV; /* * The waitHead, waitTail, and nwait fields are zeroed * when the PRCondVar structure is created. */ return 0; } void _PR_MD_FREE_CV(_MDCVar *cv) { cv->magic = (PRUint32)-1; return; } /* * _PR_MD_WAIT_CV() -- Wait on condition variable */ void _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout ) { PRThread *thred = _PR_MD_CURRENT_THREAD(); DWORD rv; DWORD msecs = (timeout == PR_INTERVAL_NO_TIMEOUT) ? INFINITE : PR_IntervalToMilliseconds(timeout); /* * If we have pending notifies, post them now. */ if (0 != lock->notified.length) { md_UnlockAndPostNotifies(lock, thred, cv); } else { AddThreadToCVWaitQueueInternal(thred, cv); LeaveCriticalSection(&lock->mutex); } /* Wait for notification or timeout; don't really care which */ rv = WaitForSingleObject(thred->md.blocked_sema, msecs); EnterCriticalSection(&(lock->mutex)); PR_ASSERT(rv != WAIT_ABANDONED); PR_ASSERT(rv != WAIT_FAILED); PR_ASSERT(rv != WAIT_OBJECT_0 || thred->md.inCVWaitQueue == PR_FALSE); if (rv == WAIT_TIMEOUT) { if (thred->md.inCVWaitQueue) { PR_ASSERT((cv->waitTail != NULL && cv->waitHead != NULL) || (cv->waitTail == NULL && cv->waitHead == NULL)); cv->nwait -= 1; thred->md.inCVWaitQueue = PR_FALSE; if (cv->waitHead == thred) { cv->waitHead = thred->md.next; if (cv->waitHead == NULL) { cv->waitTail = NULL; } else { cv->waitHead->md.prev = NULL; } } else { PR_ASSERT(thred->md.prev != NULL); thred->md.prev->md.next = thred->md.next; if (thred->md.next != NULL) { thred->md.next->md.prev = thred->md.prev; } else { PR_ASSERT(cv->waitTail == thred); cv->waitTail = thred->md.prev; } } thred->md.next = thred->md.prev = NULL; } else { /* * This thread must have been notified, but the * ReleaseSemaphore call happens after WaitForSingleObject * times out. Wait on the semaphore again to make it * non-signaled. We assume this wait won't take long. */ rv = WaitForSingleObject(thred->md.blocked_sema, INFINITE); PR_ASSERT(rv == WAIT_OBJECT_0); } } PR_ASSERT(thred->md.inCVWaitQueue == PR_FALSE); return; } /* --- end _PR_MD_WAIT_CV() --- */ void _PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock) { md_PostNotifyToCvar(cv, lock, PR_FALSE); return; } void _PR_MD_NOTIFYALL_CV(_MDCVar *cv, _MDLock *lock) { md_PostNotifyToCvar(cv, lock, PR_TRUE); return; } typedef BOOL (WINAPI *INITIALIZECRITICALSECTIONEX)( CRITICAL_SECTION *lpCriticalSection, DWORD dwSpinCount, DWORD Flags); static INITIALIZECRITICALSECTIONEX sInitializeCriticalSectionEx; void _PR_MD_INIT_LOCKS(void) { /* * Starting with Windows Vista, every CRITICAL_SECTION allocates an extra * RTL_CRITICAL_SECTION_DEBUG object. Unfortunately, this debug object is * not reclaimed by DeleteCriticalSection(), causing an apparent memory * leak. This is a debugging "feature", not a bug. If we are running on * Vista or later, use InitializeCriticalSectionEx() to allocate * CRITICAL_SECTIONs without debug objects. */ HMODULE hKernel32 = GetModuleHandle("kernel32.dll"); PR_ASSERT(hKernel32); PR_ASSERT(!sInitializeCriticalSectionEx); sInitializeCriticalSectionEx = (INITIALIZECRITICALSECTIONEX) GetProcAddress(hKernel32, "InitializeCriticalSectionEx"); } /* * By default, CRITICAL_SECTIONs are initialized with a spin count of 0. * Joe Duffy's "Concurrent Programming on Windows" book suggests 1500 is * a "reasonable starting point". On single-processor systems, the spin * count is ignored and the critical section spin count is set to 0. */ #define LOCK_SPIN_COUNT 1500 PRStatus _PR_MD_NEW_LOCK(_MDLock *lock) { CRITICAL_SECTION *cs = &lock->mutex; BOOL ok; if (sInitializeCriticalSectionEx) { ok = sInitializeCriticalSectionEx(cs, LOCK_SPIN_COUNT, CRITICAL_SECTION_NO_DEBUG_INFO); } else { ok = InitializeCriticalSectionAndSpinCount(cs, LOCK_SPIN_COUNT); } if (!ok) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } lock->notified.length = 0; lock->notified.link = NULL; return PR_SUCCESS; } void _PR_MD_UNLOCK(_MDLock *lock) { if (0 != lock->notified.length) { md_UnlockAndPostNotifies(lock, NULL, NULL); } else { LeaveCriticalSection(&lock->mutex); } } nspr-4.11/nspr/pr/src/md/windows/w95dllmain.c0000644000000000000000000000200212623070344017157 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * The DLL entry point (DllMain) for NSPR. * * This is used to detach threads that were automatically attached by * nspr. */ #include #include BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { PRThread *me; switch (fdwReason) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: if (_pr_initialized) { me = _MD_GET_ATTACHED_THREAD(); if ((me != NULL) && (me->flags & _PR_ATTACHED)) _PRI_DetachThread(); } break; case DLL_PROCESS_DETACH: break; } return TRUE; } nspr-4.11/nspr/pr/src/md/windows/w95io.c0000644000000000000000000010644512623070344016166 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Windows 95 IO module * * Assumes synchronous I/O. * */ #include "primpl.h" #include #include #ifdef MOZ_UNICODE #include #endif /* MOZ_UNICODE */ struct _MDLock _pr_ioq_lock; /* * NSPR-to-NT access right mapping table for files. */ static DWORD fileAccessTable[] = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE }; /* * NSPR-to-NT access right mapping table for directories. */ static DWORD dirAccessTable[] = { FILE_GENERIC_READ, FILE_GENERIC_WRITE|FILE_DELETE_CHILD, FILE_GENERIC_EXECUTE }; static PRBool IsPrevCharSlash(const char *str, const char *current); void _PR_MD_INIT_IO() { WORD WSAVersion = 0x0101; WSADATA WSAData; int err; err = WSAStartup( WSAVersion, &WSAData ); PR_ASSERT(0 == err); #ifdef DEBUG /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */ { SYSTEMTIME systime; union { PRTime prt; FILETIME ft; } filetime; BOOL rv; systime.wYear = 1970; systime.wMonth = 1; /* wDayOfWeek is ignored */ systime.wDay = 1; systime.wHour = 0; systime.wMinute = 0; systime.wSecond = 0; systime.wMilliseconds = 0; rv = SystemTimeToFileTime(&systime, &filetime.ft); PR_ASSERT(0 != rv); PR_ASSERT(filetime.prt == _pr_filetime_offset); } #endif /* DEBUG */ _PR_NT_InitSids(); _PR_MD_InitSockets(); } PRStatus _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks) { DWORD rv; PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? INFINITE : PR_IntervalToMilliseconds(ticks); rv = WaitForSingleObject(thread->md.blocked_sema, msecs); switch(rv) { case WAIT_OBJECT_0: return PR_SUCCESS; case WAIT_TIMEOUT: _PR_THREAD_LOCK(thread); if (thread->state == _PR_IO_WAIT) { ; } else { if (thread->wait.cvar != NULL) { thread->wait.cvar = NULL; _PR_THREAD_UNLOCK(thread); } else { /* The CVAR was notified just as the timeout * occurred. This led to us being notified twice. * call WaitForSingleObject() to clear the semaphore. */ _PR_THREAD_UNLOCK(thread); rv = WaitForSingleObject(thread->md.blocked_sema, 0); PR_ASSERT(rv == WAIT_OBJECT_0); } } return PR_SUCCESS; default: return PR_FAILURE; } } PRStatus _PR_MD_WAKEUP_WAITER(PRThread *thread) { if ( _PR_IS_NATIVE_THREAD(thread) ) { if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE) return PR_FAILURE; else return PR_SUCCESS; } } /* --- FILE IO ----------------------------------------------------------- */ /* * _PR_MD_OPEN() -- Open a file * * returns: a fileHandle * * The NSPR open flags (osflags) are translated into flags for Win95 * * Mode seems to be passed in as a unix style file permissions argument * as in 0666, in the case of opening the logFile. * */ PROsfd _PR_MD_OPEN(const char *name, PRIntn osflags, int mode) { HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) { if (osflags & PR_TRUNCATE) flags = CREATE_ALWAYS; else flags = OPEN_ALWAYS; } else { if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; } file = CreateFileA(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, flags, flag6, NULL); if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } return (PROsfd)file; } PROsfd _PR_MD_OPEN_FILE(const char *name, PRIntn osflags, int mode) { HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; if (osflags & PR_CREATE_FILE) { if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } } if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) { if (osflags & PR_TRUNCATE) flags = CREATE_ALWAYS; else flags = OPEN_ALWAYS; } else { if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; } file = CreateFileA(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, lpSA, flags, flag6, NULL); if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } return (PROsfd)file; } PRInt32 _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) { PRUint32 bytes; int rv, err; rv = ReadFile((HANDLE)fd->secret->md.osfd, (LPVOID)buf, len, &bytes, NULL); if (rv == 0) { err = GetLastError(); /* ERROR_HANDLE_EOF can only be returned by async io */ PR_ASSERT(err != ERROR_HANDLE_EOF); if (err == ERROR_BROKEN_PIPE) return 0; else { _PR_MD_MAP_READ_ERROR(err); return -1; } } return bytes; } PRInt32 _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) { PROsfd f = fd->secret->md.osfd; PRInt32 bytes; int rv; rv = WriteFile((HANDLE)f, buf, len, &bytes, NULL ); if (rv == 0) { _PR_MD_MAP_WRITE_ERROR(GetLastError()); return -1; } return bytes; } /* --- end _PR_MD_WRITE() --- */ PROffset32 _PR_MD_LSEEK(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence) { DWORD moveMethod; PROffset32 rv; switch (whence) { case PR_SEEK_SET: moveMethod = FILE_BEGIN; break; case PR_SEEK_CUR: moveMethod = FILE_CURRENT; break; case PR_SEEK_END: moveMethod = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } rv = SetFilePointer((HANDLE)fd->secret->md.osfd, offset, NULL, moveMethod); /* * If the lpDistanceToMoveHigh argument (third argument) is * NULL, SetFilePointer returns 0xffffffff on failure. */ if (-1 == rv) { _PR_MD_MAP_LSEEK_ERROR(GetLastError()); } return rv; } PROffset64 _PR_MD_LSEEK64(PRFileDesc *fd, PROffset64 offset, PRSeekWhence whence) { DWORD moveMethod; LARGE_INTEGER li; DWORD err; switch (whence) { case PR_SEEK_SET: moveMethod = FILE_BEGIN; break; case PR_SEEK_CUR: moveMethod = FILE_CURRENT; break; case PR_SEEK_END: moveMethod = FILE_END; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } li.QuadPart = offset; li.LowPart = SetFilePointer((HANDLE)fd->secret->md.osfd, li.LowPart, &li.HighPart, moveMethod); if (0xffffffff == li.LowPart && (err = GetLastError()) != NO_ERROR) { _PR_MD_MAP_LSEEK_ERROR(err); li.QuadPart = -1; } return li.QuadPart; } /* * This is documented to succeed on read-only files, but Win32's * FlushFileBuffers functions fails with "access denied" in such a * case. So we only signal an error if the error is *not* "access * denied". */ PRInt32 _PR_MD_FSYNC(PRFileDesc *fd) { /* * From the documentation: * * On Windows NT, the function FlushFileBuffers fails if hFile * is a handle to console output. That is because console * output is not buffered. The function returns FALSE, and * GetLastError returns ERROR_INVALID_HANDLE. * * On the other hand, on Win95, it returns without error. I cannot * assume that 0, 1, and 2 are console, because if someone closes * System.out and then opens a file, they might get file descriptor * 1. An error on *that* version of 1 should be reported, whereas * an error on System.out (which was the original 1) should be * ignored. So I use isatty() to ensure that such an error was due * to this bogosity, and if it was, I ignore the error. */ BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd); if (!ok) { DWORD err = GetLastError(); if (err != ERROR_ACCESS_DENIED) { // from winerror.h _PR_MD_MAP_FSYNC_ERROR(err); return -1; } } return 0; } PRInt32 _MD_CloseFile(PROsfd osfd) { PRInt32 rv; rv = (CloseHandle((HANDLE)osfd))?0:-1; if (rv == -1) _PR_MD_MAP_CLOSE_ERROR(GetLastError()); return rv; } /* --- DIR IO ------------------------------------------------------------ */ #define GetFileFromDIR(d) (d)->d_entry.cFileName #define FileIsHidden(d) ((d)->d_entry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) static void FlipSlashes(char *cp, size_t len) { while (len-- > 0) { if (cp[0] == '/') { cp[0] = PR_DIRECTORY_SEPARATOR; } cp = _mbsinc(cp); } } /* end FlipSlashes() */ /* ** ** Local implementations of standard Unix RTL functions which are not provided ** by the VC RTL. ** */ PRInt32 _PR_MD_CLOSE_DIR(_MDDir *d) { if ( d ) { if (FindClose(d->d_hdl)) { d->magic = (PRUint32)-1; return 0; } else { _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError()); return -1; } } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } PRStatus _PR_MD_OPEN_DIR(_MDDir *d, const char *name) { char filename[ MAX_PATH ]; size_t len; len = strlen(name); /* Need 5 bytes for \*.* and the trailing null byte. */ if (len + 5 > MAX_PATH) { PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); return PR_FAILURE; } strcpy(filename, name); /* * If 'name' ends in a slash or backslash, do not append * another backslash. */ if (IsPrevCharSlash(filename, filename + len)) { len--; } strcpy(&filename[len], "\\*.*"); FlipSlashes( filename, strlen(filename) ); d->d_hdl = FindFirstFileA( filename, &(d->d_entry) ); if ( d->d_hdl == INVALID_HANDLE_VALUE ) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return PR_FAILURE; } d->firstEntry = PR_TRUE; d->magic = _MD_MAGIC_DIR; return PR_SUCCESS; } char * _PR_MD_READ_DIR(_MDDir *d, PRIntn flags) { PRInt32 err; BOOL rv; char *fileName; if ( d ) { while (1) { if (d->firstEntry) { d->firstEntry = PR_FALSE; rv = 1; } else { rv = FindNextFileA(d->d_hdl, &(d->d_entry)); } if (rv == 0) { break; } fileName = GetFileFromDIR(d); if ( (flags & PR_SKIP_DOT) && (fileName[0] == '.') && (fileName[1] == '\0')) continue; if ( (flags & PR_SKIP_DOT_DOT) && (fileName[0] == '.') && (fileName[1] == '.') && (fileName[2] == '\0')) continue; if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) continue; return fileName; } err = GetLastError(); PR_ASSERT(NO_ERROR != err); _PR_MD_MAP_READDIR_ERROR(err); return NULL; } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } PRInt32 _PR_MD_DELETE(const char *name) { if (DeleteFileA(name)) { return 0; } else { _PR_MD_MAP_DELETE_ERROR(GetLastError()); return -1; } } void _PR_FileTimeToPRTime(const FILETIME *filetime, PRTime *prtm) { PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime)); CopyMemory(prtm, filetime, sizeof(PRTime)); #if defined(__MINGW32__) *prtm = (*prtm - _pr_filetime_offset) / 10LL; #else *prtm = (*prtm - _pr_filetime_offset) / 10i64; #endif #ifdef DEBUG /* Doublecheck our calculation. */ { SYSTEMTIME systime; PRExplodedTime etm; PRTime cmp; /* for comparison */ BOOL rv; rv = FileTimeToSystemTime(filetime, &systime); PR_ASSERT(0 != rv); /* * PR_ImplodeTime ignores wday and yday. */ etm.tm_usec = systime.wMilliseconds * PR_USEC_PER_MSEC; etm.tm_sec = systime.wSecond; etm.tm_min = systime.wMinute; etm.tm_hour = systime.wHour; etm.tm_mday = systime.wDay; etm.tm_month = systime.wMonth - 1; etm.tm_year = systime.wYear; /* * It is not well-documented what time zone the FILETIME's * are in. WIN32_FIND_DATA is documented to be in UTC (GMT). * But BY_HANDLE_FILE_INFORMATION is unclear about this. * By our best judgement, we assume that FILETIME is in UTC. */ etm.tm_params.tp_gmt_offset = 0; etm.tm_params.tp_dst_offset = 0; cmp = PR_ImplodeTime(&etm); /* * SYSTEMTIME is in milliseconds precision, so we convert PRTime's * microseconds to milliseconds before doing the comparison. */ PR_ASSERT((cmp / PR_USEC_PER_MSEC) == (*prtm / PR_USEC_PER_MSEC)); } #endif /* DEBUG */ } PRInt32 _PR_MD_STAT(const char *fn, struct stat *info) { PRInt32 rv; rv = _stat(fn, (struct _stat *)info); if (-1 == rv) { /* * Check for MSVC runtime library _stat() bug. * (It's really a bug in FindFirstFile().) * If a pathname ends in a backslash or slash, * e.g., c:\temp\ or c:/temp/, _stat() will fail. * Note: a pathname ending in a slash (e.g., c:/temp/) * can be handled by _stat() on NT but not on Win95. * * We remove the backslash or slash at the end and * try again. */ size_t len = strlen(fn); if (len > 0 && len <= _MAX_PATH && IsPrevCharSlash(fn, fn + len)) { char newfn[_MAX_PATH + 1]; strcpy(newfn, fn); newfn[len - 1] = '\0'; rv = _stat(newfn, (struct _stat *)info); } } if (-1 == rv) { _PR_MD_MAP_STAT_ERROR(errno); } return rv; } #define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\') static PRBool IsPrevCharSlash(const char *str, const char *current) { const char *prev; if (str >= current) return PR_FALSE; prev = _mbsdec(str, current); return (prev == current - 1) && _PR_IS_SLASH(*prev); } /* * IsRootDirectory -- * * Return PR_TRUE if the pathname 'fn' is a valid root directory, * else return PR_FALSE. The char buffer pointed to by 'fn' must * be writable. During the execution of this function, the contents * of the buffer pointed to by 'fn' may be modified, but on return * the original contents will be restored. 'buflen' is the size of * the buffer pointed to by 'fn'. * * Root directories come in three formats: * 1. / or \, meaning the root directory of the current drive. * 2. C:/ or C:\, where C is a drive letter. * 3. \\\\ or * \\\, meaning the root directory * of a UNC (Universal Naming Convention) name. */ static PRBool IsRootDirectory(char *fn, size_t buflen) { char *p; PRBool slashAdded = PR_FALSE; PRBool rv = PR_FALSE; if (_PR_IS_SLASH(fn[0]) && fn[1] == '\0') { return PR_TRUE; } if (isalpha(fn[0]) && fn[1] == ':' && _PR_IS_SLASH(fn[2]) && fn[3] == '\0') { rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE; return rv; } /* The UNC root directory */ if (_PR_IS_SLASH(fn[0]) && _PR_IS_SLASH(fn[1])) { /* The 'server' part should have at least one character. */ p = &fn[2]; if (*p == '\0' || _PR_IS_SLASH(*p)) { return PR_FALSE; } /* look for the next slash */ do { p = _mbsinc(p); } while (*p != '\0' && !_PR_IS_SLASH(*p)); if (*p == '\0') { return PR_FALSE; } /* The 'share' part should have at least one character. */ p++; if (*p == '\0' || _PR_IS_SLASH(*p)) { return PR_FALSE; } /* look for the final slash */ do { p = _mbsinc(p); } while (*p != '\0' && !_PR_IS_SLASH(*p)); if (_PR_IS_SLASH(*p) && p[1] != '\0') { return PR_FALSE; } if (*p == '\0') { /* * GetDriveType() doesn't work correctly if the * path is of the form \\server\share, so we add * a final slash temporarily. */ if ((p + 1) < (fn + buflen)) { *p++ = '\\'; *p = '\0'; slashAdded = PR_TRUE; } else { return PR_FALSE; /* name too long */ } } rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE; /* restore the 'fn' buffer */ if (slashAdded) { *--p = '\0'; } } return rv; } PRInt32 _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) { WIN32_FILE_ATTRIBUTE_DATA findFileData; BOOL rv; if (NULL == fn || '\0' == *fn) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } rv = GetFileAttributesEx(fn, GetFileExInfoStandard, &findFileData); if (!rv) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { info->type = PR_FILE_DIRECTORY; } else { info->type = PR_FILE_FILE; } info->size = findFileData.nFileSizeHigh; info->size = (info->size << 32) + findFileData.nFileSizeLow; _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime); if (0 == findFileData.ftCreationTime.dwLowDateTime && 0 == findFileData.ftCreationTime.dwHighDateTime) { info->creationTime = info->modifyTime; } else { _PR_FileTimeToPRTime(&findFileData.ftCreationTime, &info->creationTime); } return 0; } PRInt32 _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info) { PRFileInfo64 info64; PRInt32 rv = _PR_MD_GETFILEINFO64(fn, &info64); if (0 == rv) { info->type = info64.type; info->size = (PRUint32) info64.size; info->modifyTime = info64.modifyTime; info->creationTime = info64.creationTime; } return rv; } PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info) { int rv; BY_HANDLE_FILE_INFORMATION hinfo; rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo); if (rv == FALSE) { _PR_MD_MAP_FSTAT_ERROR(GetLastError()); return -1; } if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) info->type = PR_FILE_DIRECTORY; else info->type = PR_FILE_FILE; info->size = hinfo.nFileSizeHigh; info->size = (info->size << 32) + hinfo.nFileSizeLow; _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime) ); _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime) ); return 0; } PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info) { PRFileInfo64 info64; int rv = _PR_MD_GETOPENFILEINFO64(fd, &info64); if (0 == rv) { info->type = info64.type; info->modifyTime = info64.modifyTime; info->creationTime = info64.creationTime; LL_L2I(info->size, info64.size); } return rv; } PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) { BOOL rv; /* * The SetHandleInformation function fails with the * ERROR_CALL_NOT_IMPLEMENTED error on Win95. */ rv = SetHandleInformation( (HANDLE)fd->secret->md.osfd, HANDLE_FLAG_INHERIT, inheritable ? HANDLE_FLAG_INHERIT : 0); if (0 == rv) { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } return PR_SUCCESS; } void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported) { if (imported) { fd->secret->inheritable = _PR_TRI_UNKNOWN; } else { fd->secret->inheritable = _PR_TRI_FALSE; } } void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd) { DWORD flags; PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); if (GetHandleInformation((HANDLE)fd->secret->md.osfd, &flags)) { if (flags & HANDLE_FLAG_INHERIT) { fd->secret->inheritable = _PR_TRI_TRUE; } else { fd->secret->inheritable = _PR_TRI_FALSE; } } } PRInt32 _PR_MD_RENAME(const char *from, const char *to) { /* Does this work with dot-relative pathnames? */ if (MoveFileA(from, to)) { return 0; } else { _PR_MD_MAP_RENAME_ERROR(GetLastError()); return -1; } } PRInt32 _PR_MD_ACCESS(const char *name, PRAccessHow how) { PRInt32 rv; switch (how) { case PR_ACCESS_WRITE_OK: rv = _access(name, 02); break; case PR_ACCESS_READ_OK: rv = _access(name, 04); break; case PR_ACCESS_EXISTS: return _access(name, 00); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } if (rv < 0) _PR_MD_MAP_ACCESS_ERROR(errno); return rv; } PRInt32 _PR_MD_MKDIR(const char *name, PRIntn mode) { /* XXXMB - how to translate the "mode"??? */ if (CreateDirectoryA(name, NULL)) { return 0; } else { _PR_MD_MAP_MKDIR_ERROR(GetLastError()); return -1; } } PRInt32 _PR_MD_MAKE_DIR(const char *name, PRIntn mode) { BOOL rv; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } rv = CreateDirectoryA(name, lpSA); if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (rv) { return 0; } else { _PR_MD_MAP_MKDIR_ERROR(GetLastError()); return -1; } } PRInt32 _PR_MD_RMDIR(const char *name) { if (RemoveDirectoryA(name)) { return 0; } else { _PR_MD_MAP_RMDIR_ERROR(GetLastError()); return -1; } } PRStatus _PR_MD_LOCKFILE(PROsfd f) { PRStatus rc = PR_SUCCESS; DWORD rv; rv = LockFile( (HANDLE)f, 0l, 0l, 0x0l, 0xffffffffl ); if ( rv == 0 ) { DWORD err = GetLastError(); _PR_MD_MAP_DEFAULT_ERROR(err); PR_LOG( _pr_io_lm, PR_LOG_ERROR, ("_PR_MD_LOCKFILE() failed. Error: %d", err )); rc = PR_FAILURE; } return rc; } /* end _PR_MD_LOCKFILE() */ PRStatus _PR_MD_TLOCKFILE(PROsfd f) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return PR_FAILURE; } /* end _PR_MD_TLOCKFILE() */ PRStatus _PR_MD_UNLOCKFILE(PROsfd f) { PRInt32 rv; rv = UnlockFile( (HANDLE) f, 0l, 0l, 0x0l, 0xffffffffl ); if ( rv ) { return PR_SUCCESS; } else { _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); return PR_FAILURE; } } /* end _PR_MD_UNLOCKFILE() */ PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc *fd) { if (NULL == fd) PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } #ifdef MOZ_UNICODE typedef HANDLE (WINAPI *CreateFileWFn) (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); static CreateFileWFn createFileW = CreateFileW; typedef HANDLE (WINAPI *FindFirstFileWFn) (LPCWSTR, LPWIN32_FIND_DATAW); static FindFirstFileWFn findFirstFileW = FindFirstFileW; typedef BOOL (WINAPI *FindNextFileWFn) (HANDLE, LPWIN32_FIND_DATAW); static FindNextFileWFn findNextFileW = FindNextFileW; typedef DWORD (WINAPI *GetFullPathNameWFn) (LPCWSTR, DWORD, LPWSTR, LPWSTR *); static GetFullPathNameWFn getFullPathNameW = GetFullPathNameW; typedef UINT (WINAPI *GetDriveTypeWFn) (LPCWSTR); static GetDriveTypeWFn getDriveTypeW = GetDriveTypeW; #endif /* MOZ_UNICODE */ #ifdef MOZ_UNICODE /* ================ UTF16 Interfaces ================================ */ static void FlipSlashesW(PRUnichar *cp, size_t len) { while (len-- > 0) { if (cp[0] == L'/') { cp[0] = L'\\'; } cp++; } } /* end FlipSlashesW() */ PROsfd _PR_MD_OPEN_FILE_UTF16(const PRUnichar *name, PRIntn osflags, int mode) { HANDLE file; PRInt32 access = 0; PRInt32 flags = 0; PRInt32 flag6 = 0; SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; if (osflags & PR_CREATE_FILE) { if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } } if (osflags & PR_SYNC) flag6 = FILE_FLAG_WRITE_THROUGH; if (osflags & PR_RDONLY || osflags & PR_RDWR) access |= GENERIC_READ; if (osflags & PR_WRONLY || osflags & PR_RDWR) access |= GENERIC_WRITE; if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) flags = CREATE_NEW; else if (osflags & PR_CREATE_FILE) { if (osflags & PR_TRUNCATE) flags = CREATE_ALWAYS; else flags = OPEN_ALWAYS; } else { if (osflags & PR_TRUNCATE) flags = TRUNCATE_EXISTING; else flags = OPEN_EXISTING; } file = createFileW(name, access, FILE_SHARE_READ|FILE_SHARE_WRITE, lpSA, flags, flag6, NULL); if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if (file == INVALID_HANDLE_VALUE) { _PR_MD_MAP_OPEN_ERROR(GetLastError()); return -1; } return (PROsfd)file; } PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16 *d, const PRUnichar *name) { PRUnichar filename[ MAX_PATH ]; int len; len = wcslen(name); /* Need 5 bytes for \*.* and the trailing null byte. */ if (len + 5 > MAX_PATH) { PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); return PR_FAILURE; } wcscpy(filename, name); /* * If 'name' ends in a slash or backslash, do not append * another backslash. */ if (filename[len - 1] == L'/' || filename[len - 1] == L'\\') { len--; } wcscpy(&filename[len], L"\\*.*"); FlipSlashesW( filename, wcslen(filename) ); d->d_hdl = findFirstFileW( filename, &(d->d_entry) ); if ( d->d_hdl == INVALID_HANDLE_VALUE ) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return PR_FAILURE; } d->firstEntry = PR_TRUE; d->magic = _MD_MAGIC_DIR; return PR_SUCCESS; } PRUnichar * _PR_MD_READ_DIR_UTF16(_MDDirUTF16 *d, PRIntn flags) { PRInt32 err; BOOL rv; PRUnichar *fileName; if ( d ) { while (1) { if (d->firstEntry) { d->firstEntry = PR_FALSE; rv = 1; } else { rv = findNextFileW(d->d_hdl, &(d->d_entry)); } if (rv == 0) { break; } fileName = GetFileFromDIR(d); if ( (flags & PR_SKIP_DOT) && (fileName[0] == L'.') && (fileName[1] == L'\0')) continue; if ( (flags & PR_SKIP_DOT_DOT) && (fileName[0] == L'.') && (fileName[1] == L'.') && (fileName[2] == L'\0')) continue; if ( (flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) continue; return fileName; } err = GetLastError(); PR_ASSERT(NO_ERROR != err); _PR_MD_MAP_READDIR_ERROR(err); return NULL; } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16 *d) { if ( d ) { if (FindClose(d->d_hdl)) { d->magic = (PRUint32)-1; return 0; } else { _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError()); return -1; } } PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } #define _PR_IS_W_SLASH(ch) ((ch) == L'/' || (ch) == L'\\') /* * IsRootDirectoryW -- * * Return PR_TRUE if the pathname 'fn' is a valid root directory, * else return PR_FALSE. The PRUnichar buffer pointed to by 'fn' must * be writable. During the execution of this function, the contents * of the buffer pointed to by 'fn' may be modified, but on return * the original contents will be restored. 'buflen' is the size of * the buffer pointed to by 'fn', in PRUnichars. * * Root directories come in three formats: * 1. / or \, meaning the root directory of the current drive. * 2. C:/ or C:\, where C is a drive letter. * 3. \\\\ or * \\\, meaning the root directory * of a UNC (Universal Naming Convention) name. */ static PRBool IsRootDirectoryW(PRUnichar *fn, size_t buflen) { PRUnichar *p; PRBool slashAdded = PR_FALSE; PRBool rv = PR_FALSE; if (_PR_IS_W_SLASH(fn[0]) && fn[1] == L'\0') { return PR_TRUE; } if (iswalpha(fn[0]) && fn[1] == L':' && _PR_IS_W_SLASH(fn[2]) && fn[3] == L'\0') { rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; return rv; } /* The UNC root directory */ if (_PR_IS_W_SLASH(fn[0]) && _PR_IS_W_SLASH(fn[1])) { /* The 'server' part should have at least one character. */ p = &fn[2]; if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { return PR_FALSE; } /* look for the next slash */ do { p++; } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); if (*p == L'\0') { return PR_FALSE; } /* The 'share' part should have at least one character. */ p++; if (*p == L'\0' || _PR_IS_W_SLASH(*p)) { return PR_FALSE; } /* look for the final slash */ do { p++; } while (*p != L'\0' && !_PR_IS_W_SLASH(*p)); if (_PR_IS_W_SLASH(*p) && p[1] != L'\0') { return PR_FALSE; } if (*p == L'\0') { /* * GetDriveType() doesn't work correctly if the * path is of the form \\server\share, so we add * a final slash temporarily. */ if ((p + 1) < (fn + buflen)) { *p++ = L'\\'; *p = L'\0'; slashAdded = PR_TRUE; } else { return PR_FALSE; /* name too long */ } } rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE; /* restore the 'fn' buffer */ if (slashAdded) { *--p = L'\0'; } } return rv; } PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar *fn, PRFileInfo64 *info) { HANDLE hFindFile; WIN32_FIND_DATAW findFileData; PRUnichar pathbuf[MAX_PATH + 1]; if (NULL == fn || L'\0' == *fn) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } /* * FindFirstFile() expands wildcard characters. So * we make sure the pathname contains no wildcard. */ if (NULL != wcspbrk(fn, L"?*")) { PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0); return -1; } hFindFile = findFirstFileW(fn, &findFileData); if (INVALID_HANDLE_VALUE == hFindFile) { DWORD len; PRUnichar *filePart; /* * FindFirstFile() does not work correctly on root directories. * It also doesn't work correctly on a pathname that ends in a * slash. So we first check to see if the pathname specifies a * root directory. If not, and if the pathname ends in a slash, * we remove the final slash and try again. */ /* * If the pathname does not contain ., \, and /, it cannot be * a root directory or a pathname that ends in a slash. */ if (NULL == wcspbrk(fn, L".\\/")) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } len = getFullPathNameW(fn, sizeof(pathbuf)/sizeof(pathbuf[0]), pathbuf, &filePart); if (0 == len) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } if (len > sizeof(pathbuf)/sizeof(pathbuf[0])) { PR_SetError(PR_NAME_TOO_LONG_ERROR, 0); return -1; } if (IsRootDirectoryW(pathbuf, sizeof(pathbuf)/sizeof(pathbuf[0]))) { info->type = PR_FILE_DIRECTORY; info->size = 0; /* * These timestamps don't make sense for root directories. */ info->modifyTime = 0; info->creationTime = 0; return 0; } if (!_PR_IS_W_SLASH(pathbuf[len - 1])) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } else { pathbuf[len - 1] = L'\0'; hFindFile = findFirstFileW(pathbuf, &findFileData); if (INVALID_HANDLE_VALUE == hFindFile) { _PR_MD_MAP_OPENDIR_ERROR(GetLastError()); return -1; } } } FindClose(hFindFile); if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { info->type = PR_FILE_DIRECTORY; } else { info->type = PR_FILE_FILE; } info->size = findFileData.nFileSizeHigh; info->size = (info->size << 32) + findFileData.nFileSizeLow; _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime); if (0 == findFileData.ftCreationTime.dwLowDateTime && 0 == findFileData.ftCreationTime.dwHighDateTime) { info->creationTime = info->modifyTime; } else { _PR_FileTimeToPRTime(&findFileData.ftCreationTime, &info->creationTime); } return 0; } /* ================ end of UTF16 Interfaces ================================ */ #endif /* MOZ_UNICODE */ nspr-4.11/nspr/pr/src/md/windows/w95sock.c0000644000000000000000000004355612623070344016521 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Win95 Sockets module * */ #include "primpl.h" #define READ_FD 1 #define WRITE_FD 2 #define CONNECT_FD 3 static PRInt32 socket_io_wait( PROsfd osfd, PRInt32 fd_type, PRIntervalTime timeout); /* --- SOCKET IO --------------------------------------------------------- */ static PRBool socketFixInet6RcvBuf = PR_FALSE; void _PR_MD_InitSockets(void) { OSVERSIONINFO osvi; memset(&osvi, 0, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { /* if Windows XP (32-bit) */ socketFixInet6RcvBuf = PR_TRUE; } } void _PR_MD_CleanupSockets(void) { socketFixInet6RcvBuf = PR_FALSE; } PROsfd _PR_MD_SOCKET(int af, int type, int flags) { SOCKET sock; u_long one = 1; sock = socket(af, type, flags); if (sock == INVALID_SOCKET ) { _PR_MD_MAP_SOCKET_ERROR(WSAGetLastError()); return (PROsfd)sock; } /* ** Make the socket Non-Blocking */ if (ioctlsocket( sock, FIONBIO, &one) != 0) { PR_SetError(PR_UNKNOWN_ERROR, WSAGetLastError()); closesocket(sock); return -1; } if (af == AF_INET6 && socketFixInet6RcvBuf) { int bufsize; int len = sizeof(bufsize); int rv; /* Windows XP 32-bit returns an error on getpeername() for AF_INET6 * sockets if the receive buffer size is greater than 65535 before * the connection is initiated. The default receive buffer size may * be 128000 so fix it here to always be <= 65535. See bug 513659 * and IBM DB2 support technote "Receive/Send IPv6 Socket Size * Problem in Windows XP SP2 & SP3". */ rv = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, &len); if (rv == 0 && bufsize > 65535) { bufsize = 65535; setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufsize, len); } } return (PROsfd)sock; } /* ** _MD_CloseSocket() -- Close a socket ** */ PRInt32 _MD_CloseSocket(PROsfd osfd) { PRInt32 rv; rv = closesocket((SOCKET) osfd ); if (rv < 0) _PR_MD_MAP_CLOSE_ERROR(WSAGetLastError()); return rv; } PRInt32 _MD_SocketAvailable(PRFileDesc *fd) { PRInt32 result; if (ioctlsocket(fd->secret->md.osfd, FIONREAD, &result) < 0) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, WSAGetLastError()); return -1; } return result; } PROsfd _MD_Accept( PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen, PRIntervalTime timeout ) { PROsfd osfd = fd->secret->md.osfd; SOCKET sock; PRInt32 rv, err; while ((sock = accept(osfd, (struct sockaddr *) raddr, rlen)) == -1) { err = WSAGetLastError(); if ((err == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) { break; } } else { _PR_MD_MAP_ACCEPT_ERROR(err); break; } } return(sock); } /* end _MD_accept() */ PRInt32 _PR_MD_CONNECT(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv; int err; if ((rv = connect(osfd, (struct sockaddr *) addr, addrlen)) == -1) { err = WSAGetLastError(); if ((!fd->secret->nonblocking) && (err == WSAEWOULDBLOCK)) { rv = socket_io_wait(osfd, CONNECT_FD, timeout); if ( rv < 0 ) { return(-1); } else { PR_ASSERT(rv > 0); /* it's connected */ return(0); } } _PR_MD_MAP_CONNECT_ERROR(err); } return rv; } PRInt32 _PR_MD_BIND(PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen) { PRInt32 rv; rv = bind(fd->secret->md.osfd, (const struct sockaddr *)&(addr->inet), addrlen); if (rv == SOCKET_ERROR) { _PR_MD_MAP_BIND_ERROR(WSAGetLastError()); return -1; } return 0; } PRInt32 _PR_MD_LISTEN(PRFileDesc *fd, PRIntn backlog) { PRInt32 rv; rv = listen(fd->secret->md.osfd, backlog); if (rv == SOCKET_ERROR) { _PR_MD_MAP_DEFAULT_ERROR(WSAGetLastError()); return -1; } return 0; } PRInt32 _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; int osflags; if (0 == flags) { osflags = 0; } else { PR_ASSERT(PR_MSG_PEEK == flags); osflags = MSG_PEEK; } while ((rv = recv( osfd, buf, amount, osflags)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { rv = socket_io_wait(osfd, READ_FD, timeout); if ( rv < 0 ) { return -1; } } else { _PR_MD_MAP_RECV_ERROR(err); break; } } /* end while() */ return(rv); } PRInt32 _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; PRInt32 bytesSent = 0; while(bytesSent < amount ) { while ((rv = send( osfd, buf, amount, 0 )) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { rv = socket_io_wait(osfd, WRITE_FD, timeout); if ( rv < 0 ) { return -1; } } else { _PR_MD_MAP_SEND_ERROR(err); return -1; } } bytesSent += rv; if (fd->secret->nonblocking) { break; } if (bytesSent < amount) { rv = socket_io_wait(osfd, WRITE_FD, timeout); if ( rv < 0 ) { return -1; } } } return bytesSent; } PRInt32 _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; PRInt32 bytesSent = 0; while(bytesSent < amount) { while ((rv = sendto( osfd, buf, amount, 0, (struct sockaddr *) addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { rv = socket_io_wait(osfd, WRITE_FD, timeout); if ( rv < 0 ) { return -1; } } else { _PR_MD_MAP_SENDTO_ERROR(err); return -1; } } bytesSent += rv; if (fd->secret->nonblocking) { break; } if (bytesSent < amount) { rv = socket_io_wait(osfd, WRITE_FD, timeout); if (rv < 0) { return -1; } } } return bytesSent; } PRInt32 _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout) { PROsfd osfd = fd->secret->md.osfd; PRInt32 rv, err; while ((rv = recvfrom( osfd, buf, amount, 0, (struct sockaddr *) addr, addrlen)) == -1) { if (((err = WSAGetLastError()) == WSAEWOULDBLOCK) && (!fd->secret->nonblocking)) { rv = socket_io_wait(osfd, READ_FD, timeout); if ( rv < 0) { return -1; } } else { _PR_MD_MAP_RECVFROM_ERROR(err); break; } } return(rv); } PRInt32 _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { int index; int sent = 0; int rv; for (index=0; index < iov_size; index++) { rv = _PR_MD_SEND(fd, iov[index].iov_base, iov[index].iov_len, 0, timeout); if (rv > 0) sent += rv; if ( rv != iov[index].iov_len ) { if (rv < 0) { if (fd->secret->nonblocking && (PR_GetError() == PR_WOULD_BLOCK_ERROR) && (sent > 0)) { return sent; } else { return -1; } } /* Only a nonblocking socket can have partial sends */ PR_ASSERT(fd->secret->nonblocking); return sent; } } return sent; } PRInt32 _PR_MD_SHUTDOWN(PRFileDesc *fd, PRIntn how) { PRInt32 rv; rv = shutdown(fd->secret->md.osfd, how); if (rv < 0) _PR_MD_MAP_SHUTDOWN_ERROR(WSAGetLastError()); return rv; } PRStatus _PR_MD_GETSOCKNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) { PRInt32 rv; rv = getsockname((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len); if (rv==0) { return PR_SUCCESS; } else { _PR_MD_MAP_GETSOCKNAME_ERROR(WSAGetLastError()); return PR_FAILURE; } } PRStatus _PR_MD_GETPEERNAME(PRFileDesc *fd, PRNetAddr *addr, PRUint32 *len) { PRInt32 rv; rv = getpeername((SOCKET)fd->secret->md.osfd, (struct sockaddr *)addr, len); if (rv==0) { return PR_SUCCESS; } else { _PR_MD_MAP_GETPEERNAME_ERROR(WSAGetLastError()); return PR_FAILURE; } } PRStatus _PR_MD_GETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, char* optval, PRInt32* optlen) { PRInt32 rv; rv = getsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen); if (rv==0) { return PR_SUCCESS; } else { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return PR_FAILURE; } } PRStatus _PR_MD_SETSOCKOPT(PRFileDesc *fd, PRInt32 level, PRInt32 optname, const char* optval, PRInt32 optlen) { PRInt32 rv; rv = setsockopt((SOCKET)fd->secret->md.osfd, level, optname, optval, optlen); if (rv==0) { return PR_SUCCESS; } else { _PR_MD_MAP_SETSOCKOPT_ERROR(WSAGetLastError()); return PR_FAILURE; } } void _MD_MakeNonblock(PRFileDesc *f) { return; /* do nothing */ } /* * socket_io_wait -- * * Wait for socket i/o, periodically checking for interrupt. * * This function returns 1 on success. On failure, it returns * -1 and sets the error codes. It never returns 0. */ #define _PR_INTERRUPT_CHECK_INTERVAL_SECS 5 static PRInt32 socket_io_wait( PROsfd osfd, PRInt32 fd_type, PRIntervalTime timeout) { PRInt32 rv = -1; struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime elapsed, remaining; PRBool wait_for_remaining; fd_set rd_wr, ex; int err, len; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; FD_ZERO(&rd_wr); FD_ZERO(&ex); do { FD_SET(osfd, &rd_wr); FD_SET(osfd, &ex); switch( fd_type ) { case READ_FD: rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv); break; case WRITE_FD: rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv); break; case CONNECT_FD: rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv); break; default: PR_ASSERT(0); break; } /* end switch() */ if (rv == -1 ) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } if ( rv > 0 && fd_type == CONNECT_FD ) { /* * Call Sleep(0) to work around a Winsock timing bug. */ Sleep(0); if (FD_ISSET((SOCKET)osfd, &ex)) { len = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == SOCKET_ERROR) { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return -1; } if (err != 0) _PR_MD_MAP_CONNECT_ERROR(err); else PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } if (FD_ISSET((SOCKET)osfd, &rd_wr)) { /* it's connected */ return 1; } PR_ASSERT(0); } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0); break; default: remaining = timeout; FD_ZERO(&rd_wr); FD_ZERO(&ex); do { /* * We block in _MD_SELECT for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { tv.tv_usec = PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); } FD_SET(osfd, &rd_wr); FD_SET(osfd, &ex); switch( fd_type ) { case READ_FD: rv = _MD_SELECT(0, &rd_wr, NULL, NULL, &tv); break; case WRITE_FD: rv = _MD_SELECT(0, NULL, &rd_wr, NULL, &tv); break; case CONNECT_FD: rv = _MD_SELECT(0, NULL, &rd_wr, &ex, &tv); break; default: PR_ASSERT(0); break; } /* end switch() */ if (rv == -1) { _PR_MD_MAP_SELECT_ERROR(WSAGetLastError()); break; } if ( rv > 0 && fd_type == CONNECT_FD ) { /* * Call Sleep(0) to work around a Winsock timing bug. */ Sleep(0); if (FD_ISSET((SOCKET)osfd, &ex)) { len = sizeof(err); if (getsockopt(osfd, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == SOCKET_ERROR) { _PR_MD_MAP_GETSOCKOPT_ERROR(WSAGetLastError()); return -1; } if (err != 0) _PR_MD_MAP_CONNECT_ERROR(err); else PR_SetError(PR_UNKNOWN_ERROR, 0); return -1; } if (FD_ISSET((SOCKET)osfd, &rd_wr)) { /* it's connected */ return 1; } PR_ASSERT(0); } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * We loop again if _MD_SELECT timed out and the * timeout deadline has not passed yet. */ if (rv == 0 ) { if (wait_for_remaining) { elapsed = remaining; } else { elapsed = PR_SecondsToInterval(tv.tv_sec) + PR_MicrosecondsToInterval(tv.tv_usec); } if (elapsed >= remaining) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = remaining - elapsed; } } } while (rv == 0 ); break; } return(rv); } /* end socket_io_wait() */ nspr-4.11/nspr/pr/src/md/windows/w95thred.c0000644000000000000000000001707312623070344016663 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* for _beginthreadex() */ #if defined(_MSC_VER) && _MSC_VER <= 1200 /* * VC++ 6.0 doesn't have DWORD_PTR. */ typedef DWORD DWORD_PTR; #endif /* _MSC_VER <= 1200 */ /* --- globals ------------------------------------------------ */ #ifdef _PR_USE_STATIC_TLS __declspec(thread) struct PRThread *_pr_thread_last_run; __declspec(thread) struct PRThread *_pr_currentThread; __declspec(thread) struct _PRCPU *_pr_currentCPU; #else DWORD _pr_currentThreadIndex; DWORD _pr_lastThreadIndex; DWORD _pr_currentCPUIndex; #endif int _pr_intsOff = 0; _PRInterruptTable _pr_interruptTable[] = { { 0 } }; void _PR_MD_EARLY_INIT() { #ifndef _PR_USE_STATIC_TLS _pr_currentThreadIndex = TlsAlloc(); _pr_lastThreadIndex = TlsAlloc(); _pr_currentCPUIndex = TlsAlloc(); #endif } void _PR_MD_CLEANUP_BEFORE_EXIT(void) { _PR_NT_FreeSids(); _PR_MD_CleanupSockets(); WSACleanup(); #ifndef _PR_USE_STATIC_TLS TlsFree(_pr_currentThreadIndex); TlsFree(_pr_lastThreadIndex); TlsFree(_pr_currentCPUIndex); #endif } PRStatus _PR_MD_INIT_THREAD(PRThread *thread) { if (thread->flags & (_PR_PRIMORDIAL | _PR_ATTACHED)) { /* ** Warning: ** -------- ** NSPR requires a real handle to every thread. ** GetCurrentThread() returns a pseudo-handle which ** is not suitable for some thread operations (e.g., ** suspending). Therefore, get a real handle from ** the pseudo handle via DuplicateHandle(...) */ DuplicateHandle( GetCurrentProcess(), /* Process of source handle */ GetCurrentThread(), /* Pseudo Handle to dup */ GetCurrentProcess(), /* Process of handle */ &(thread->md.handle), /* resulting handle */ 0L, /* access flags */ FALSE, /* Inheritable */ DUPLICATE_SAME_ACCESS); /* Options */ } /* Create the blocking IO semaphore */ thread->md.blocked_sema = CreateSemaphore(NULL, 0, 1, NULL); if (thread->md.blocked_sema == NULL) return PR_FAILURE; else return PR_SUCCESS; } static unsigned __stdcall pr_root(void *arg) { PRThread *thread = (PRThread *)arg; thread->md.start(thread); return 0; } PRStatus _PR_MD_CREATE_THREAD(PRThread *thread, void (*start)(void *), PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { thread->md.start = start; thread->md.handle = (HANDLE) _beginthreadex( NULL, thread->stack->stackSize, pr_root, (void *)thread, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, &(thread->id)); if(!thread->md.handle) { return PR_FAILURE; } thread->md.id = thread->id; /* * On windows, a thread is created with a thread priority of * THREAD_PRIORITY_NORMAL. */ if (priority != PR_PRIORITY_NORMAL) { _PR_MD_SET_PRIORITY(&(thread->md), priority); } /* Activate the thread */ if ( ResumeThread( thread->md.handle ) != -1) return PR_SUCCESS; return PR_FAILURE; } void _PR_MD_YIELD(void) { /* Can NT really yield at all? */ Sleep(0); } void _PR_MD_SET_PRIORITY(_MDThread *thread, PRThreadPriority newPri) { int nativePri; BOOL rv; if (newPri < PR_PRIORITY_FIRST) { newPri = PR_PRIORITY_FIRST; } else if (newPri > PR_PRIORITY_LAST) { newPri = PR_PRIORITY_LAST; } switch (newPri) { case PR_PRIORITY_LOW: nativePri = THREAD_PRIORITY_BELOW_NORMAL; break; case PR_PRIORITY_NORMAL: nativePri = THREAD_PRIORITY_NORMAL; break; case PR_PRIORITY_HIGH: nativePri = THREAD_PRIORITY_ABOVE_NORMAL; break; case PR_PRIORITY_URGENT: nativePri = THREAD_PRIORITY_HIGHEST; } rv = SetThreadPriority(thread->handle, nativePri); PR_ASSERT(rv); if (!rv) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_SetThreadPriority: can't set thread priority\n")); } return; } const DWORD MS_VC_EXCEPTION = 0x406D1388; #pragma pack(push,8) typedef struct tagTHREADNAME_INFO { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1=caller thread). DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) void _PR_MD_SET_CURRENT_THREAD_NAME(const char *name) { #ifdef _MSC_VER THREADNAME_INFO info; if (!IsDebuggerPresent()) return; info.dwType = 0x1000; info.szName = (char*) name; info.dwThreadID = -1; info.dwFlags = 0; __try { RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); } __except(EXCEPTION_CONTINUE_EXECUTION) { } #endif } void _PR_MD_CLEAN_THREAD(PRThread *thread) { BOOL rv; if (thread->md.blocked_sema) { rv = CloseHandle(thread->md.blocked_sema); PR_ASSERT(rv); thread->md.blocked_sema = 0; } if (thread->md.handle) { rv = CloseHandle(thread->md.handle); PR_ASSERT(rv); thread->md.handle = 0; } } void _PR_MD_EXIT_THREAD(PRThread *thread) { _PR_MD_CLEAN_THREAD(thread); _PR_MD_SET_CURRENT_THREAD(NULL); } void _PR_MD_EXIT(PRIntn status) { _exit(status); } PRInt32 _PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask ) { #ifdef WINCE SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return -1; #else DWORD_PTR rv; rv = SetThreadAffinityMask(thread->md.handle, mask); return rv?0:-1; #endif } PRInt32 _PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask) { #ifdef WINCE SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return -1; #else BOOL rv; DWORD_PTR process_mask; DWORD_PTR system_mask; rv = GetProcessAffinityMask(GetCurrentProcess(), &process_mask, &system_mask); if (rv) *mask = (PRUint32)process_mask; return rv?0:-1; #endif } void _PR_MD_SUSPEND_CPU(_PRCPU *cpu) { _PR_MD_SUSPEND_THREAD(cpu->thread); } void _PR_MD_RESUME_CPU(_PRCPU *cpu) { _PR_MD_RESUME_THREAD(cpu->thread); } void _PR_MD_SUSPEND_THREAD(PRThread *thread) { if (_PR_IS_NATIVE_THREAD(thread)) { DWORD previousSuspendCount; /* XXXMB - SuspendThread() is not a blocking call; how do we * know when the thread is *REALLY* suspended? */ previousSuspendCount = SuspendThread(thread->md.handle); PR_ASSERT(previousSuspendCount == 0); } } void _PR_MD_RESUME_THREAD(PRThread *thread) { if (_PR_IS_NATIVE_THREAD(thread)) { DWORD previousSuspendCount; previousSuspendCount = ResumeThread(thread->md.handle); PR_ASSERT(previousSuspendCount == 1); } } PRThread* _MD_CURRENT_THREAD(void) { PRThread *thread; thread = _MD_GET_ATTACHED_THREAD(); if (NULL == thread) { thread = _PRI_AttachThread( PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL, 0); } PR_ASSERT(thread != NULL); return thread; } nspr-4.11/nspr/pr/src/md/windows/win32_errors.c0000644000000000000000000003257612623070344017553 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prerror.h" #include "prlog.h" #include #include /* * On Win32, we map three kinds of error codes: * - GetLastError(): for Win32 functions * - WSAGetLastError(): for Winsock functions * - errno: for standard C library functions * * GetLastError() and WSAGetLastError() return error codes in * non-overlapping ranges, so their error codes (ERROR_* and * WSAE*) can be mapped by the same function. On the other hand, * errno and GetLastError() have overlapping ranges, so we need * to use a separate function to map errno. * * We do not check for WSAEINPROGRESS and WSAEINTR because we do not * use blocking Winsock 1.1 calls. * * Except for the 'socket' call, we do not check for WSAEINITIALISED. * It is assumed that if Winsock is not initialized, that fact will * be detected at the time we create new sockets. */ static void _MD_win32_map_default_errno(PRInt32 err) { PRErrorCode prError; switch (err) { case EACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case ENOENT: prError = PR_FILE_NOT_FOUND_ERROR; break; default: prError = PR_UNKNOWN_ERROR; break; } PR_SetError(prError, err); } void _MD_win32_map_default_error(PRInt32 err) { PRErrorCode prError; switch (err) { case ERROR_ACCESS_DENIED: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case ERROR_ALREADY_EXISTS: prError = PR_FILE_EXISTS_ERROR; break; case ERROR_CALL_NOT_IMPLEMENTED: prError = PR_NOT_IMPLEMENTED_ERROR; break; case ERROR_DISK_CORRUPT: prError = PR_IO_ERROR; break; case ERROR_DISK_FULL: prError = PR_NO_DEVICE_SPACE_ERROR; break; case ERROR_DISK_OPERATION_FAILED: prError = PR_IO_ERROR; break; case ERROR_DRIVE_LOCKED: prError = PR_FILE_IS_LOCKED_ERROR; break; case ERROR_FILENAME_EXCED_RANGE: prError = PR_NAME_TOO_LONG_ERROR; break; case ERROR_FILE_CORRUPT: prError = PR_IO_ERROR; break; case ERROR_FILE_EXISTS: prError = PR_FILE_EXISTS_ERROR; break; case ERROR_FILE_INVALID: prError = PR_BAD_DESCRIPTOR_ERROR; break; case ERROR_FILE_NOT_FOUND: prError = PR_FILE_NOT_FOUND_ERROR; break; case ERROR_HANDLE_DISK_FULL: prError = PR_NO_DEVICE_SPACE_ERROR; break; case ERROR_INVALID_ADDRESS: prError = PR_ACCESS_FAULT_ERROR; break; case ERROR_INVALID_HANDLE: prError = PR_BAD_DESCRIPTOR_ERROR; break; case ERROR_INVALID_NAME: prError = PR_INVALID_ARGUMENT_ERROR; break; case ERROR_INVALID_PARAMETER: prError = PR_INVALID_ARGUMENT_ERROR; break; case ERROR_INVALID_USER_BUFFER: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case ERROR_LOCKED: prError = PR_FILE_IS_LOCKED_ERROR; break; case ERROR_NETNAME_DELETED: prError = PR_CONNECT_RESET_ERROR; break; case ERROR_NOACCESS: prError = PR_ACCESS_FAULT_ERROR; break; case ERROR_NOT_ENOUGH_MEMORY: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case ERROR_NOT_ENOUGH_QUOTA: prError = PR_OUT_OF_MEMORY_ERROR; break; case ERROR_NOT_READY: prError = PR_IO_ERROR; break; case ERROR_NO_MORE_FILES: prError = PR_NO_MORE_FILES_ERROR; break; case ERROR_OPEN_FAILED: prError = PR_IO_ERROR; break; case ERROR_OPEN_FILES: prError = PR_IO_ERROR; break; case ERROR_OPERATION_ABORTED: prError = PR_OPERATION_ABORTED_ERROR; break; case ERROR_OUTOFMEMORY: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case ERROR_PATH_BUSY: prError = PR_IO_ERROR; break; case ERROR_PATH_NOT_FOUND: prError = PR_FILE_NOT_FOUND_ERROR; break; case ERROR_SEEK_ON_DEVICE: prError = PR_IO_ERROR; break; case ERROR_SHARING_VIOLATION: prError = PR_FILE_IS_BUSY_ERROR; break; case ERROR_STACK_OVERFLOW: prError = PR_ACCESS_FAULT_ERROR; break; case ERROR_TOO_MANY_OPEN_FILES: prError = PR_SYS_DESC_TABLE_FULL_ERROR; break; case ERROR_WRITE_PROTECT: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case WSAEACCES: prError = PR_NO_ACCESS_RIGHTS_ERROR; break; case WSAEADDRINUSE: prError = PR_ADDRESS_IN_USE_ERROR; break; case WSAEADDRNOTAVAIL: prError = PR_ADDRESS_NOT_AVAILABLE_ERROR; break; case WSAEAFNOSUPPORT: prError = PR_ADDRESS_NOT_SUPPORTED_ERROR; break; case WSAEALREADY: prError = PR_ALREADY_INITIATED_ERROR; break; case WSAEBADF: prError = PR_BAD_DESCRIPTOR_ERROR; break; case WSAECONNABORTED: prError = PR_CONNECT_ABORTED_ERROR; break; case WSAECONNREFUSED: prError = PR_CONNECT_REFUSED_ERROR; break; case WSAECONNRESET: prError = PR_CONNECT_RESET_ERROR; break; case WSAEDESTADDRREQ: prError = PR_INVALID_ARGUMENT_ERROR; break; case WSAEFAULT: prError = PR_ACCESS_FAULT_ERROR; break; case WSAEHOSTUNREACH: prError = PR_HOST_UNREACHABLE_ERROR; break; case WSAEINVAL: prError = PR_INVALID_ARGUMENT_ERROR; break; case WSAEISCONN: prError = PR_IS_CONNECTED_ERROR; break; case WSAEMFILE: prError = PR_PROC_DESC_TABLE_FULL_ERROR; break; case WSAEMSGSIZE: prError = PR_BUFFER_OVERFLOW_ERROR; break; case WSAENETDOWN: prError = PR_NETWORK_DOWN_ERROR; break; case WSAENETRESET: prError = PR_CONNECT_ABORTED_ERROR; break; case WSAENETUNREACH: prError = PR_NETWORK_UNREACHABLE_ERROR; break; case WSAENOBUFS: prError = PR_INSUFFICIENT_RESOURCES_ERROR; break; case WSAENOPROTOOPT: prError = PR_INVALID_ARGUMENT_ERROR; break; case WSAENOTCONN: prError = PR_NOT_CONNECTED_ERROR; break; case WSAENOTSOCK: prError = PR_NOT_SOCKET_ERROR; break; case WSAEOPNOTSUPP: prError = PR_OPERATION_NOT_SUPPORTED_ERROR; break; case WSAEPROTONOSUPPORT: prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR; break; case WSAEPROTOTYPE: prError = PR_INVALID_ARGUMENT_ERROR; break; case WSAESHUTDOWN: prError = PR_SOCKET_SHUTDOWN_ERROR; break; case WSAESOCKTNOSUPPORT: prError = PR_INVALID_ARGUMENT_ERROR; break; case WSAETIMEDOUT: prError = PR_CONNECT_ABORTED_ERROR; break; case WSAEWOULDBLOCK: prError = PR_WOULD_BLOCK_ERROR; break; default: prError = PR_UNKNOWN_ERROR; break; } PR_SetError(prError, err); } void _MD_win32_map_opendir_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_closedir_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_unix_readdir_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_delete_error(PRInt32 err) { _MD_win32_map_default_error(err); } /* The error code for stat() is in errno. */ void _MD_win32_map_stat_error(PRInt32 err) { _MD_win32_map_default_errno(err); } void _MD_win32_map_fstat_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_rename_error(PRInt32 err) { _MD_win32_map_default_error(err); } /* The error code for access() is in errno. */ void _MD_win32_map_access_error(PRInt32 err) { _MD_win32_map_default_errno(err); } void _MD_win32_map_mkdir_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_rmdir_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_read_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_transmitfile_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_write_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_lseek_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_fsync_error(PRInt32 err) { _MD_win32_map_default_error(err); } /* * For both CloseHandle() and closesocket(). */ void _MD_win32_map_close_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_socket_error(PRInt32 err) { PR_ASSERT(err != WSANOTINITIALISED); _MD_win32_map_default_error(err); } void _MD_win32_map_recv_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_recvfrom_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_send_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_sendto_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEMSGSIZE: prError = PR_INVALID_ARGUMENT_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_accept_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break; case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_acceptex_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_connect_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEWOULDBLOCK: prError = PR_IN_PROGRESS_ERROR; break; case WSAEINVAL: prError = PR_ALREADY_INITIATED_ERROR; break; case WSAETIMEDOUT: prError = PR_IO_TIMEOUT_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_bind_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEINVAL: prError = PR_SOCKET_ADDRESS_IS_BOUND_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_listen_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEOPNOTSUPP: prError = PR_NOT_TCP_SOCKET_ERROR; break; case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_shutdown_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_getsockname_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAEINVAL: prError = PR_INVALID_STATE_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_getpeername_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_getsockopt_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_setsockopt_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_open_error(PRInt32 err) { _MD_win32_map_default_error(err); } void _MD_win32_map_gethostname_error(PRInt32 err) { _MD_win32_map_default_error(err); } /* Win32 select() only works on sockets. So in this ** context, WSAENOTSOCK is equivalent to EBADF on Unix. */ void _MD_win32_map_select_error(PRInt32 err) { PRErrorCode prError; switch (err) { case WSAENOTSOCK: prError = PR_BAD_DESCRIPTOR_ERROR; break; default: _MD_win32_map_default_error(err); return; } PR_SetError(prError, err); } void _MD_win32_map_lockf_error(PRInt32 err) { _MD_win32_map_default_error(err); } nspr-4.11/nspr/pr/src/memory/.cvsignore0000644000000000000000000000001112623070344016242 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/memory/Makefile.in0000644000000000000000000000114212623070344016315 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = prseg.c prshm.c prshma.c TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/memory/prseg.c0000644000000000000000000000267512623070344015550 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #if defined(_PR_PTHREADS) /* ** The pthreads version doesn't use these functions. */ void _PR_InitSegs(void) { } #else /* _PR_PTHREADS */ void _PR_InitSegs(void) { _PR_MD_INIT_SEGS(); } /* ** Allocate a memory segment. The size value is rounded up to the native ** system page size and a page aligned portion of memory is returned. ** This memory is not part of the malloc heap. If "vaddr" is not NULL ** then PR tries to allocate the segment at the desired virtual address. */ PRSegment* _PR_NewSegment(PRUint32 size, void *vaddr) { PRSegment *seg; /* calloc the data structure for the segment */ seg = PR_NEWZAP(PRSegment); if (seg) { size = ((size + _pr_pageSize - 1) >> _pr_pageShift) << _pr_pageShift; /* ** Now, allocate the actual segment memory (or map under some OS) ** The OS specific code decides from where or how to allocate memory. */ if (_PR_MD_ALLOC_SEGMENT(seg, size, vaddr) != PR_SUCCESS) { PR_DELETE(seg); return NULL; } } return seg; } /* ** Free a memory segment. */ void _PR_DestroySegment(PRSegment *seg) { _PR_MD_FREE_SEGMENT(seg); PR_DELETE(seg); } #endif /* _PR_PTHREADS */ nspr-4.11/nspr/pr/src/memory/prshm.c0000644000000000000000000000560212623070344015552 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prshm.c -- NSPR Named Shared Memory ** ** lth. Jul-1999. */ #include #include "primpl.h" extern PRLogModuleInfo *_pr_shm_lm; #if defined PR_HAVE_SYSV_NAMED_SHARED_MEMORY /* SysV implementation is in pr/src/md/unix/uxshm.c */ #elif defined PR_HAVE_POSIX_NAMED_SHARED_MEMORY /* Posix implementation is in pr/src/md/unix/uxshm.c */ #elif defined PR_HAVE_WIN32_NAMED_SHARED_MEMORY /* Win32 implementation is in pr/src/md/windows/w32shm.c */ #else /* ** there is no named_shared_memory */ extern PRSharedMemory* _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } extern PRStatus _MD_DeleteSharedMemory( const char *name ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } #endif /* HAVE_SYSV_NAMED_SHARED_MEMORY */ /* ** FUNCTION: PR_OpenSharedMemory() ** */ PR_IMPLEMENT( PRSharedMemory * ) PR_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ) { if (!_pr_initialized) _PR_ImplicitInitialization(); return( _PR_MD_OPEN_SHARED_MEMORY( name, size, flags, mode )); } /* end PR_OpenSharedMemory() */ /* ** FUNCTION: PR_AttachSharedMemory() ** */ PR_IMPLEMENT( void * ) PR_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ) { return( _PR_MD_ATTACH_SHARED_MEMORY( shm, flags )); } /* end PR_AttachSharedMemory() */ /* ** FUNCTION: PR_DetachSharedMemory() ** */ PR_IMPLEMENT( PRStatus ) PR_DetachSharedMemory( PRSharedMemory *shm, void *addr ) { return( _PR_MD_DETACH_SHARED_MEMORY( shm, addr )); } /* end PR_DetachSharedMemory() */ /* ** FUNCTION: PR_CloseSharedMemory() ** */ PR_IMPLEMENT( PRStatus ) PR_CloseSharedMemory( PRSharedMemory *shm ) { return( _PR_MD_CLOSE_SHARED_MEMORY( shm )); } /* end PR_CloseSharedMemory() */ /* ** FUNCTION: PR_DeleteSharedMemory() ** */ PR_EXTERN( PRStatus ) PR_DeleteSharedMemory( const char *name ) { if (!_pr_initialized) _PR_ImplicitInitialization(); return(_PR_MD_DELETE_SHARED_MEMORY( name )); } /* end PR_DestroySharedMemory() */ /* end prshm.c */ nspr-4.11/nspr/pr/src/memory/prshma.c0000644000000000000000000000517412623070344015717 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prshma.h -- NSPR Anonymous Shared Memory ** ** */ #include "primpl.h" extern PRLogModuleInfo *_pr_shma_lm; #if defined(XP_UNIX) /* defined in pr/src/md/unix/uxshm.c */ #elif defined(WIN32) /* defined in pr/src/md/windows/w32shm.c */ #else extern PRFileMap * _PR_MD_OPEN_ANON_FILE_MAP( const char *dirName, PRSize size, PRFileMapProtect prot ) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } extern PRStatus _PR_MD_EXPORT_FILE_MAP_AS_STRING(PRFileMap *fm, PRSize bufSize, char *buf) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } extern PRFileMap * _PR_MD_IMPORT_FILE_MAP_FROM_STRING(const char *fmstring) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } #endif /* ** PR_OpenAnonFileMap() -- Creates an anonymous file-mapped shared memory ** */ PR_IMPLEMENT(PRFileMap*) PR_OpenAnonFileMap( const char *dirName, PRSize size, PRFileMapProtect prot ) { return(_PR_MD_OPEN_ANON_FILE_MAP( dirName, size, prot )); } /* end PR_OpenAnonFileMap() */ /* ** PR_ProcessAttrSetInheritableFileMap() -- Prepare FileMap for export ** to my children processes via PR_CreateProcess() ** ** */ PR_IMPLEMENT( PRStatus) PR_ProcessAttrSetInheritableFileMap( PRProcessAttr *attr, PRFileMap *fm, const char *shmname ) { PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return( PR_FAILURE); } /* end PR_ProcessAttrSetInheritableFileMap() */ /* ** PR_GetInheritedFileMap() -- Import a PRFileMap previously exported ** by my parent process via PR_CreateProcess() ** */ PR_IMPLEMENT( PRFileMap *) PR_GetInheritedFileMap( const char *shmname ) { PRFileMap *fm = NULL; PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); return( fm ); } /* end PR_GetInhteritedFileMap() */ /* ** PR_ExportFileMapAsString() -- Creates a string identifying a PRFileMap ** */ PR_IMPLEMENT( PRStatus ) PR_ExportFileMapAsString( PRFileMap *fm, PRSize bufSize, char *buf ) { return( _PR_MD_EXPORT_FILE_MAP_AS_STRING( fm, bufSize, buf )); } /* end PR_ExportFileMapAsString() */ /* ** PR_ImportFileMapFromString() -- Creates a PRFileMap from the identifying string ** ** */ PR_IMPLEMENT( PRFileMap * ) PR_ImportFileMapFromString( const char *fmstring ) { return( _PR_MD_IMPORT_FILE_MAP_FROM_STRING(fmstring)); } /* end PR_ImportFileMapFromString() */ /* end prshma.c */ nspr-4.11/nspr/pr/src/misc/.cvsignore0000644000000000000000000000001112623070344015665 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/misc/Makefile.in0000644000000000000000000000320112623070344015736 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = \ pralarm.c \ pratom.c \ prcountr.c \ prdtoa.c \ prenv.c \ prerr.c \ prerror.c \ prerrortable.c \ prinit.c \ prinrval.c \ pripc.c \ prlog2.c \ prlong.c \ prnetdb.c \ praton.c \ prolock.c \ prrng.c \ prsystem.c \ prtime.c \ prthinfo.c \ prtpool.c \ prtrace.c \ $(NULL) ifndef USE_PTHREADS CSRCS += \ pripcsem.c \ $(NULL) endif TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties include $(topsrcdir)/config/rules.mk # Prevent floating point errors caused by MSVC 6.0 Processor Pack # optimizations (bug 207421). This disables optimizations that # could change the precision of floating-point calculations for # this single compilation unit. ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) $(OBJDIR)/prdtoa.$(OBJ_SUFFIX): prdtoa.c @$(MAKE_OBJDIR) ifeq (,$(filter-out 1100 1200 1300 1310,$(MSC_VER))) $(CC) -Fo$@ -c $(CFLAGS) -Op $(call pr_abspath,$<) else $(CC) -Fo$@ -c $(CFLAGS) -fp:precise $(call pr_abspath,$<) endif endif # # Generate prerr.h, prerr.c, and prerr.properties from prerr.et. # build_prerr: cd $(srcdir); $(PERL) compile-et.pl prerr.et export:: $(TARGETS) nspr-4.11/nspr/pr/src/misc/compile-et.pl0000644000000000000000000000516712623070344016301 0ustar 00000000000000#!/usr/bin/perl # usage: compile-et input.et # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. sub header { local($filename, $comment) = @_; < 0x7fffff); $base*256; } sub code { local($macro, $text) = @_; $code = $table_base + $table_item_count; print H "\n"; print H "/* ", $text, " */\n"; printf H "#define %-40s (%dL)\n", $macro, $code; print C "\t{\"", $macro, "\", \"", $text, "\"},\n"; print PROPERTIES $macro, "=", $text, "\n"; $table_item_count++; } $filename = $ARGV[0]; open(INPUT, "< $filename") || die "Can't read $filename: $!\n"; $base = "$filename"; $base =~ s/\.et$//; $base =~ s#.*/##; open(H, "> ${base}.h") || die "Can't write ${base}.h\n"; open(C, "> ${base}.c") || die "Can't write ${base}.c\n"; open(PROPERTIES, "> ${base}.properties") || die "Can't write ${base}.properties\n"; print H "/*\n", &header("${base}.h", " *"), " */\n"; print C "/*\n", &header("${base}.c", " *"), " */\n"; print PROPERTIES &header("${base}.properties", "#"); $skipone = 0; while ($_ = ) { next if /^#/; if (/^[ \t]*(error_table|et)[ \t]+([a-zA-Z][a-zA-Z0-9_]+) *(-?[0-9]*)/) { $table_name = $2; if ($3) { $table_base = $3; } else { $table_base = &table_base($table_name); } $table_item_count = 0; print C "#include \"prerror.h\"\n"; print C "static const struct PRErrorMessage text[] = {\n"; } elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*$/) { $skipone = 1; $macro = $2; } elsif (/^[ \t]*(error_code|ec)[ \t]+([A-Z_0-9]+),[ \t]*"(.*)"[ \t]*$/) { &code($2, $3); } elsif ($skipone && /^[ \t]*"(.*)"[ \t]*$/) { &code($macro, $1); } } print H "\n"; print H "extern void ", $table_name, "_InitializePRErrorTable","(void);\n"; printf H "#define ERROR_TABLE_BASE_%s (%dL)\n", $table_name, $table_base; print C "\t{0, 0}\n"; print C "};\n\n"; printf C "static const struct PRErrorTable et = { text, \"%s\", %dL, %d };\n", $base, $table_base, $table_item_count; print C "\n"; print C "void ", $table_name, "_InitializePRErrorTable", "(void) {\n"; print C " PR_ErrorInstallTable(&et);\n"; print C "}\n"; 0; nspr-4.11/nspr/pr/src/misc/dtoa.c0000644000000000000000000025456612623070344015012 0ustar 00000000000000/**************************************************************** * * The author of this software is David M. Gay. * * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. * * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. * ***************************************************************/ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ /* On a machine with IEEE extended-precision registers, it is * necessary to specify double-precision (53-bit) rounding precision * before invoking strtod or dtoa. If the machine uses (the equivalent * of) Intel 80x87 arithmetic, the call * _control87(PC_53, MCW_PC); * does this with many compilers. Whether this or another call is * appropriate depends on the compiler; for this to work, it may be * necessary to #include "float.h" or another system-dependent header * file. */ /* strtod for IEEE-, VAX-, and IBM-arithmetic machines. * * This strtod returns a nearest machine number to the input decimal * string (or sets errno to ERANGE). With IEEE arithmetic, ties are * broken by the IEEE round-even rule. Otherwise ties are broken by * biased rounding (add half and chop). * * Inspired loosely by William D. Clinger's paper "How to Read Floating * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. * * Modifications: * * 1. We only require IEEE, IBM, or VAX double-precision * arithmetic (not IEEE double-extended). * 2. We get by with floating-point arithmetic in a case that * Clinger missed -- when we're computing d * 10^n * for a small integer d and the integer n is not too * much larger than 22 (the maximum integer k for which * we can represent 10^k exactly), we may be able to * compute (d*10^k) * 10^(e-k) with just one roundoff. * 3. Rather than a bit-at-a-time adjustment of the binary * result in the hard case, we use floating-point * arithmetic to determine the adjustment to within * one bit; only in really hard cases do we need to * compute a second residual. * 4. Because of 3., we don't need a large table of powers of 10 * for ten-to-e (just some small tables, e.g. of 10^k * for 0 <= k <= 22). */ /* * #define IEEE_8087 for IEEE-arithmetic machines where the least * significant byte has the lowest address. * #define IEEE_MC68k for IEEE-arithmetic machines where the most * significant byte has the lowest address. * #define Long int on machines with 32-bit ints and 64-bit longs. * #define IBM for IBM mainframe-style floating-point arithmetic. * #define VAX for VAX-style floating-point arithmetic (D_floating). * #define No_leftright to omit left-right logic in fast floating-point * computation of dtoa. This will cause dtoa modes 4 and 5 to be * treated the same as modes 2 and 3 for some inputs. * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 * and strtod and dtoa should round accordingly. Unless Trust_FLT_ROUNDS * is also #defined, fegetround() will be queried for the rounding mode. * Note that both FLT_ROUNDS and fegetround() are specified by the C99 * standard (and are specified to be consistent, with fesetround() * affecting the value of FLT_ROUNDS), but that some (Linux) systems * do not work correctly in this regard, so using fegetround() is more * portable than using FLT_ROUNDS directly. * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 * and Honor_FLT_ROUNDS is not #defined. * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines * that use extended-precision instructions to compute rounded * products and quotients) with IBM. * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic * that rounds toward +Infinity. * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased * rounding when the underlying floating-point arithmetic uses * unbiased rounding. This prevent using ordinary floating-point * arithmetic when the result could be computed with one rounding error. * #define Inaccurate_Divide for IEEE-format with correctly rounded * products but inaccurate quotients, e.g., for Intel i860. * #define NO_LONG_LONG on machines that do not have a "long long" * integer type (of >= 64 bits). On such machines, you can * #define Just_16 to store 16 bits per 32-bit Long when doing * high-precision integer arithmetic. Whether this speeds things * up or slows things down depends on the machine and the number * being converted. If long long is available and the name is * something other than "long long", #define Llong to be the name, * and if "unsigned Llong" does not work as an unsigned version of * Llong, #define #ULLong to be the corresponding unsigned type. * #define KR_headers for old-style C function headers. * #define Bad_float_h if your system lacks a float.h or if it does not * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) * if memory is available and otherwise does something you deem * appropriate. If MALLOC is undefined, malloc will be invoked * directly -- and assumed always to succeed. Similarly, if you * want something other than the system's free() to be called to * recycle memory acquired from MALLOC, #define FREE to be the * name of the alternate routine. (FREE or free is only called in * pathological cases, e.g., in a dtoa call after a dtoa return in * mode 3 with thousands of digits requested.) * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making * memory allocations from a private pool of memory when possible. * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, * unless #defined to be a different length. This default length * suffices to get rid of MALLOC calls except for unusual cases, * such as decimal-to-binary conversion of a very long string of * digits. The longest string dtoa can return is about 751 bytes * long. For conversions by strtod of strings of 800 digits and * all dtoa conversions in single-threaded executions with 8-byte * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte * pointers, PRIVATE_MEM >= 7112 appears adequate. * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK * #defined automatically on IEEE systems. On such systems, * when INFNAN_CHECK is #defined, strtod checks * for Infinity and NaN (case insensitively). On some systems * (e.g., some HP systems), it may be necessary to #define NAN_WORD0 * appropriately -- to the most significant word of a quiet NaN. * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, * strtod also accepts (case insensitively) strings of the form * NaN(x), where x is a string of hexadecimal digits and spaces; * if there is only one string of hexadecimal digits, it is taken * for the 52 fraction bits of the resulting NaN; if there are two * or more strings of hex digits, the first is for the high 20 bits, * the second and subsequent for the low 32 bits, with intervening * white space ignored; but if this results in none of the 52 * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 * and NAN_WORD1 are used instead. * #define MULTIPLE_THREADS if the system offers preemptively scheduled * multiple threads. In this case, you must provide (or suitably * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed * in pow5mult, ensures lazy evaluation of only one copy of high * powers of 5; omitting this lock would introduce a small * probability of wasting memory, but would otherwise be harmless.) * You must also invoke freedtoa(s) to free the value s returned by * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that * avoids underflows on inputs whose result does not underflow. * If you #define NO_IEEE_Scale on a machine that uses IEEE-format * floating-point numbers and flushes underflows to zero rather * than implementing gradual underflow, then you must also #define * Sudden_Underflow. * #define USE_LOCALE to use the current locale's decimal_point value. * #define SET_INEXACT if IEEE arithmetic is being used and extra * computation should be done to set the inexact flag when the * result is inexact and avoid setting inexact when the result * is exact. In this case, dtoa.c must be compiled in * an environment, perhaps provided by #include "dtoa.c" in a * suitable wrapper, that defines two functions, * int get_inexact(void); * void clear_inexact(void); * such that get_inexact() returns a nonzero value if the * inexact bit is already set, and clear_inexact() sets the * inexact bit to 0. When SET_INEXACT is #defined, strtod * also does extra computations to set the underflow and overflow * flags when appropriate (i.e., when the result is tiny and * inexact or when it is a numeric value rounded to +-infinity). * #define NO_ERRNO if strtod should not assign errno = ERANGE when * the result overflows to +-Infinity or underflows to 0. * #define NO_HEX_FP to omit recognition of hexadecimal floating-point * values by strtod. * #define NO_STRTOD_BIGCOMP (on IEEE-arithmetic systems only for now) * to disable logic for "fast" testing of very long input strings * to strtod. This testing proceeds by initially truncating the * input string, then if necessary comparing the whole string with * a decimal expansion to decide close cases. This logic is only * used for input more than STRTOD_DIGLIM digits long (default 40). */ #ifndef Long #define Long long #endif #ifndef ULong typedef unsigned Long ULong; #endif #ifdef DEBUG #include "stdio.h" #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} #endif #include "stdlib.h" #include "string.h" #ifdef USE_LOCALE #include "locale.h" #endif #ifdef Honor_FLT_ROUNDS #ifndef Trust_FLT_ROUNDS #include #endif #endif #ifdef MALLOC #ifdef KR_headers extern char *MALLOC(); #else extern void *MALLOC(size_t); #endif #else #define MALLOC malloc #endif #ifndef Omit_Private_Memory #ifndef PRIVATE_MEM #define PRIVATE_MEM 2304 #endif #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) static double private_mem[PRIVATE_mem], *pmem_next = private_mem; #endif #undef IEEE_Arith #undef Avoid_Underflow #ifdef IEEE_MC68k #define IEEE_Arith #endif #ifdef IEEE_8087 #define IEEE_Arith #endif #ifdef IEEE_Arith #ifndef NO_INFNAN_CHECK #undef INFNAN_CHECK #define INFNAN_CHECK #endif #else #undef INFNAN_CHECK #define NO_STRTOD_BIGCOMP #endif #include "errno.h" #ifdef Bad_float_h #ifdef IEEE_Arith #define DBL_DIG 15 #define DBL_MAX_10_EXP 308 #define DBL_MAX_EXP 1024 #define FLT_RADIX 2 #endif /*IEEE_Arith*/ #ifdef IBM #define DBL_DIG 16 #define DBL_MAX_10_EXP 75 #define DBL_MAX_EXP 63 #define FLT_RADIX 16 #define DBL_MAX 7.2370055773322621e+75 #endif #ifdef VAX #define DBL_DIG 16 #define DBL_MAX_10_EXP 38 #define DBL_MAX_EXP 127 #define FLT_RADIX 2 #define DBL_MAX 1.7014118346046923e+38 #endif #ifndef LONG_MAX #define LONG_MAX 2147483647 #endif #else /* ifndef Bad_float_h */ #include "float.h" #endif /* Bad_float_h */ #ifndef __MATH_H__ #include "math.h" #endif #ifdef __cplusplus extern "C" { #endif #ifndef CONST #ifdef KR_headers #define CONST /* blank */ #else #define CONST const #endif #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. #endif typedef union { double d; ULong L[2]; } U; #ifdef IEEE_8087 #define word0(x) (x)->L[1] #define word1(x) (x)->L[0] #else #define word0(x) (x)->L[0] #define word1(x) (x)->L[1] #endif #define dval(x) (x)->d #ifndef STRTOD_DIGLIM #define STRTOD_DIGLIM 40 #endif #ifdef DIGLIM_DEBUG extern int strtod_diglim; #else #define strtod_diglim STRTOD_DIGLIM #endif /* The following definition of Storeinc is appropriate for MIPS processors. * An alternative that might be better on some machines is * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) */ #if defined(IEEE_8087) + defined(VAX) #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ ((unsigned short *)a)[0] = (unsigned short)c, a++) #else #define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ ((unsigned short *)a)[1] = (unsigned short)c, a++) #endif /* #define P DBL_MANT_DIG */ /* Ten_pmax = floor(P*log(2)/log(5)) */ /* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ /* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ /* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ #ifdef IEEE_Arith #define Exp_shift 20 #define Exp_shift1 20 #define Exp_msk1 0x100000 #define Exp_msk11 0x100000 #define Exp_mask 0x7ff00000 #define P 53 #define Nbits 53 #define Bias 1023 #define Emax 1023 #define Emin (-1022) #define Exp_1 0x3ff00000 #define Exp_11 0x3ff00000 #define Ebits 11 #define Frac_mask 0xfffff #define Frac_mask1 0xfffff #define Ten_pmax 22 #define Bletch 0x10 #define Bndry_mask 0xfffff #define Bndry_mask1 0xfffff #define LSB 1 #define Sign_bit 0x80000000 #define Log2P 1 #define Tiny0 0 #define Tiny1 1 #define Quick_max 14 #define Int_max 14 #ifndef NO_IEEE_Scale #define Avoid_Underflow #ifdef Flush_Denorm /* debugging option */ #undef Sudden_Underflow #endif #endif #ifndef Flt_Rounds #ifdef FLT_ROUNDS #define Flt_Rounds FLT_ROUNDS #else #define Flt_Rounds 1 #endif #endif /*Flt_Rounds*/ #ifdef Honor_FLT_ROUNDS #undef Check_FLT_ROUNDS #define Check_FLT_ROUNDS #else #define Rounding Flt_Rounds #endif #else /* ifndef IEEE_Arith */ #undef Check_FLT_ROUNDS #undef Honor_FLT_ROUNDS #undef SET_INEXACT #undef Sudden_Underflow #define Sudden_Underflow #ifdef IBM #undef Flt_Rounds #define Flt_Rounds 0 #define Exp_shift 24 #define Exp_shift1 24 #define Exp_msk1 0x1000000 #define Exp_msk11 0x1000000 #define Exp_mask 0x7f000000 #define P 14 #define Nbits 56 #define Bias 65 #define Emax 248 #define Emin (-260) #define Exp_1 0x41000000 #define Exp_11 0x41000000 #define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ #define Frac_mask 0xffffff #define Frac_mask1 0xffffff #define Bletch 4 #define Ten_pmax 22 #define Bndry_mask 0xefffff #define Bndry_mask1 0xffffff #define LSB 1 #define Sign_bit 0x80000000 #define Log2P 4 #define Tiny0 0x100000 #define Tiny1 0 #define Quick_max 14 #define Int_max 15 #else /* VAX */ #undef Flt_Rounds #define Flt_Rounds 1 #define Exp_shift 23 #define Exp_shift1 7 #define Exp_msk1 0x80 #define Exp_msk11 0x800000 #define Exp_mask 0x7f80 #define P 56 #define Nbits 56 #define Bias 129 #define Emax 126 #define Emin (-129) #define Exp_1 0x40800000 #define Exp_11 0x4080 #define Ebits 8 #define Frac_mask 0x7fffff #define Frac_mask1 0xffff007f #define Ten_pmax 24 #define Bletch 2 #define Bndry_mask 0xffff007f #define Bndry_mask1 0xffff007f #define LSB 0x10000 #define Sign_bit 0x8000 #define Log2P 1 #define Tiny0 0x80 #define Tiny1 0 #define Quick_max 15 #define Int_max 15 #endif /* IBM, VAX */ #endif /* IEEE_Arith */ #ifndef IEEE_Arith #define ROUND_BIASED #else #ifdef ROUND_BIASED_without_Round_Up #undef ROUND_BIASED #define ROUND_BIASED #endif #endif #ifdef RND_PRODQUOT #define rounded_product(a,b) a = rnd_prod(a, b) #define rounded_quotient(a,b) a = rnd_quot(a, b) #ifdef KR_headers extern double rnd_prod(), rnd_quot(); #else extern double rnd_prod(double, double), rnd_quot(double, double); #endif #else #define rounded_product(a,b) a *= b #define rounded_quotient(a,b) a /= b #endif #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) #define Big1 0xffffffff #ifndef Pack_32 #define Pack_32 #endif typedef struct BCinfo BCinfo; struct BCinfo { int dp0, dp1, dplen, dsign, e0, inexact, nd, nd0, rounding, scale, uflchk; }; #ifdef KR_headers #define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff) #else #define FFFFFFFF 0xffffffffUL #endif #ifdef NO_LONG_LONG #undef ULLong #ifdef Just_16 #undef Pack_32 /* When Pack_32 is not defined, we store 16 bits per 32-bit Long. * This makes some inner loops simpler and sometimes saves work * during multiplications, but it often seems to make things slightly * slower. Hence the default is now to store 32 bits per Long. */ #endif #else /* long long available */ #ifndef Llong #define Llong long long #endif #ifndef ULLong #define ULLong unsigned Llong #endif #endif /* NO_LONG_LONG */ #ifndef MULTIPLE_THREADS #define ACQUIRE_DTOA_LOCK(n) /*nothing*/ #define FREE_DTOA_LOCK(n) /*nothing*/ #endif #define Kmax 7 #ifdef __cplusplus extern "C" double strtod(const char *s00, char **se); extern "C" char *dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve); #endif struct Bigint { struct Bigint *next; int k, maxwds, sign, wds; ULong x[1]; }; typedef struct Bigint Bigint; static Bigint *freelist[Kmax+1]; static Bigint * Balloc #ifdef KR_headers (k) int k; #else (int k) #endif { int x; Bigint *rv; #ifndef Omit_Private_Memory unsigned int len; #endif ACQUIRE_DTOA_LOCK(0); /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ /* but this case seems very unlikely. */ if (k <= Kmax && (rv = freelist[k])) freelist[k] = rv->next; else { x = 1 << k; #ifdef Omit_Private_Memory rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); #else len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) /sizeof(double); if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { rv = (Bigint*)pmem_next; pmem_next += len; } else rv = (Bigint*)MALLOC(len*sizeof(double)); #endif rv->k = k; rv->maxwds = x; } FREE_DTOA_LOCK(0); rv->sign = rv->wds = 0; return rv; } static void Bfree #ifdef KR_headers (v) Bigint *v; #else (Bigint *v) #endif { if (v) { if (v->k > Kmax) #ifdef FREE FREE((void*)v); #else free((void*)v); #endif else { ACQUIRE_DTOA_LOCK(0); v->next = freelist[v->k]; freelist[v->k] = v; FREE_DTOA_LOCK(0); } } } #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ y->wds*sizeof(Long) + 2*sizeof(int)) static Bigint * multadd #ifdef KR_headers (b, m, a) Bigint *b; int m, a; #else (Bigint *b, int m, int a) /* multiply by m and add a */ #endif { int i, wds; #ifdef ULLong ULong *x; ULLong carry, y; #else ULong carry, *x, y; #ifdef Pack_32 ULong xi, z; #endif #endif Bigint *b1; wds = b->wds; x = b->x; i = 0; carry = a; do { #ifdef ULLong y = *x * (ULLong)m + carry; carry = y >> 32; *x++ = y & FFFFFFFF; #else #ifdef Pack_32 xi = *x; y = (xi & 0xffff) * m + carry; z = (xi >> 16) * m + (y >> 16); carry = z >> 16; *x++ = (z << 16) + (y & 0xffff); #else y = *x * m + carry; carry = y >> 16; *x++ = y & 0xffff; #endif #endif } while(++i < wds); if (carry) { if (wds >= b->maxwds) { b1 = Balloc(b->k+1); Bcopy(b1, b); Bfree(b); b = b1; } b->x[wds++] = carry; b->wds = wds; } return b; } static Bigint * s2b #ifdef KR_headers (s, nd0, nd, y9, dplen) CONST char *s; int nd0, nd, dplen; ULong y9; #else (const char *s, int nd0, int nd, ULong y9, int dplen) #endif { Bigint *b; int i, k; Long x, y; x = (nd + 8) / 9; for(k = 0, y = 1; x > y; y <<= 1, k++) ; #ifdef Pack_32 b = Balloc(k); b->x[0] = y9; b->wds = 1; #else b = Balloc(k+1); b->x[0] = y9 & 0xffff; b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; #endif i = 9; if (9 < nd0) { s += 9; do b = multadd(b, 10, *s++ - '0'); while(++i < nd0); s += dplen; } else s += dplen + 9; for(; i < nd; i++) b = multadd(b, 10, *s++ - '0'); return b; } static int hi0bits #ifdef KR_headers (x) ULong x; #else (ULong x) #endif { int k = 0; if (!(x & 0xffff0000)) { k = 16; x <<= 16; } if (!(x & 0xff000000)) { k += 8; x <<= 8; } if (!(x & 0xf0000000)) { k += 4; x <<= 4; } if (!(x & 0xc0000000)) { k += 2; x <<= 2; } if (!(x & 0x80000000)) { k++; if (!(x & 0x40000000)) return 32; } return k; } static int lo0bits #ifdef KR_headers (y) ULong *y; #else (ULong *y) #endif { int k; ULong x = *y; if (x & 7) { if (x & 1) return 0; if (x & 2) { *y = x >> 1; return 1; } *y = x >> 2; return 2; } k = 0; if (!(x & 0xffff)) { k = 16; x >>= 16; } if (!(x & 0xff)) { k += 8; x >>= 8; } if (!(x & 0xf)) { k += 4; x >>= 4; } if (!(x & 0x3)) { k += 2; x >>= 2; } if (!(x & 1)) { k++; x >>= 1; if (!x) return 32; } *y = x; return k; } static Bigint * i2b #ifdef KR_headers (i) int i; #else (int i) #endif { Bigint *b; b = Balloc(1); b->x[0] = i; b->wds = 1; return b; } static Bigint * mult #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { Bigint *c; int k, wa, wb, wc; ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; ULong y; #ifdef ULLong ULLong carry, z; #else ULong carry, z; #ifdef Pack_32 ULong z2; #endif #endif if (a->wds < b->wds) { c = a; a = b; b = c; } k = a->k; wa = a->wds; wb = b->wds; wc = wa + wb; if (wc > a->maxwds) k++; c = Balloc(k); for(x = c->x, xa = x + wc; x < xa; x++) *x = 0; xa = a->x; xae = xa + wa; xb = b->x; xbe = xb + wb; xc0 = c->x; #ifdef ULLong for(; xb < xbe; xc0++) { if ((y = *xb++)) { x = xa; xc = xc0; carry = 0; do { z = *x++ * (ULLong)y + *xc + carry; carry = z >> 32; *xc++ = z & FFFFFFFF; } while(x < xae); *xc = carry; } } #else #ifdef Pack_32 for(; xb < xbe; xb++, xc0++) { if (y = *xb & 0xffff) { x = xa; xc = xc0; carry = 0; do { z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; carry = z >> 16; z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; carry = z2 >> 16; Storeinc(xc, z2, z); } while(x < xae); *xc = carry; } if (y = *xb >> 16) { x = xa; xc = xc0; carry = 0; z2 = *xc; do { z = (*x & 0xffff) * y + (*xc >> 16) + carry; carry = z >> 16; Storeinc(xc, z, z2); z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; carry = z2 >> 16; } while(x < xae); *xc = z2; } } #else for(; xb < xbe; xc0++) { if (y = *xb++) { x = xa; xc = xc0; carry = 0; do { z = *x++ * y + *xc + carry; carry = z >> 16; *xc++ = z & 0xffff; } while(x < xae); *xc = carry; } } #endif #endif for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; c->wds = wc; return c; } static Bigint *p5s; static Bigint * pow5mult #ifdef KR_headers (b, k) Bigint *b; int k; #else (Bigint *b, int k) #endif { Bigint *b1, *p5, *p51; int i; static int p05[3] = { 5, 25, 125 }; if ((i = k & 3)) b = multadd(b, p05[i-1], 0); if (!(k >>= 2)) return b; if (!(p5 = p5s)) { /* first time */ #ifdef MULTIPLE_THREADS ACQUIRE_DTOA_LOCK(1); if (!(p5 = p5s)) { p5 = p5s = i2b(625); p5->next = 0; } FREE_DTOA_LOCK(1); #else p5 = p5s = i2b(625); p5->next = 0; #endif } for(;;) { if (k & 1) { b1 = mult(b, p5); Bfree(b); b = b1; } if (!(k >>= 1)) break; if (!(p51 = p5->next)) { #ifdef MULTIPLE_THREADS ACQUIRE_DTOA_LOCK(1); if (!(p51 = p5->next)) { p51 = p5->next = mult(p5,p5); p51->next = 0; } FREE_DTOA_LOCK(1); #else p51 = p5->next = mult(p5,p5); p51->next = 0; #endif } p5 = p51; } return b; } static Bigint * lshift #ifdef KR_headers (b, k) Bigint *b; int k; #else (Bigint *b, int k) #endif { int i, k1, n, n1; Bigint *b1; ULong *x, *x1, *xe, z; #ifdef Pack_32 n = k >> 5; #else n = k >> 4; #endif k1 = b->k; n1 = n + b->wds + 1; for(i = b->maxwds; n1 > i; i <<= 1) k1++; b1 = Balloc(k1); x1 = b1->x; for(i = 0; i < n; i++) *x1++ = 0; x = b->x; xe = x + b->wds; #ifdef Pack_32 if (k &= 0x1f) { k1 = 32 - k; z = 0; do { *x1++ = *x << k | z; z = *x++ >> k1; } while(x < xe); if ((*x1 = z)) ++n1; } #else if (k &= 0xf) { k1 = 16 - k; z = 0; do { *x1++ = *x << k & 0xffff | z; z = *x++ >> k1; } while(x < xe); if (*x1 = z) ++n1; } #endif else do *x1++ = *x++; while(x < xe); b1->wds = n1 - 1; Bfree(b); return b1; } static int cmp #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { ULong *xa, *xa0, *xb, *xb0; int i, j; i = a->wds; j = b->wds; #ifdef DEBUG if (i > 1 && !a->x[i-1]) Bug("cmp called with a->x[a->wds-1] == 0"); if (j > 1 && !b->x[j-1]) Bug("cmp called with b->x[b->wds-1] == 0"); #endif if (i -= j) return i; xa0 = a->x; xa = xa0 + j; xb0 = b->x; xb = xb0 + j; for(;;) { if (*--xa != *--xb) return *xa < *xb ? -1 : 1; if (xa <= xa0) break; } return 0; } static Bigint * diff #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { Bigint *c; int i, wa, wb; ULong *xa, *xae, *xb, *xbe, *xc; #ifdef ULLong ULLong borrow, y; #else ULong borrow, y; #ifdef Pack_32 ULong z; #endif #endif i = cmp(a,b); if (!i) { c = Balloc(0); c->wds = 1; c->x[0] = 0; return c; } if (i < 0) { c = a; a = b; b = c; i = 1; } else i = 0; c = Balloc(a->k); c->sign = i; wa = a->wds; xa = a->x; xae = xa + wa; wb = b->wds; xb = b->x; xbe = xb + wb; xc = c->x; borrow = 0; #ifdef ULLong do { y = (ULLong)*xa++ - *xb++ - borrow; borrow = y >> 32 & (ULong)1; *xc++ = y & FFFFFFFF; } while(xb < xbe); while(xa < xae) { y = *xa++ - borrow; borrow = y >> 32 & (ULong)1; *xc++ = y & FFFFFFFF; } #else #ifdef Pack_32 do { y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(xc, z, y); } while(xb < xbe); while(xa < xae) { y = (*xa & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*xa++ >> 16) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(xc, z, y); } #else do { y = *xa++ - *xb++ - borrow; borrow = (y & 0x10000) >> 16; *xc++ = y & 0xffff; } while(xb < xbe); while(xa < xae) { y = *xa++ - borrow; borrow = (y & 0x10000) >> 16; *xc++ = y & 0xffff; } #endif #endif while(!*--xc) wa--; c->wds = wa; return c; } static double ulp #ifdef KR_headers (x) U *x; #else (U *x) #endif { Long L; U u; L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; #ifndef Avoid_Underflow #ifndef Sudden_Underflow if (L > 0) { #endif #endif #ifdef IBM L |= Exp_msk1 >> 4; #endif word0(&u) = L; word1(&u) = 0; #ifndef Avoid_Underflow #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { word0(&u) = 0x80000 >> L; word1(&u) = 0; } else { word0(&u) = 0; L -= Exp_shift; word1(&u) = L >= 31 ? 1 : 1 << 31 - L; } } #endif #endif return dval(&u); } static double b2d #ifdef KR_headers (a, e) Bigint *a; int *e; #else (Bigint *a, int *e) #endif { ULong *xa, *xa0, w, y, z; int k; U d; #ifdef VAX ULong d0, d1; #else #define d0 word0(&d) #define d1 word1(&d) #endif xa0 = a->x; xa = xa0 + a->wds; y = *--xa; #ifdef DEBUG if (!y) Bug("zero y in b2d"); #endif k = hi0bits(y); *e = 32 - k; #ifdef Pack_32 if (k < Ebits) { d0 = Exp_1 | y >> (Ebits - k); w = xa > xa0 ? *--xa : 0; d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); goto ret_d; } z = xa > xa0 ? *--xa : 0; if (k -= Ebits) { d0 = Exp_1 | y << k | z >> (32 - k); y = xa > xa0 ? *--xa : 0; d1 = z << k | y >> (32 - k); } else { d0 = Exp_1 | y; d1 = z; } #else if (k < Ebits + 16) { z = xa > xa0 ? *--xa : 0; d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; w = xa > xa0 ? *--xa : 0; y = xa > xa0 ? *--xa : 0; d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; goto ret_d; } z = xa > xa0 ? *--xa : 0; w = xa > xa0 ? *--xa : 0; k -= Ebits + 16; d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; y = xa > xa0 ? *--xa : 0; d1 = w << k + 16 | y << k; #endif ret_d: #ifdef VAX word0(&d) = d0 >> 16 | d0 << 16; word1(&d) = d1 >> 16 | d1 << 16; #else #undef d0 #undef d1 #endif return dval(&d); } static Bigint * d2b #ifdef KR_headers (d, e, bits) U *d; int *e, *bits; #else (U *d, int *e, int *bits) #endif { Bigint *b; int de, k; ULong *x, y, z; #ifndef Sudden_Underflow int i; #endif #ifdef VAX ULong d0, d1; d0 = word0(d) >> 16 | word0(d) << 16; d1 = word1(d) >> 16 | word1(d) << 16; #else #define d0 word0(d) #define d1 word1(d) #endif #ifdef Pack_32 b = Balloc(1); #else b = Balloc(2); #endif x = b->x; z = d0 & Frac_mask; d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ #ifdef Sudden_Underflow de = (int)(d0 >> Exp_shift); #ifndef IBM z |= Exp_msk11; #endif #else if ((de = (int)(d0 >> Exp_shift))) z |= Exp_msk1; #endif #ifdef Pack_32 if ((y = d1)) { if ((k = lo0bits(&y))) { x[0] = y | z << (32 - k); z >>= k; } else x[0] = y; #ifndef Sudden_Underflow i = #endif b->wds = (x[1] = z) ? 2 : 1; } else { k = lo0bits(&z); x[0] = z; #ifndef Sudden_Underflow i = #endif b->wds = 1; k += 32; } #else if (y = d1) { if (k = lo0bits(&y)) if (k >= 16) { x[0] = y | z << 32 - k & 0xffff; x[1] = z >> k - 16 & 0xffff; x[2] = z >> k; i = 2; } else { x[0] = y & 0xffff; x[1] = y >> 16 | z << 16 - k & 0xffff; x[2] = z >> k & 0xffff; x[3] = z >> k+16; i = 3; } else { x[0] = y & 0xffff; x[1] = y >> 16; x[2] = z & 0xffff; x[3] = z >> 16; i = 3; } } else { #ifdef DEBUG if (!z) Bug("Zero passed to d2b"); #endif k = lo0bits(&z); if (k >= 16) { x[0] = z; i = 0; } else { x[0] = z & 0xffff; x[1] = z >> 16; i = 1; } k += 32; } while(!x[i]) --i; b->wds = i + 1; #endif #ifndef Sudden_Underflow if (de) { #endif #ifdef IBM *e = (de - Bias - (P-1) << 2) + k; *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); #else *e = de - Bias - (P-1) + k; *bits = P - k; #endif #ifndef Sudden_Underflow } else { *e = de - Bias - (P-1) + 1 + k; #ifdef Pack_32 *bits = 32*i - hi0bits(x[i-1]); #else *bits = (i+2)*16 - hi0bits(x[i]); #endif } #endif return b; } #undef d0 #undef d1 static double ratio #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { U da, db; int k, ka, kb; dval(&da) = b2d(a, &ka); dval(&db) = b2d(b, &kb); #ifdef Pack_32 k = ka - kb + 32*(a->wds - b->wds); #else k = ka - kb + 16*(a->wds - b->wds); #endif #ifdef IBM if (k > 0) { word0(&da) += (k >> 2)*Exp_msk1; if (k &= 3) dval(&da) *= 1 << k; } else { k = -k; word0(&db) += (k >> 2)*Exp_msk1; if (k &= 3) dval(&db) *= 1 << k; } #else if (k > 0) word0(&da) += k*Exp_msk1; else { k = -k; word0(&db) += k*Exp_msk1; } #endif return dval(&da) / dval(&db); } static CONST double tens[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 #ifdef VAX , 1e23, 1e24 #endif }; static CONST double #ifdef IEEE_Arith bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, #ifdef Avoid_Underflow 9007199254740992.*9007199254740992.e-256 /* = 2^106 * 1e-256 */ #else 1e-256 #endif }; /* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ /* flag unnecessarily. It leads to a song and dance at the end of strtod. */ #define Scale_Bit 0x10 #define n_bigtens 5 #else #ifdef IBM bigtens[] = { 1e16, 1e32, 1e64 }; static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; #define n_bigtens 3 #else bigtens[] = { 1e16, 1e32 }; static CONST double tinytens[] = { 1e-16, 1e-32 }; #define n_bigtens 2 #endif #endif #undef Need_Hexdig #ifdef INFNAN_CHECK #ifndef No_Hex_NaN #define Need_Hexdig #endif #endif #ifndef Need_Hexdig #ifndef NO_HEX_FP #define Need_Hexdig #endif #endif #ifdef Need_Hexdig /*{*/ static unsigned char hexdig[256]; static void #ifdef KR_headers htinit(h, s, inc) unsigned char *h; unsigned char *s; int inc; #else htinit(unsigned char *h, unsigned char *s, int inc) #endif { int i, j; for(i = 0; (j = s[i]) !=0; i++) h[j] = i + inc; } static void #ifdef KR_headers hexdig_init() #else hexdig_init(void) #endif { #define USC (unsigned char *) htinit(hexdig, USC "0123456789", 0x10); htinit(hexdig, USC "abcdef", 0x10 + 10); htinit(hexdig, USC "ABCDEF", 0x10 + 10); } #endif /* } Need_Hexdig */ #ifdef INFNAN_CHECK #ifndef NAN_WORD0 #define NAN_WORD0 0x7ff80000 #endif #ifndef NAN_WORD1 #define NAN_WORD1 0 #endif static int match #ifdef KR_headers (sp, t) char **sp, *t; #else (const char **sp, const char *t) #endif { int c, d; CONST char *s = *sp; while((d = *t++)) { if ((c = *++s) >= 'A' && c <= 'Z') c += 'a' - 'A'; if (c != d) return 0; } *sp = s + 1; return 1; } #ifndef No_Hex_NaN static void hexnan #ifdef KR_headers (rvp, sp) U *rvp; CONST char **sp; #else (U *rvp, const char **sp) #endif { ULong c, x[2]; CONST char *s; int c1, havedig, udx0, xshift; if (!hexdig['0']) hexdig_init(); x[0] = x[1] = 0; havedig = xshift = 0; udx0 = 1; s = *sp; /* allow optional initial 0x or 0X */ while((c = *(CONST unsigned char*)(s+1)) && c <= ' ') ++s; if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X')) s += 2; while((c = *(CONST unsigned char*)++s)) { if ((c1 = hexdig[c])) c = c1 & 0xf; else if (c <= ' ') { if (udx0 && havedig) { udx0 = 0; xshift = 1; } continue; } #ifdef GDTOA_NON_PEDANTIC_NANCHECK else if (/*(*/ c == ')' && havedig) { *sp = s + 1; break; } else return; /* invalid form: don't change *sp */ #else else { do { if (/*(*/ c == ')') { *sp = s + 1; break; } } while((c = *++s)); break; } #endif havedig = 1; if (xshift) { xshift = 0; x[0] = x[1]; x[1] = 0; } if (udx0) x[0] = (x[0] << 4) | (x[1] >> 28); x[1] = (x[1] << 4) | c; } if ((x[0] &= 0xfffff) || x[1]) { word0(rvp) = Exp_mask | x[0]; word1(rvp) = x[1]; } } #endif /*No_Hex_NaN*/ #endif /* INFNAN_CHECK */ #ifdef Pack_32 #define ULbits 32 #define kshift 5 #define kmask 31 #else #define ULbits 16 #define kshift 4 #define kmask 15 #endif #if !defined(NO_HEX_FP) || defined(Honor_FLT_ROUNDS) /*{*/ static Bigint * #ifdef KR_headers increment(b) Bigint *b; #else increment(Bigint *b) #endif { ULong *x, *xe; Bigint *b1; x = b->x; xe = x + b->wds; do { if (*x < (ULong)0xffffffffL) { ++*x; return b; } *x++ = 0; } while(x < xe); { if (b->wds >= b->maxwds) { b1 = Balloc(b->k+1); Bcopy(b1,b); Bfree(b); b = b1; } b->x[b->wds++] = 1; } return b; } #endif /*}*/ #ifndef NO_HEX_FP /*{*/ static void #ifdef KR_headers rshift(b, k) Bigint *b; int k; #else rshift(Bigint *b, int k) #endif { ULong *x, *x1, *xe, y; int n; x = x1 = b->x; n = k >> kshift; if (n < b->wds) { xe = x + b->wds; x += n; if (k &= kmask) { n = 32 - k; y = *x++ >> k; while(x < xe) { *x1++ = (y | (*x << n)) & 0xffffffff; y = *x++ >> k; } if ((*x1 = y) !=0) x1++; } else while(x < xe) *x1++ = *x++; } if ((b->wds = x1 - b->x) == 0) b->x[0] = 0; } static ULong #ifdef KR_headers any_on(b, k) Bigint *b; int k; #else any_on(Bigint *b, int k) #endif { int n, nwds; ULong *x, *x0, x1, x2; x = b->x; nwds = b->wds; n = k >> kshift; if (n > nwds) n = nwds; else if (n < nwds && (k &= kmask)) { x1 = x2 = x[n]; x1 >>= k; x1 <<= k; if (x1 != x2) return 1; } x0 = x; x += n; while(x > x0) if (*--x) return 1; return 0; } enum { /* rounding values: same as FLT_ROUNDS */ Round_zero = 0, Round_near = 1, Round_up = 2, Round_down = 3 }; void #ifdef KR_headers gethex(sp, rvp, rounding, sign) CONST char **sp; U *rvp; int rounding, sign; #else gethex( CONST char **sp, U *rvp, int rounding, int sign) #endif { Bigint *b; CONST unsigned char *decpt, *s0, *s, *s1; Long e, e1; ULong L, lostbits, *x; int big, denorm, esign, havedig, k, n, nbits, up, zret; #ifdef IBM int j; #endif enum { #ifdef IEEE_Arith /*{{*/ emax = 0x7fe - Bias - P + 1, emin = Emin - P + 1 #else /*}{*/ emin = Emin - P, #ifdef VAX emax = 0x7ff - Bias - P + 1 #endif #ifdef IBM emax = 0x7f - Bias - P #endif #endif /*}}*/ }; #ifdef USE_LOCALE int i; #ifdef NO_LOCALE_CACHE const unsigned char *decimalpoint = (unsigned char*) localeconv()->decimal_point; #else const unsigned char *decimalpoint; static unsigned char *decimalpoint_cache; if (!(s0 = decimalpoint_cache)) { s0 = (unsigned char*)localeconv()->decimal_point; if ((decimalpoint_cache = (unsigned char*) MALLOC(strlen((CONST char*)s0) + 1))) { strcpy((char*)decimalpoint_cache, (CONST char*)s0); s0 = decimalpoint_cache; } } decimalpoint = s0; #endif #endif if (!hexdig['0']) hexdig_init(); havedig = 0; s0 = *(CONST unsigned char **)sp + 2; while(s0[havedig] == '0') havedig++; s0 += havedig; s = s0; decpt = 0; zret = 0; e = 0; if (hexdig[*s]) havedig++; else { zret = 1; #ifdef USE_LOCALE for(i = 0; decimalpoint[i]; ++i) { if (s[i] != decimalpoint[i]) goto pcheck; } decpt = s += i; #else if (*s != '.') goto pcheck; decpt = ++s; #endif if (!hexdig[*s]) goto pcheck; while(*s == '0') s++; if (hexdig[*s]) zret = 0; havedig = 1; s0 = s; } while(hexdig[*s]) s++; #ifdef USE_LOCALE if (*s == *decimalpoint && !decpt) { for(i = 1; decimalpoint[i]; ++i) { if (s[i] != decimalpoint[i]) goto pcheck; } decpt = s += i; #else if (*s == '.' && !decpt) { decpt = ++s; #endif while(hexdig[*s]) s++; }/*}*/ if (decpt) e = -(((Long)(s-decpt)) << 2); pcheck: s1 = s; big = esign = 0; switch(*s) { case 'p': case 'P': switch(*++s) { case '-': esign = 1; /* no break */ case '+': s++; } if ((n = hexdig[*s]) == 0 || n > 0x19) { s = s1; break; } e1 = n - 0x10; while((n = hexdig[*++s]) !=0 && n <= 0x19) { if (e1 & 0xf8000000) big = 1; e1 = 10*e1 + n - 0x10; } if (esign) e1 = -e1; e += e1; } *sp = (char*)s; if (!havedig) *sp = (char*)s0 - 1; if (zret) goto retz1; if (big) { if (esign) { #ifdef IEEE_Arith switch(rounding) { case Round_up: if (sign) break; goto ret_tiny; case Round_down: if (!sign) break; goto ret_tiny; } #endif goto retz; #ifdef IEEE_Arith ret_tiny: #ifndef NO_ERRNO errno = ERANGE; #endif word0(rvp) = 0; word1(rvp) = 1; return; #endif /* IEEE_Arith */ } switch(rounding) { case Round_near: goto ovfl1; case Round_up: if (!sign) goto ovfl1; goto ret_big; case Round_down: if (sign) goto ovfl1; goto ret_big; } ret_big: word0(rvp) = Big0; word1(rvp) = Big1; return; } n = s1 - s0 - 1; for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) k++; b = Balloc(k); x = b->x; n = 0; L = 0; #ifdef USE_LOCALE for(i = 0; decimalpoint[i+1]; ++i); #endif while(s1 > s0) { #ifdef USE_LOCALE if (*--s1 == decimalpoint[i]) { s1 -= i; continue; } #else if (*--s1 == '.') continue; #endif if (n == ULbits) { *x++ = L; L = 0; n = 0; } L |= (hexdig[*s1] & 0x0f) << n; n += 4; } *x++ = L; b->wds = n = x - b->x; n = ULbits*n - hi0bits(L); nbits = Nbits; lostbits = 0; x = b->x; if (n > nbits) { n -= nbits; if (any_on(b,n)) { lostbits = 1; k = n - 1; if (x[k>>kshift] & 1 << (k & kmask)) { lostbits = 2; if (k > 0 && any_on(b,k)) lostbits = 3; } } rshift(b, n); e += n; } else if (n < nbits) { n = nbits - n; b = lshift(b, n); e -= n; x = b->x; } if (e > Emax) { ovfl: Bfree(b); ovfl1: #ifndef NO_ERRNO errno = ERANGE; #endif word0(rvp) = Exp_mask; word1(rvp) = 0; return; } denorm = 0; if (e < emin) { denorm = 1; n = emin - e; if (n >= nbits) { #ifdef IEEE_Arith /*{*/ switch (rounding) { case Round_near: if (n == nbits && (n < 2 || any_on(b,n-1))) goto ret_tiny; break; case Round_up: if (!sign) goto ret_tiny; break; case Round_down: if (sign) goto ret_tiny; } #endif /* } IEEE_Arith */ Bfree(b); retz: #ifndef NO_ERRNO errno = ERANGE; #endif retz1: rvp->d = 0.; return; } k = n - 1; if (lostbits) lostbits = 1; else if (k > 0) lostbits = any_on(b,k); if (x[k>>kshift] & 1 << (k & kmask)) lostbits |= 2; nbits -= n; rshift(b,n); e = emin; } if (lostbits) { up = 0; switch(rounding) { case Round_zero: break; case Round_near: if (lostbits & 2 && (lostbits & 1) | (x[0] & 1)) up = 1; break; case Round_up: up = 1 - sign; break; case Round_down: up = sign; } if (up) { k = b->wds; b = increment(b); x = b->x; if (denorm) { #if 0 if (nbits == Nbits - 1 && x[nbits >> kshift] & 1 << (nbits & kmask)) denorm = 0; /* not currently used */ #endif } else if (b->wds > k || ((n = nbits & kmask) !=0 && hi0bits(x[k-1]) < 32-n)) { rshift(b,1); if (++e > Emax) goto ovfl; } } } #ifdef IEEE_Arith if (denorm) word0(rvp) = b->wds > 1 ? b->x[1] & ~0x100000 : 0; else word0(rvp) = (b->x[1] & ~0x100000) | ((e + 0x3ff + 52) << 20); word1(rvp) = b->x[0]; #endif #ifdef IBM if ((j = e & 3)) { k = b->x[0] & ((1 << j) - 1); rshift(b,j); if (k) { switch(rounding) { case Round_up: if (!sign) increment(b); break; case Round_down: if (sign) increment(b); break; case Round_near: j = 1 << (j-1); if (k & j && ((k & (j-1)) | lostbits)) increment(b); } } } e >>= 2; word0(rvp) = b->x[1] | ((e + 65 + 13) << 24); word1(rvp) = b->x[0]; #endif #ifdef VAX /* The next two lines ignore swap of low- and high-order 2 bytes. */ /* word0(rvp) = (b->x[1] & ~0x800000) | ((e + 129 + 55) << 23); */ /* word1(rvp) = b->x[0]; */ word0(rvp) = ((b->x[1] & ~0x800000) >> 16) | ((e + 129 + 55) << 7) | (b->x[1] << 16); word1(rvp) = (b->x[0] >> 16) | (b->x[0] << 16); #endif Bfree(b); } #endif /*!NO_HEX_FP}*/ static int #ifdef KR_headers dshift(b, p2) Bigint *b; int p2; #else dshift(Bigint *b, int p2) #endif { int rv = hi0bits(b->x[b->wds-1]) - 4; if (p2 > 0) rv -= p2; return rv & kmask; } static int quorem #ifdef KR_headers (b, S) Bigint *b, *S; #else (Bigint *b, Bigint *S) #endif { int n; ULong *bx, *bxe, q, *sx, *sxe; #ifdef ULLong ULLong borrow, carry, y, ys; #else ULong borrow, carry, y, ys; #ifdef Pack_32 ULong si, z, zs; #endif #endif n = S->wds; #ifdef DEBUG /*debug*/ if (b->wds > n) /*debug*/ Bug("oversize b in quorem"); #endif if (b->wds < n) return 0; sx = S->x; sxe = sx + --n; bx = b->x; bxe = bx + n; q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ #ifdef DEBUG #ifdef NO_STRTOD_BIGCOMP /*debug*/ if (q > 9) #else /* An oversized q is possible when quorem is called from bigcomp and */ /* the input is near, e.g., twice the smallest denormalized number. */ /*debug*/ if (q > 15) #endif /*debug*/ Bug("oversized quotient in quorem"); #endif if (q) { borrow = 0; carry = 0; do { #ifdef ULLong ys = *sx++ * (ULLong)q + carry; carry = ys >> 32; y = *bx - (ys & FFFFFFFF) - borrow; borrow = y >> 32 & (ULong)1; *bx++ = y & FFFFFFFF; #else #ifdef Pack_32 si = *sx++; ys = (si & 0xffff) * q + carry; zs = (si >> 16) * q + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*bx >> 16) - (zs & 0xffff) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(bx, z, y); #else ys = *sx++ * q + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; *bx++ = y & 0xffff; #endif #endif } while(sx <= sxe); if (!*bxe) { bx = b->x; while(--bxe > bx && !*bxe) --n; b->wds = n; } } if (cmp(b, S) >= 0) { q++; borrow = 0; carry = 0; bx = b->x; sx = S->x; do { #ifdef ULLong ys = *sx++ + carry; carry = ys >> 32; y = *bx - (ys & FFFFFFFF) - borrow; borrow = y >> 32 & (ULong)1; *bx++ = y & FFFFFFFF; #else #ifdef Pack_32 si = *sx++; ys = (si & 0xffff) + carry; zs = (si >> 16) + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*bx >> 16) - (zs & 0xffff) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(bx, z, y); #else ys = *sx++ + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; *bx++ = y & 0xffff; #endif #endif } while(sx <= sxe); bx = b->x; bxe = bx + n; if (!*bxe) { while(--bxe > bx && !*bxe) --n; b->wds = n; } } return q; } #if defined(Avoid_Underflow) || !defined(NO_STRTOD_BIGCOMP) /*{*/ static double sulp #ifdef KR_headers (x, bc) U *x; BCinfo *bc; #else (U *x, BCinfo *bc) #endif { U u; double rv; int i; rv = ulp(x); if (!bc->scale || (i = 2*P + 1 - ((word0(x) & Exp_mask) >> Exp_shift)) <= 0) return rv; /* Is there an example where i <= 0 ? */ word0(&u) = Exp_1 + (i << Exp_shift); word1(&u) = 0; return rv * u.d; } #endif /*}*/ #ifndef NO_STRTOD_BIGCOMP static void bigcomp #ifdef KR_headers (rv, s0, bc) U *rv; CONST char *s0; BCinfo *bc; #else (U *rv, const char *s0, BCinfo *bc) #endif { Bigint *b, *d; int b2, bbits, d2, dd, dig, dsign, i, j, nd, nd0, p2, p5, speccase; dsign = bc->dsign; nd = bc->nd; nd0 = bc->nd0; p5 = nd + bc->e0 - 1; speccase = 0; #ifndef Sudden_Underflow if (rv->d == 0.) { /* special case: value near underflow-to-zero */ /* threshold was rounded to zero */ b = i2b(1); p2 = Emin - P + 1; bbits = 1; #ifdef Avoid_Underflow word0(rv) = (P+2) << Exp_shift; #else word1(rv) = 1; #endif i = 0; #ifdef Honor_FLT_ROUNDS if (bc->rounding == 1) #endif { speccase = 1; --p2; dsign = 0; goto have_i; } } else #endif b = d2b(rv, &p2, &bbits); #ifdef Avoid_Underflow p2 -= bc->scale; #endif /* floor(log2(rv)) == bbits - 1 + p2 */ /* Check for denormal case. */ i = P - bbits; if (i > (j = P - Emin - 1 + p2)) { #ifdef Sudden_Underflow Bfree(b); b = i2b(1); p2 = Emin; i = P - 1; #ifdef Avoid_Underflow word0(rv) = (1 + bc->scale) << Exp_shift; #else word0(rv) = Exp_msk1; #endif word1(rv) = 0; #else i = j; #endif } #ifdef Honor_FLT_ROUNDS if (bc->rounding != 1) { if (i > 0) b = lshift(b, i); if (dsign) b = increment(b); } else #endif { b = lshift(b, ++i); b->x[0] |= 1; } #ifndef Sudden_Underflow have_i: #endif p2 -= p5 + i; d = i2b(1); /* Arrange for convenient computation of quotients: * shift left if necessary so divisor has 4 leading 0 bits. */ if (p5 > 0) d = pow5mult(d, p5); else if (p5 < 0) b = pow5mult(b, -p5); if (p2 > 0) { b2 = p2; d2 = 0; } else { b2 = 0; d2 = -p2; } i = dshift(d, d2); if ((b2 += i) > 0) b = lshift(b, b2); if ((d2 += i) > 0) d = lshift(d, d2); /* Now b/d = exactly half-way between the two floating-point values */ /* on either side of the input string. Compute first digit of b/d. */ if (!(dig = quorem(b,d))) { b = multadd(b, 10, 0); /* very unlikely */ dig = quorem(b,d); } /* Compare b/d with s0 */ for(i = 0; i < nd0; ) { if ((dd = s0[i++] - '0' - dig)) goto ret; if (!b->x[0] && b->wds == 1) { if (i < nd) dd = 1; goto ret; } b = multadd(b, 10, 0); dig = quorem(b,d); } for(j = bc->dp1; i++ < nd;) { if ((dd = s0[j++] - '0' - dig)) goto ret; if (!b->x[0] && b->wds == 1) { if (i < nd) dd = 1; goto ret; } b = multadd(b, 10, 0); dig = quorem(b,d); } if (b->x[0] || b->wds > 1 || dig > 0) dd = -1; ret: Bfree(b); Bfree(d); #ifdef Honor_FLT_ROUNDS if (bc->rounding != 1) { if (dd < 0) { if (bc->rounding == 0) { if (!dsign) goto retlow1; } else if (dsign) goto rethi1; } else if (dd > 0) { if (bc->rounding == 0) { if (dsign) goto rethi1; goto ret1; } if (!dsign) goto rethi1; dval(rv) += 2.*sulp(rv,bc); } else { bc->inexact = 0; if (dsign) goto rethi1; } } else #endif if (speccase) { if (dd <= 0) rv->d = 0.; } else if (dd < 0) { if (!dsign) /* does not happen for round-near */ retlow1: dval(rv) -= sulp(rv,bc); } else if (dd > 0) { if (dsign) { rethi1: dval(rv) += sulp(rv,bc); } } else { /* Exact half-way case: apply round-even rule. */ if ((j = ((word0(rv) & Exp_mask) >> Exp_shift) - bc->scale) <= 0) { i = 1 - j; if (i <= 31) { if (word1(rv) & (0x1 << i)) goto odd; } else if (word0(rv) & (0x1 << (i-32))) goto odd; } else if (word1(rv) & 1) { odd: if (dsign) goto rethi1; goto retlow1; } } #ifdef Honor_FLT_ROUNDS ret1: #endif return; } #endif /* NO_STRTOD_BIGCOMP */ double strtod #ifdef KR_headers (s00, se) CONST char *s00; char **se; #else (const char *s00, char **se) #endif { int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, e, e1; int esign, i, j, k, nd, nd0, nf, nz, nz0, nz1, sign; CONST char *s, *s0, *s1; double aadj, aadj1; Long L; U aadj2, adj, rv, rv0; ULong y, z; BCinfo bc; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; #ifdef Avoid_Underflow ULong Lsb, Lsb1; #endif #ifdef SET_INEXACT int oldinexact; #endif #ifndef NO_STRTOD_BIGCOMP int req_bigcomp = 0; #endif #ifdef Honor_FLT_ROUNDS /*{*/ #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ bc.rounding = Flt_Rounds; #else /*}{*/ bc.rounding = 1; switch(fegetround()) { case FE_TOWARDZERO: bc.rounding = 0; break; case FE_UPWARD: bc.rounding = 2; break; case FE_DOWNWARD: bc.rounding = 3; } #endif /*}}*/ #endif /*}*/ #ifdef USE_LOCALE CONST char *s2; #endif sign = nz0 = nz1 = nz = bc.dplen = bc.uflchk = 0; dval(&rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': sign = 1; /* no break */ case '+': if (*++s) goto break2; /* no break */ case 0: goto ret0; case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': continue; default: goto break2; } break2: if (*s == '0') { #ifndef NO_HEX_FP /*{*/ switch(s[1]) { case 'x': case 'X': #ifdef Honor_FLT_ROUNDS gethex(&s, &rv, bc.rounding, sign); #else gethex(&s, &rv, 1, sign); #endif goto ret; } #endif /*}*/ nz0 = 1; while(*++s == '0') ; if (!*s) goto ret; } s0 = s; y = z = 0; for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) if (nd < 9) y = 10*y + c - '0'; else if (nd < 16) z = 10*z + c - '0'; nd0 = nd; bc.dp0 = bc.dp1 = s - s0; for(s1 = s; s1 > s0 && *--s1 == '0'; ) ++nz1; #ifdef USE_LOCALE s1 = localeconv()->decimal_point; if (c == *s1) { c = '.'; if (*++s1) { s2 = s; for(;;) { if (*++s2 != *s1) { c = 0; break; } if (!*++s1) { s = s2; break; } } } } #endif if (c == '.') { c = *++s; bc.dp1 = s - s0; bc.dplen = bc.dp1 - bc.dp0; if (!nd) { for(; c == '0'; c = *++s) nz++; if (c > '0' && c <= '9') { bc.dp0 = s0 - s; bc.dp1 = bc.dp0 + bc.dplen; s0 = s; nf += nz; nz = 0; goto have_dig; } goto dig_done; } for(; c >= '0' && c <= '9'; c = *++s) { have_dig: nz++; if (c -= '0') { nf += nz; for(i = 1; i < nz; i++) if (nd++ < 9) y *= 10; else if (nd <= DBL_DIG + 1) z *= 10; if (nd++ < 9) y = 10*y + c; else if (nd <= DBL_DIG + 1) z = 10*z + c; nz = nz1 = 0; } } } dig_done: e = 0; if (c == 'e' || c == 'E') { if (!nd && !nz && !nz0) { goto ret0; } s00 = s; esign = 0; switch(c = *++s) { case '-': esign = 1; case '+': c = *++s; } if (c >= '0' && c <= '9') { while(c == '0') c = *++s; if (c > '0' && c <= '9') { L = c - '0'; s1 = s; while((c = *++s) >= '0' && c <= '9') L = 10*L + c - '0'; if (s - s1 > 8 || L > 19999) /* Avoid confusion from exponents * so large that e might overflow. */ e = 19999; /* safe for 16 bit ints */ else e = (int)L; if (esign) e = -e; } else e = 0; } else s = s00; } if (!nd) { if (!nz && !nz0) { #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ if (!bc.dplen) switch(c) { case 'i': case 'I': if (match(&s,"nf")) { --s; if (!match(&s,"inity")) ++s; word0(&rv) = 0x7ff00000; word1(&rv) = 0; goto ret; } break; case 'n': case 'N': if (match(&s, "an")) { word0(&rv) = NAN_WORD0; word1(&rv) = NAN_WORD1; #ifndef No_Hex_NaN if (*s == '(') /*)*/ hexnan(&rv, &s); #endif goto ret; } } #endif /* INFNAN_CHECK */ ret0: s = s00; sign = 0; } goto ret; } bc.e0 = e1 = e -= nf; /* Now we have nd0 digits, starting at s0, followed by a * decimal point, followed by nd-nd0 digits. The number we're * after is the integer represented by those digits times * 10**e */ if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; dval(&rv) = y; if (k > 9) { #ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact(); #endif dval(&rv) = tens[k - 9] * dval(&rv) + z; } bd0 = 0; if (nd <= DBL_DIG #ifndef RND_PRODQUOT #ifndef Honor_FLT_ROUNDS && Flt_Rounds == 1 #endif #endif ) { if (!e) goto ret; #ifndef ROUND_BIASED_without_Round_Up if (e > 0) { if (e <= Ten_pmax) { #ifdef VAX goto vax_ovfl_check; #else #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv.d = -rv.d; sign = 0; } #endif /* rv = */ rounded_product(dval(&rv), tens[e]); goto ret; #endif } i = DBL_DIG - nd; if (e <= Ten_pmax + i) { /* A fancier test would sometimes let us do * this for larger i values. */ #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv.d = -rv.d; sign = 0; } #endif e -= i; dval(&rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: word0(&rv) -= P*Exp_msk1; /* rv = */ rounded_product(dval(&rv), tens[e]); if ((word0(&rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto ovfl; word0(&rv) += P*Exp_msk1; #else /* rv = */ rounded_product(dval(&rv), tens[e]); #endif goto ret; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv.d = -rv.d; sign = 0; } #endif /* rv = */ rounded_quotient(dval(&rv), tens[-e]); goto ret; } #endif #endif /* ROUND_BIASED_without_Round_Up */ } e1 += nd - k; #ifdef IEEE_Arith #ifdef SET_INEXACT bc.inexact = 1; if (k <= DBL_DIG) oldinexact = get_inexact(); #endif #ifdef Avoid_Underflow bc.scale = 0; #endif #ifdef Honor_FLT_ROUNDS if (bc.rounding >= 2) { if (sign) bc.rounding = bc.rounding == 2 ? 0 : 2; else if (bc.rounding != 2) bc.rounding = 0; } #endif #endif /*IEEE_Arith*/ /* Get starting approximation = rv * 10**e1 */ if (e1 > 0) { if ((i = e1 & 15)) dval(&rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: /* Can't trust HUGE_VAL */ #ifdef IEEE_Arith #ifdef Honor_FLT_ROUNDS switch(bc.rounding) { case 0: /* toward 0 */ case 3: /* toward -infinity */ word0(&rv) = Big0; word1(&rv) = Big1; break; default: word0(&rv) = Exp_mask; word1(&rv) = 0; } #else /*Honor_FLT_ROUNDS*/ word0(&rv) = Exp_mask; word1(&rv) = 0; #endif /*Honor_FLT_ROUNDS*/ #ifdef SET_INEXACT /* set overflow bit */ dval(&rv0) = 1e300; dval(&rv0) *= dval(&rv0); #endif #else /*IEEE_Arith*/ word0(&rv) = Big0; word1(&rv) = Big1; #endif /*IEEE_Arith*/ range_err: if (bd0) { Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta); } #ifndef NO_ERRNO errno = ERANGE; #endif goto ret; } e1 >>= 4; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) dval(&rv) *= bigtens[j]; /* The last multiplication could overflow. */ word0(&rv) -= P*Exp_msk1; dval(&rv) *= bigtens[j]; if ((z = word0(&rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) goto ovfl; if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ word0(&rv) = Big0; word1(&rv) = Big1; } else word0(&rv) += P*Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if ((i = e1 & 15)) dval(&rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl; #ifdef Avoid_Underflow if (e1 & Scale_Bit) bc.scale = 2*P; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) dval(&rv) *= tinytens[j]; if (bc.scale && (j = 2*P + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; clear j low bits */ if (j >= 32) { if (j > 54) goto undfl; word1(&rv) = 0; if (j >= 53) word0(&rv) = (P+2)*Exp_msk1; else word0(&rv) &= 0xffffffff << (j-32); } else word1(&rv) &= 0xffffffff << j; } #else for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) dval(&rv) *= tinytens[j]; /* The last multiplication could underflow. */ dval(&rv0) = dval(&rv); dval(&rv) *= tinytens[j]; if (!dval(&rv)) { dval(&rv) = 2.*dval(&rv0); dval(&rv) *= tinytens[j]; #endif if (!dval(&rv)) { undfl: dval(&rv) = 0.; goto range_err; } #ifndef Avoid_Underflow word0(&rv) = Tiny0; word1(&rv) = Tiny1; /* The refinement below will clean * this approximation up. */ } #endif } } /* Now the hard part -- adjusting rv to the correct value.*/ /* Put digits into bd: true value = bd * 10^e */ bc.nd = nd - nz1; #ifndef NO_STRTOD_BIGCOMP bc.nd0 = nd0; /* Only needed if nd > strtod_diglim, but done here */ /* to silence an erroneous warning about bc.nd0 */ /* possibly not being initialized. */ if (nd > strtod_diglim) { /* ASSERT(strtod_diglim >= 18); 18 == one more than the */ /* minimum number of decimal digits to distinguish double values */ /* in IEEE arithmetic. */ i = j = 18; if (i > nd0) j += bc.dplen; for(;;) { if (--j < bc.dp1 && j >= bc.dp0) j = bc.dp0 - 1; if (s0[j] != '0') break; --i; } e += nd - i; nd = i; if (nd0 > nd) nd0 = nd; if (nd < 9) { /* must recompute y */ y = 0; for(i = 0; i < nd0; ++i) y = 10*y + s0[i] - '0'; for(j = bc.dp1; i < nd; ++i) y = 10*y + s0[j++] - '0'; } } #endif bd0 = s2b(s0, nd0, nd, y, bc.dplen); for(;;) { bd = Balloc(bd0->k); Bcopy(bd, bd0); bb = d2b(&rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ bs = i2b(1); if (e >= 0) { bb2 = bb5 = 0; bd2 = bd5 = e; } else { bb2 = bb5 = -e; bd2 = bd5 = 0; } if (bbe >= 0) bb2 += bbe; else bd2 -= bbe; bs2 = bb2; #ifdef Honor_FLT_ROUNDS if (bc.rounding != 1) bs2++; #endif #ifdef Avoid_Underflow Lsb = LSB; Lsb1 = 0; j = bbe - bc.scale; i = j + bbbits - 1; /* logb(rv) */ j = P + 1 - bbbits; if (i < Emin) { /* denormal */ i = Emin - i; j -= i; if (i < 32) Lsb <<= i; else if (i < 52) Lsb1 = Lsb << (i-32); else Lsb1 = Exp_mask; } #else /*Avoid_Underflow*/ #ifdef Sudden_Underflow #ifdef IBM j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); #else j = P + 1 - bbbits; #endif #else /*Sudden_Underflow*/ j = bbe; i = j + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j += P - Emin; else j = P + 1 - bbbits; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ bb2 += j; bd2 += j; #ifdef Avoid_Underflow bd2 += bc.scale; #endif i = bb2 < bd2 ? bb2 : bd2; if (i > bs2) i = bs2; if (i > 0) { bb2 -= i; bd2 -= i; bs2 -= i; } if (bb5 > 0) { bs = pow5mult(bs, bb5); bb1 = mult(bs, bb); Bfree(bb); bb = bb1; } if (bb2 > 0) bb = lshift(bb, bb2); if (bd5 > 0) bd = pow5mult(bd, bd5); if (bd2 > 0) bd = lshift(bd, bd2); if (bs2 > 0) bs = lshift(bs, bs2); delta = diff(bb, bd); bc.dsign = delta->sign; delta->sign = 0; i = cmp(delta, bs); #ifndef NO_STRTOD_BIGCOMP /*{*/ if (bc.nd > nd && i <= 0) { if (bc.dsign) { /* Must use bigcomp(). */ req_bigcomp = 1; break; } #ifdef Honor_FLT_ROUNDS if (bc.rounding != 1) { if (i < 0) { req_bigcomp = 1; break; } } else #endif i = -1; /* Discarded digits make delta smaller. */ } #endif /*}*/ #ifdef Honor_FLT_ROUNDS /*{*/ if (bc.rounding != 1) { if (i < 0) { /* Error is less than an ulp */ if (!delta->x[0] && delta->wds <= 1) { /* exact */ #ifdef SET_INEXACT bc.inexact = 0; #endif break; } if (bc.rounding) { if (bc.dsign) { adj.d = 1.; goto apply_adj; } } else if (!bc.dsign) { adj.d = -1.; if (!word1(&rv) && !(word0(&rv) & Frac_mask)) { y = word0(&rv) & Exp_mask; #ifdef Avoid_Underflow if (!bc.scale || y > 2*P*Exp_msk1) #else if (y) #endif { delta = lshift(delta,Log2P); if (cmp(delta, bs) <= 0) adj.d = -0.5; } } apply_adj: #ifdef Avoid_Underflow /*{*/ if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) word0(&adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { word0(&rv) += P*Exp_msk1; dval(&rv) += adj.d*ulp(dval(&rv)); word0(&rv) -= P*Exp_msk1; } else #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow}*/ dval(&rv) += adj.d*ulp(&rv); } break; } adj.d = ratio(delta, bs); if (adj.d < 1.) adj.d = 1.; if (adj.d <= 0x7ffffffe) { /* adj = rounding ? ceil(adj) : floor(adj); */ y = adj.d; if (y != adj.d) { if (!((bc.rounding>>1) ^ bc.dsign)) y++; adj.d = y; } } #ifdef Avoid_Underflow /*{*/ if (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) word0(&adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { word0(&rv) += P*Exp_msk1; adj.d *= ulp(dval(&rv)); if (bc.dsign) dval(&rv) += adj.d; else dval(&rv) -= adj.d; word0(&rv) -= P*Exp_msk1; goto cont; } #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow}*/ adj.d *= ulp(&rv); if (bc.dsign) { if (word0(&rv) == Big0 && word1(&rv) == Big1) goto ovfl; dval(&rv) += adj.d; } else dval(&rv) -= adj.d; goto cont; } #endif /*}Honor_FLT_ROUNDS*/ if (i < 0) { /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask #ifdef IEEE_Arith /*{*/ #ifdef Avoid_Underflow || (word0(&rv) & Exp_mask) <= (2*P+1)*Exp_msk1 #else || (word0(&rv) & Exp_mask) <= Exp_msk1 #endif #endif /*}*/ ) { #ifdef SET_INEXACT if (!delta->x[0] && delta->wds <= 1) bc.inexact = 0; #endif break; } if (!delta->x[0] && delta->wds <= 1) { /* exact result */ #ifdef SET_INEXACT bc.inexact = 0; #endif break; } delta = lshift(delta,Log2P); if (cmp(delta, bs) > 0) goto drop_down; break; } if (i == 0) { /* exactly half-way between */ if (bc.dsign) { if ((word0(&rv) & Bndry_mask1) == Bndry_mask1 && word1(&rv) == ( #ifdef Avoid_Underflow (bc.scale && (y = word0(&rv) & Exp_mask) <= 2*P*Exp_msk1) ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : #endif 0xffffffff)) { /*boundary case -- increment exponent*/ if (word0(&rv) == Big0 && word1(&rv) == Big1) goto ovfl; word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1 #ifdef IBM | Exp_msk1 >> 4 #endif ; word1(&rv) = 0; #ifdef Avoid_Underflow bc.dsign = 0; #endif break; } } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) { drop_down: /* boundary case -- decrement exponent */ #ifdef Sudden_Underflow /*{{*/ L = word0(&rv) & Exp_mask; #ifdef IBM if (L < Exp_msk1) #else #ifdef Avoid_Underflow if (L <= (bc.scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) #else if (L <= Exp_msk1) #endif /*Avoid_Underflow*/ #endif /*IBM*/ { if (bc.nd >nd) { bc.uflchk = 1; break; } goto undfl; } L -= Exp_msk1; #else /*Sudden_Underflow}{*/ #ifdef Avoid_Underflow if (bc.scale) { L = word0(&rv) & Exp_mask; if (L <= (2*P+1)*Exp_msk1) { if (L > (P+2)*Exp_msk1) /* round even ==> */ /* accept rv */ break; /* rv = smallest denormal */ if (bc.nd >nd) { bc.uflchk = 1; break; } goto undfl; } } #endif /*Avoid_Underflow*/ L = (word0(&rv) & Exp_mask) - Exp_msk1; #endif /*Sudden_Underflow}}*/ word0(&rv) = L | Bndry_mask1; word1(&rv) = 0xffffffff; #ifdef IBM goto cont; #else #ifndef NO_STRTOD_BIGCOMP if (bc.nd > nd) goto cont; #endif break; #endif } #ifndef ROUND_BIASED #ifdef Avoid_Underflow if (Lsb1) { if (!(word0(&rv) & Lsb1)) break; } else if (!(word1(&rv) & Lsb)) break; #else if (!(word1(&rv) & LSB)) break; #endif #endif if (bc.dsign) #ifdef Avoid_Underflow dval(&rv) += sulp(&rv, &bc); #else dval(&rv) += ulp(&rv); #endif #ifndef ROUND_BIASED else { #ifdef Avoid_Underflow dval(&rv) -= sulp(&rv, &bc); #else dval(&rv) -= ulp(&rv); #endif #ifndef Sudden_Underflow if (!dval(&rv)) { if (bc.nd >nd) { bc.uflchk = 1; break; } goto undfl; } #endif } #ifdef Avoid_Underflow bc.dsign = 1 - bc.dsign; #endif #endif break; } if ((aadj = ratio(delta, bs)) <= 2.) { if (bc.dsign) aadj = aadj1 = 1.; else if (word1(&rv) || word0(&rv) & Bndry_mask) { #ifndef Sudden_Underflow if (word1(&rv) == Tiny1 && !word0(&rv)) { if (bc.nd >nd) { bc.uflchk = 1; break; } goto undfl; } #endif aadj = 1.; aadj1 = -1.; } else { /* special case -- power of FLT_RADIX to be */ /* rounded down... */ if (aadj < 2./FLT_RADIX) aadj = 1./FLT_RADIX; else aadj *= 0.5; aadj1 = -aadj; } } else { aadj *= 0.5; aadj1 = bc.dsign ? aadj : -aadj; #ifdef Check_FLT_ROUNDS switch(bc.rounding) { case 2: /* towards +infinity */ aadj1 -= 0.5; break; case 0: /* towards 0 */ case 3: /* towards -infinity */ aadj1 += 0.5; } #else if (Flt_Rounds == 0) aadj1 += 0.5; #endif /*Check_FLT_ROUNDS*/ } y = word0(&rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { dval(&rv0) = dval(&rv); word0(&rv) -= P*Exp_msk1; adj.d = aadj1 * ulp(&rv); dval(&rv) += adj.d; if ((word0(&rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(&rv0) == Big0 && word1(&rv0) == Big1) goto ovfl; word0(&rv) = Big0; word1(&rv) = Big1; goto cont; } else word0(&rv) += P*Exp_msk1; } else { #ifdef Avoid_Underflow if (bc.scale && y <= 2*P*Exp_msk1) { if (aadj <= 0x7fffffff) { if ((z = aadj) <= 0) z = 1; aadj = z; aadj1 = bc.dsign ? aadj : -aadj; } dval(&aadj2) = aadj1; word0(&aadj2) += (2*P+1)*Exp_msk1 - y; aadj1 = dval(&aadj2); adj.d = aadj1 * ulp(&rv); dval(&rv) += adj.d; if (rv.d == 0.) #ifdef NO_STRTOD_BIGCOMP goto undfl; #else { if (bc.nd > nd) bc.dsign = 1; break; } #endif } else { adj.d = aadj1 * ulp(&rv); dval(&rv) += adj.d; } #else #ifdef Sudden_Underflow if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) { dval(&rv0) = dval(&rv); word0(&rv) += P*Exp_msk1; adj.d = aadj1 * ulp(&rv); dval(&rv) += adj.d; #ifdef IBM if ((word0(&rv) & Exp_mask) < P*Exp_msk1) #else if ((word0(&rv) & Exp_mask) <= P*Exp_msk1) #endif { if (word0(&rv0) == Tiny0 && word1(&rv0) == Tiny1) { if (bc.nd >nd) { bc.uflchk = 1; break; } goto undfl; } word0(&rv) = Tiny0; word1(&rv) = Tiny1; goto cont; } else word0(&rv) -= P*Exp_msk1; } else { adj.d = aadj1 * ulp(&rv); dval(&rv) += adj.d; } #else /*Sudden_Underflow*/ /* Compute adj so that the IEEE rounding rules will * correctly round rv + adj in some half-way cases. * If rv * ulp(rv) is denormalized (i.e., * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid * trouble from bits lost to denormalization; * example: 1.2e-307 . */ if (y <= (P-1)*Exp_msk1 && aadj > 1.) { aadj1 = (double)(int)(aadj + 0.5); if (!bc.dsign) aadj1 = -aadj1; } adj.d = aadj1 * ulp(&rv); dval(&rv) += adj.d; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ } z = word0(&rv) & Exp_mask; #ifndef SET_INEXACT if (bc.nd == nd) { #ifdef Avoid_Underflow if (!bc.scale) #endif if (y == z) { /* Can we stop now? */ L = (Long)aadj; aadj -= L; /* The tolerances below are conservative. */ if (bc.dsign || word1(&rv) || word0(&rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } else if (aadj < .4999999/FLT_RADIX) break; } } #endif cont: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(delta); } Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta); #ifndef NO_STRTOD_BIGCOMP if (req_bigcomp) { bd0 = 0; bc.e0 += nz1; bigcomp(&rv, s0, &bc); y = word0(&rv) & Exp_mask; if (y == Exp_mask) goto ovfl; if (y == 0 && rv.d == 0.) goto undfl; } #endif #ifdef SET_INEXACT if (bc.inexact) { if (!oldinexact) { word0(&rv0) = Exp_1 + (70 << Exp_shift); word1(&rv0) = 0; dval(&rv0) += 1.; } } else if (!oldinexact) clear_inexact(); #endif #ifdef Avoid_Underflow if (bc.scale) { word0(&rv0) = Exp_1 - 2*P*Exp_msk1; word1(&rv0) = 0; dval(&rv) *= dval(&rv0); #ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ #ifdef IEEE_Arith if (!(word0(&rv) & Exp_mask)) #else if (word0(&rv) == 0 && word1(&rv) == 0) #endif errno = ERANGE; #endif } #endif /* Avoid_Underflow */ #ifdef SET_INEXACT if (bc.inexact && !(word0(&rv) & Exp_mask)) { /* set underflow bit */ dval(&rv0) = 1e-300; dval(&rv0) *= dval(&rv0); } #endif ret: if (se) *se = (char *)s; return sign ? -dval(&rv) : dval(&rv); } #ifndef MULTIPLE_THREADS static char *dtoa_result; #endif static char * #ifdef KR_headers rv_alloc(i) int i; #else rv_alloc(int i) #endif { int j, k, *r; j = sizeof(ULong); for(k = 0; sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i; j <<= 1) k++; r = (int*)Balloc(k); *r = k; return #ifndef MULTIPLE_THREADS dtoa_result = #endif (char *)(r+1); } static char * #ifdef KR_headers nrv_alloc(s, rve, n) char *s, **rve; int n; #else nrv_alloc(const char *s, char **rve, int n) #endif { char *rv, *t; t = rv = rv_alloc(n); while((*t = *s++)) t++; if (rve) *rve = t; return rv; } /* freedtoa(s) must be used to free values s returned by dtoa * when MULTIPLE_THREADS is #defined. It should be used in all cases, * but for consistency with earlier versions of dtoa, it is optional * when MULTIPLE_THREADS is not defined. */ void #ifdef KR_headers freedtoa(s) char *s; #else freedtoa(char *s) #endif { Bigint *b = (Bigint *)((int *)s - 1); b->maxwds = 1 << (b->k = *(int*)b); Bfree(b); #ifndef MULTIPLE_THREADS if (s == dtoa_result) dtoa_result = 0; #endif } /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * * Inspired by "How to Print Floating-Point Numbers Accurately" by * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. * * Modifications: * 1. Rather than iterating, we use a simple numeric overestimate * to determine k = floor(log10(d)). We scale relevant * quantities using O(log2(k)) rather than O(k) multiplications. * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't * try to generate digits strictly left to right. Instead, we * compute with fewer bits and propagate the carry if necessary * when rounding the final digit up. This is often faster. * 3. Under the assumption that input will be rounded nearest, * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. * That is, we allow equality in stopping tests when the * round-nearest rule will give the same floating-point value * as would satisfaction of the stopping test with strict * inequality. * 4. We remove common factors of powers of 2 from relevant * quantities. * 5. When converting floating-point integers less than 1e16, * we use floating-point arithmetic rather than resorting * to multiple-precision integers. * 6. When asked to produce fewer than 15 digits, we first try * to get by with floating-point arithmetic; we resort to * multiple-precision integer arithmetic only if we cannot * guarantee that the floating-point calculation has given * the correctly rounded result. For k requested digits and * "uniformly" distributed input, the probability is * something like 10^(k-15) that we must resort to the Long * calculation. */ char * dtoa #ifdef KR_headers (dd, mode, ndigits, decpt, sign, rve) double dd; int mode, ndigits, *decpt, *sign; char **rve; #else (double dd, int mode, int ndigits, int *decpt, int *sign, char **rve) #endif { /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; trailing zeros are suppressed from the returned string. If not null, *rve is set to point to the end of the return value. If d is +-Infinity or NaN, then *decpt is set to 9999. mode: 0 ==> shortest string that yields d when read in and rounded to nearest. 1 ==> like 0, but with Steele & White stopping rule; e.g. with IEEE P754 arithmetic , mode 0 gives 1e23 whereas mode 1 gives 9.999999999999999e22. 2 ==> max(1,ndigits) significant digits. This gives a return value similar to that of ecvt, except that trailing zeros are suppressed. 3 ==> through ndigits past the decimal point. This gives a return value similar to that from fcvt, except that trailing zeros are suppressed, and ndigits can be negative. 4,5 ==> similar to 2 and 3, respectively, but (in round-nearest mode) with the tests of mode 0 to possibly return a shorter string that rounds to d. With IEEE arithmetic and compilation with -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same as modes 2 and 3 when FLT_ROUNDS != 1. 6-9 ==> Debugging modes similar to mode - 4: don't try fast floating-point estimate (if applicable). Values of mode other than 0-9 are treated as mode 0. Sufficient space is allocated to the return value to hold the suppressed trailing zeros. */ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, spec_case, try_quick; Long L; #ifndef Sudden_Underflow int denorm; ULong x; #endif Bigint *b, *b1, *delta, *mlo, *mhi, *S; U d2, eps, u; double ds; char *s, *s0; #ifndef No_leftright #ifdef IEEE_Arith U eps1; #endif #endif #ifdef SET_INEXACT int inexact, oldinexact; #endif #ifdef Honor_FLT_ROUNDS /*{*/ int Rounding; #ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ Rounding = Flt_Rounds; #else /*}{*/ Rounding = 1; switch(fegetround()) { case FE_TOWARDZERO: Rounding = 0; break; case FE_UPWARD: Rounding = 2; break; case FE_DOWNWARD: Rounding = 3; } #endif /*}}*/ #endif /*}*/ #ifndef MULTIPLE_THREADS if (dtoa_result) { freedtoa(dtoa_result); dtoa_result = 0; } #endif u.d = dd; if (word0(&u) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; word0(&u) &= ~Sign_bit; /* clear sign bit */ } else *sign = 0; #if defined(IEEE_Arith) + defined(VAX) #ifdef IEEE_Arith if ((word0(&u) & Exp_mask) == Exp_mask) #else if (word0(&u) == 0x8000) #endif { /* Infinity or NaN */ *decpt = 9999; #ifdef IEEE_Arith if (!word1(&u) && !(word0(&u) & 0xfffff)) return nrv_alloc("Infinity", rve, 8); #endif return nrv_alloc("NaN", rve, 3); } #endif #ifdef IBM dval(&u) += 0; /* normalize */ #endif if (!dval(&u)) { *decpt = 1; return nrv_alloc("0", rve, 1); } #ifdef SET_INEXACT try_quick = oldinexact = get_inexact(); inexact = 1; #endif #ifdef Honor_FLT_ROUNDS if (Rounding >= 2) { if (*sign) Rounding = Rounding == 2 ? 0 : 2; else if (Rounding != 2) Rounding = 0; } #endif b = d2b(&u, &be, &bbits); #ifdef Sudden_Underflow i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); #else if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) { #endif dval(&d2) = dval(&u); word0(&d2) &= Frac_mask1; word0(&d2) |= Exp_11; #ifdef IBM if (j = 11 - hi0bits(word0(&d2) & Frac_mask)) dval(&d2) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) * * This suggests computing an approximation k to log10(d) by * * k = (i - Bias)*0.301029995663981 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); * * We want k to be too large rather than too small. * The error in the first-order Taylor series approximation * is in our favor, so we just round up the constant enough * to compensate for any error in the multiplication of * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, * adding 1e-13 to the constant term more than suffices. * Hence we adjust the constant term to 0.1760912590558. * (We could get a more accurate k by invoking log10, * but this is probably not worthwhile.) */ i -= Bias; #ifdef IBM i <<= 2; i += j; #endif #ifndef Sudden_Underflow denorm = 0; } else { /* d is denormalized */ i = bbits + be + (Bias + (P-1) - 1); x = i > 32 ? word0(&u) << (64 - i) | word1(&u) >> (i - 32) : word1(&u) << (32 - i); dval(&d2) = x; word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ i -= (Bias + (P-1) - 1) + 1; denorm = 1; } #endif ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; k = (int)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { if (dval(&u) < tens[k]) k--; k_check = 0; } j = bbits - i - 1; if (j >= 0) { b2 = 0; s2 = j; } else { b2 = -j; s2 = 0; } if (k >= 0) { b5 = 0; s5 = k; s2 += k; } else { b2 -= k; b5 = -k; s5 = 0; } if (mode < 0 || mode > 9) mode = 0; #ifndef SET_INEXACT #ifdef Check_FLT_ROUNDS try_quick = Rounding == 1; #else try_quick = 1; #endif #endif /*SET_INEXACT*/ if (mode > 5) { mode -= 4; try_quick = 0; } leftright = 1; ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ /* silence erroneous "gcc -Wall" warning. */ switch(mode) { case 0: case 1: i = 18; ndigits = 0; break; case 2: leftright = 0; /* no break */ case 4: if (ndigits <= 0) ndigits = 1; ilim = ilim1 = i = ndigits; break; case 3: leftright = 0; /* no break */ case 5: i = ndigits + k + 1; ilim = i; ilim1 = i - 1; if (i <= 0) i = 1; } s = s0 = rv_alloc(i); #ifdef Honor_FLT_ROUNDS if (mode > 1 && Rounding != 1) leftright = 0; #endif if (ilim >= 0 && ilim <= Quick_max && try_quick) { /* Try to get by with floating-point arithmetic. */ i = 0; dval(&d2) = dval(&u); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ if (k > 0) { ds = tens[k&0xf]; j = k >> 4; if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; dval(&u) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) if (j & 1) { ieps++; ds *= bigtens[i]; } dval(&u) /= ds; } else if ((j1 = -k)) { dval(&u) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; dval(&u) *= bigtens[i]; } } if (k_check && dval(&u) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; dval(&u) *= 10.; ieps++; } dval(&eps) = ieps*dval(&u) + 7.; word0(&eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; dval(&u) -= 5.; if (dval(&u) > dval(&eps)) goto one_digit; if (dval(&u) < -dval(&eps)) goto no_digits; goto fast_failed; } #ifndef No_leftright if (leftright) { /* Use Steele & White method of only * generating digits needed. */ dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); #ifdef IEEE_Arith if (k0 < 0 && j1 >= 307) { eps1.d = 1.01e256; /* 1.01 allows roundoff in the next few lines */ word0(&eps1) -= Exp_msk1 * (Bias+P-1); dval(&eps1) *= tens[j1 & 0xf]; for(i = 0, j = (j1-256) >> 4; j; j >>= 1, i++) if (j & 1) dval(&eps1) *= bigtens[i]; if (eps.d < eps1.d) eps.d = eps1.d; } #endif for(i = 0;;) { L = dval(&u); dval(&u) -= L; *s++ = '0' + (int)L; if (1. - dval(&u) < dval(&eps)) goto bump_up; if (dval(&u) < dval(&eps)) goto ret1; if (++i >= ilim) break; dval(&eps) *= 10.; dval(&u) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ dval(&eps) *= tens[ilim-1]; for(i = 1;; i++, dval(&u) *= 10.) { L = (Long)(dval(&u)); if (!(dval(&u) -= L)) ilim = i; *s++ = '0' + (int)L; if (i == ilim) { if (dval(&u) > 0.5 + dval(&eps)) goto bump_up; else if (dval(&u) < 0.5 - dval(&eps)) { while(*--s == '0'); s++; goto ret1; } break; } } #ifndef No_leftright } #endif fast_failed: s = s0; dval(&u) = dval(&d2); k = k0; ilim = ilim0; } /* Do we have a "small" integer? */ if (be >= 0 && k <= Int_max) { /* Yes. */ ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; if (ilim < 0 || dval(&u) <= 5*ds) goto no_digits; goto one_digit; } for(i = 1;; i++, dval(&u) *= 10.) { L = (Long)(dval(&u) / ds); dval(&u) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ if (dval(&u) < 0) { L--; dval(&u) += ds; } #endif *s++ = '0' + (int)L; if (!dval(&u)) { #ifdef SET_INEXACT inexact = 0; #endif break; } if (i == ilim) { #ifdef Honor_FLT_ROUNDS if (mode > 1) switch(Rounding) { case 0: goto ret1; case 2: goto bump_up; } #endif dval(&u) += dval(&u); #ifdef ROUND_BIASED if (dval(&u) >= ds) #else if (dval(&u) > ds || (dval(&u) == ds && L & 1)) #endif { bump_up: while(*--s == '9') if (s == s0) { k++; *s = '0'; break; } ++*s++; } break; } } goto ret1; } m2 = b2; m5 = b5; mhi = mlo = 0; if (leftright) { i = #ifndef Sudden_Underflow denorm ? be + (Bias + (P-1) - 1 + 1) : #endif #ifdef IBM 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); #else 1 + P - bbits; #endif b2 += i; s2 += i; mhi = i2b(1); } if (m2 > 0 && s2 > 0) { i = m2 < s2 ? m2 : s2; b2 -= i; m2 -= i; s2 -= i; } if (b5 > 0) { if (leftright) { if (m5 > 0) { mhi = pow5mult(mhi, m5); b1 = mult(mhi, b); Bfree(b); b = b1; } if ((j = b5 - m5)) b = pow5mult(b, j); } else b = pow5mult(b, b5); } S = i2b(1); if (s5 > 0) S = pow5mult(S, s5); /* Check for special case that d is a normalized power of 2. */ spec_case = 0; if ((mode < 2 || leftright) #ifdef Honor_FLT_ROUNDS && Rounding == 1 #endif ) { if (!word1(&u) && !(word0(&u) & Bndry_mask) #ifndef Sudden_Underflow && word0(&u) & (Exp_mask & ~Exp_msk1) #endif ) { /* The special case */ b2 += Log2P; s2 += Log2P; spec_case = 1; } } /* Arrange for convenient computation of quotients: * shift left if necessary so divisor has 4 leading 0 bits. * * Perhaps we should just compute leading 28 bits of S once * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ i = dshift(S, s2); b2 += i; m2 += i; s2 += i; if (b2 > 0) b = lshift(b, b2); if (s2 > 0) S = lshift(S, s2); if (k_check) { if (cmp(b,S) < 0) { k--; b = multadd(b, 10, 0); /* we botched the k estimate */ if (leftright) mhi = multadd(mhi, 10, 0); ilim = ilim1; } } if (ilim <= 0 && (mode == 3 || mode == 5)) { if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { /* no digits, fcvt style */ no_digits: k = -1 - ndigits; goto ret; } one_digit: *s++ = '1'; k++; goto ret; } if (leftright) { if (m2 > 0) mhi = lshift(mhi, m2); /* Compute mlo -- check for special case * that d is a normalized power of 2. */ mlo = mhi; if (spec_case) { mhi = Balloc(mhi->k); Bcopy(mhi, mlo); mhi = lshift(mhi, Log2P); } for(i = 1;;i++) { dig = quorem(b,S) + '0'; /* Do we yet have the shortest decimal string * that will round to d? */ j = cmp(b, mlo); delta = diff(S, mhi); j1 = delta->sign ? 1 : cmp(b, delta); Bfree(delta); #ifndef ROUND_BIASED if (j1 == 0 && mode != 1 && !(word1(&u) & 1) #ifdef Honor_FLT_ROUNDS && Rounding >= 1 #endif ) { if (dig == '9') goto round_9_up; if (j > 0) dig++; #ifdef SET_INEXACT else if (!b->x[0] && b->wds <= 1) inexact = 0; #endif *s++ = dig; goto ret; } #endif if (j < 0 || (j == 0 && mode != 1 #ifndef ROUND_BIASED && !(word1(&u) & 1) #endif )) { if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto accept_dig; } #ifdef Honor_FLT_ROUNDS if (mode > 1) switch(Rounding) { case 0: goto accept_dig; case 2: goto keep_dig; } #endif /*Honor_FLT_ROUNDS*/ if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); #ifdef ROUND_BIASED if (j1 >= 0 /*)*/ #else if ((j1 > 0 || (j1 == 0 && dig & 1)) #endif && dig++ == '9') goto round_9_up; } accept_dig: *s++ = dig; goto ret; } if (j1 > 0) { #ifdef Honor_FLT_ROUNDS if (!Rounding) goto accept_dig; #endif if (dig == '9') { /* possible if i == 1 */ round_9_up: *s++ = '9'; goto roundoff; } *s++ = dig + 1; goto ret; } #ifdef Honor_FLT_ROUNDS keep_dig: #endif *s++ = dig; if (i == ilim) break; b = multadd(b, 10, 0); if (mlo == mhi) mlo = mhi = multadd(mhi, 10, 0); else { mlo = multadd(mlo, 10, 0); mhi = multadd(mhi, 10, 0); } } } else for(i = 1;; i++) { *s++ = dig = quorem(b,S) + '0'; if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto ret; } if (i >= ilim) break; b = multadd(b, 10, 0); } /* Round off last digit */ #ifdef Honor_FLT_ROUNDS switch(Rounding) { case 0: goto trimzeros; case 2: goto roundoff; } #endif b = lshift(b, 1); j = cmp(b, S); #ifdef ROUND_BIASED if (j >= 0) #else if (j > 0 || (j == 0 && dig & 1)) #endif { roundoff: while(*--s == '9') if (s == s0) { k++; *s++ = '1'; goto ret; } ++*s++; } else { #ifdef Honor_FLT_ROUNDS trimzeros: #endif while(*--s == '0'); s++; } ret: Bfree(S); if (mhi) { if (mlo && mlo != mhi) Bfree(mlo); Bfree(mhi); } ret1: #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { word0(&u) = Exp_1 + (70 << Exp_shift); word1(&u) = 0; dval(&u) += 1.; } } else if (!oldinexact) clear_inexact(); #endif Bfree(b); *s = 0; *decpt = k + 1; if (rve) *rve = s; return s0; } #ifdef __cplusplus } #endif nspr-4.11/nspr/pr/src/misc/pralarm.c0000644000000000000000000002053412623070344015503 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /**********************************************************************/ /******************************* PRALARM ******************************/ /**********************************************************************/ #include "obsolete/pralarm.h" struct PRAlarmID { /* typedef'd in pralarm.h */ PRCList list; /* circular list linkage */ PRAlarm *alarm; /* back pointer to owning alarm */ PRPeriodicAlarmFn function; /* function to call for notify */ void *clientData; /* opaque client context */ PRIntervalTime period; /* the client defined period */ PRUint32 rate; /* rate of notification */ PRUint32 accumulator; /* keeps track of # notifies */ PRIntervalTime epoch; /* when timer was started */ PRIntervalTime nextNotify; /* when we'll next do our thing */ PRIntervalTime lastNotify; /* when we last did our thing */ }; typedef enum {alarm_active, alarm_inactive} _AlarmState; struct PRAlarm { /* typedef'd in pralarm.h */ PRCList timers; /* base of alarm ids list */ PRLock *lock; /* lock used to protect data */ PRCondVar *cond; /* condition that used to wait */ PRThread *notifier; /* thread to deliver notifies */ PRAlarmID *current; /* current alarm being served */ _AlarmState state; /* used to delete the alarm */ }; static PRAlarmID *pr_getNextAlarm(PRAlarm *alarm, PRAlarmID *id) { /* * Puts 'id' back into the sorted list iff it's not NULL. * Removes the first element from the list and returns it (or NULL). * List is "assumed" to be short. * * NB: Caller is providing locking */ PRCList *timer; PRAlarmID *result = id; PRIntervalTime now = PR_IntervalNow(); if (!PR_CLIST_IS_EMPTY(&alarm->timers)) { if (id != NULL) /* have to put this id back in */ { PRIntervalTime idDelta = now - id->nextNotify; timer = alarm->timers.next; do { result = (PRAlarmID*)timer; if ((PRIntervalTime)(now - result->nextNotify) > idDelta) { PR_INSERT_BEFORE(&id->list, &alarm->timers); break; } timer = timer->next; } while (timer != &alarm->timers); } result = (PRAlarmID*)(timer = PR_LIST_HEAD(&alarm->timers)); PR_REMOVE_LINK(timer); /* remove it from the list */ } return result; } /* pr_getNextAlarm */ static PRIntervalTime pr_PredictNextNotifyTime(PRAlarmID *id) { PRIntervalTime delta; PRFloat64 baseRate = (PRFloat64)id->period / (PRFloat64)id->rate; PRFloat64 offsetFromEpoch = (PRFloat64)id->accumulator * baseRate; id->accumulator += 1; /* every call advances to next period */ id->lastNotify = id->nextNotify; /* just keeping track of things */ id->nextNotify = (PRIntervalTime)(offsetFromEpoch + 0.5); delta = id->nextNotify - id->lastNotify; return delta; } /* pr_PredictNextNotifyTime */ static void PR_CALLBACK pr_alarmNotifier(void *arg) { /* * This is the root of the notifier thread. There is one such thread * for each PRAlarm. It may service an arbitrary (though assumed to be * small) number of alarms using the same thread and structure. It * continues to run until the alarm is destroyed. */ PRAlarmID *id = NULL; PRAlarm *alarm = (PRAlarm*)arg; enum {notify, abort, scan} why = scan; while (why != abort) { PRIntervalTime pause; PR_Lock(alarm->lock); while (why == scan) { alarm->current = NULL; /* reset current id */ if (alarm->state == alarm_inactive) why = abort; /* we're toast */ else if (why == scan) /* the dominant case */ { id = pr_getNextAlarm(alarm, id); /* even if it's the same */ if (id == NULL) /* there are no alarms set */ (void)PR_WaitCondVar(alarm->cond, PR_INTERVAL_NO_TIMEOUT); else { pause = id->nextNotify - (PR_IntervalNow() - id->epoch); if ((PRInt32)pause <= 0) /* is this one's time up? */ { why = notify; /* set up to do our thing */ alarm->current = id; /* id we're about to schedule */ } else (void)PR_WaitCondVar(alarm->cond, pause); /* dally */ } } } PR_Unlock(alarm->lock); if (why == notify) { (void)pr_PredictNextNotifyTime(id); if (!id->function(id, id->clientData, ~pause)) { /* * Notified function decided not to continue. Free * the alarm id to make sure it doesn't get back on * the list. */ PR_DELETE(id); /* free notifier object */ id = NULL; /* so it doesn't get back into the list */ } why = scan; /* so we can cycle through the loop again */ } } } /* pr_alarm_notifier */ PR_IMPLEMENT(PRAlarm*) PR_CreateAlarm(void) { PRAlarm *alarm = PR_NEWZAP(PRAlarm); if (alarm != NULL) { if ((alarm->lock = PR_NewLock()) == NULL) goto done; if ((alarm->cond = PR_NewCondVar(alarm->lock)) == NULL) goto done; alarm->state = alarm_active; PR_INIT_CLIST(&alarm->timers); alarm->notifier = PR_CreateThread( PR_USER_THREAD, pr_alarmNotifier, alarm, PR_GetThreadPriority(PR_GetCurrentThread()), PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (alarm->notifier == NULL) goto done; } return alarm; done: if (alarm->cond != NULL) PR_DestroyCondVar(alarm->cond); if (alarm->lock != NULL) PR_DestroyLock(alarm->lock); PR_DELETE(alarm); return NULL; } /* CreateAlarm */ PR_IMPLEMENT(PRStatus) PR_DestroyAlarm(PRAlarm *alarm) { PRStatus rv; PR_Lock(alarm->lock); alarm->state = alarm_inactive; rv = PR_NotifyCondVar(alarm->cond); PR_Unlock(alarm->lock); if (rv == PR_SUCCESS) rv = PR_JoinThread(alarm->notifier); if (rv == PR_SUCCESS) { PR_DestroyCondVar(alarm->cond); PR_DestroyLock(alarm->lock); PR_DELETE(alarm); } return rv; } /* PR_DestroyAlarm */ PR_IMPLEMENT(PRAlarmID*) PR_SetAlarm( PRAlarm *alarm, PRIntervalTime period, PRUint32 rate, PRPeriodicAlarmFn function, void *clientData) { /* * Create a new periodic alarm an existing current structure. * Set up the context and compute the first notify time (immediate). * Link the new ID into the head of the list (since it's notifying * immediately). */ PRAlarmID *id = PR_NEWZAP(PRAlarmID); if (!id) return NULL; id->alarm = alarm; PR_INIT_CLIST(&id->list); id->function = function; id->clientData = clientData; id->period = period; id->rate = rate; id->epoch = id->nextNotify = PR_IntervalNow(); (void)pr_PredictNextNotifyTime(id); PR_Lock(alarm->lock); PR_INSERT_BEFORE(&id->list, &alarm->timers); PR_NotifyCondVar(alarm->cond); PR_Unlock(alarm->lock); return id; } /* PR_SetAlarm */ PR_IMPLEMENT(PRStatus) PR_ResetAlarm( PRAlarmID *id, PRIntervalTime period, PRUint32 rate) { /* * Can only be called from within the notify routine. Doesn't * need locking because it can only be called from within the * notify routine. */ if (id != id->alarm->current) return PR_FAILURE; id->period = period; id->rate = rate; id->accumulator = 1; id->epoch = PR_IntervalNow(); (void)pr_PredictNextNotifyTime(id); return PR_SUCCESS; } /* PR_ResetAlarm */ nspr-4.11/nspr/pr/src/misc/pratom.c0000644000000000000000000002142312623070344015345 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** PR Atomic operations */ #include "pratom.h" #include "primpl.h" #include /* * The following is a fallback implementation that emulates * atomic operations for platforms without atomic operations. * If a platform has atomic operations, it should define the * macro _PR_HAVE_ATOMIC_OPS, and the following will not be * compiled in. */ #if !defined(_PR_HAVE_ATOMIC_OPS) #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) /* * PR_AtomicDecrement() is used in NSPR's thread-specific data * destructor. Because thread-specific data destructors may be * invoked after a PR_Cleanup() call, we need an implementation * of the atomic routines that doesn't need NSPR to be initialized. */ /* * We use a set of locks for all the emulated atomic operations. * By hashing on the address of the integer to be locked the * contention between multiple threads should be lessened. * * The number of atomic locks can be set by the environment variable * NSPR_ATOMIC_HASH_LOCKS */ /* * lock counts should be a power of 2 */ #define DEFAULT_ATOMIC_LOCKS 16 /* should be in sync with the number of initializers below */ #define MAX_ATOMIC_LOCKS (4 * 1024) static pthread_mutex_t static_atomic_locks[DEFAULT_ATOMIC_LOCKS] = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }; #ifdef DEBUG static PRInt32 static_hash_lock_counts[DEFAULT_ATOMIC_LOCKS]; static PRInt32 *hash_lock_counts = static_hash_lock_counts; #endif static PRUint32 num_atomic_locks = DEFAULT_ATOMIC_LOCKS; static pthread_mutex_t *atomic_locks = static_atomic_locks; static PRUint32 atomic_hash_mask = DEFAULT_ATOMIC_LOCKS - 1; #define _PR_HASH_FOR_LOCK(ptr) \ ((PRUint32) (((PRUptrdiff) (ptr) >> 2) ^ \ ((PRUptrdiff) (ptr) >> 8)) & \ atomic_hash_mask) void _PR_MD_INIT_ATOMIC() { char *eval; int index; PR_ASSERT(PR_FloorLog2(MAX_ATOMIC_LOCKS) == PR_CeilingLog2(MAX_ATOMIC_LOCKS)); PR_ASSERT(PR_FloorLog2(DEFAULT_ATOMIC_LOCKS) == PR_CeilingLog2(DEFAULT_ATOMIC_LOCKS)); if (((eval = getenv("NSPR_ATOMIC_HASH_LOCKS")) != NULL) && ((num_atomic_locks = atoi(eval)) != DEFAULT_ATOMIC_LOCKS)) { if (num_atomic_locks > MAX_ATOMIC_LOCKS) num_atomic_locks = MAX_ATOMIC_LOCKS; else if (num_atomic_locks < 1) num_atomic_locks = 1; else { num_atomic_locks = PR_FloorLog2(num_atomic_locks); num_atomic_locks = 1L << num_atomic_locks; } atomic_locks = (pthread_mutex_t *) PR_Malloc(sizeof(pthread_mutex_t) * num_atomic_locks); if (atomic_locks) { for (index = 0; index < num_atomic_locks; index++) { if (pthread_mutex_init(&atomic_locks[index], NULL)) { PR_DELETE(atomic_locks); atomic_locks = NULL; break; } } } #ifdef DEBUG if (atomic_locks) { hash_lock_counts = PR_CALLOC(num_atomic_locks * sizeof(PRInt32)); if (hash_lock_counts == NULL) { PR_DELETE(atomic_locks); atomic_locks = NULL; } } #endif if (atomic_locks == NULL) { /* * Use statically allocated locks */ atomic_locks = static_atomic_locks; num_atomic_locks = DEFAULT_ATOMIC_LOCKS; #ifdef DEBUG hash_lock_counts = static_hash_lock_counts; #endif } atomic_hash_mask = num_atomic_locks - 1; } PR_ASSERT(PR_FloorLog2(num_atomic_locks) == PR_CeilingLog2(num_atomic_locks)); } PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val) { PRInt32 rv; PRInt32 idx = _PR_HASH_FOR_LOCK(val); pthread_mutex_lock(&atomic_locks[idx]); rv = ++(*val); #ifdef DEBUG hash_lock_counts[idx]++; #endif pthread_mutex_unlock(&atomic_locks[idx]); return rv; } PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) { PRInt32 rv; PRInt32 idx = _PR_HASH_FOR_LOCK(ptr); pthread_mutex_lock(&atomic_locks[idx]); rv = ((*ptr) += val); #ifdef DEBUG hash_lock_counts[idx]++; #endif pthread_mutex_unlock(&atomic_locks[idx]); return rv; } PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) { PRInt32 rv; PRInt32 idx = _PR_HASH_FOR_LOCK(val); pthread_mutex_lock(&atomic_locks[idx]); rv = --(*val); #ifdef DEBUG hash_lock_counts[idx]++; #endif pthread_mutex_unlock(&atomic_locks[idx]); return rv; } PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) { PRInt32 rv; PRInt32 idx = _PR_HASH_FOR_LOCK(val); pthread_mutex_lock(&atomic_locks[idx]); rv = *val; *val = newval; #ifdef DEBUG hash_lock_counts[idx]++; #endif pthread_mutex_unlock(&atomic_locks[idx]); return rv; } #else /* _PR_PTHREADS && !_PR_DCETHREADS */ /* * We use a single lock for all the emulated atomic operations. * The lock contention should be acceptable. */ static PRLock *atomic_lock = NULL; void _PR_MD_INIT_ATOMIC(void) { if (atomic_lock == NULL) { atomic_lock = PR_NewLock(); } } PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val) { PRInt32 rv; if (!_pr_initialized) { _PR_ImplicitInitialization(); } PR_Lock(atomic_lock); rv = ++(*val); PR_Unlock(atomic_lock); return rv; } PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *ptr, PRInt32 val) { PRInt32 rv; if (!_pr_initialized) { _PR_ImplicitInitialization(); } PR_Lock(atomic_lock); rv = ((*ptr) += val); PR_Unlock(atomic_lock); return rv; } PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) { PRInt32 rv; if (!_pr_initialized) { _PR_ImplicitInitialization(); } PR_Lock(atomic_lock); rv = --(*val); PR_Unlock(atomic_lock); return rv; } PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval) { PRInt32 rv; if (!_pr_initialized) { _PR_ImplicitInitialization(); } PR_Lock(atomic_lock); rv = *val; *val = newval; PR_Unlock(atomic_lock); return rv; } #endif /* _PR_PTHREADS && !_PR_DCETHREADS */ #endif /* !_PR_HAVE_ATOMIC_OPS */ void _PR_InitAtomic(void) { _PR_MD_INIT_ATOMIC(); } PR_IMPLEMENT(PRInt32) PR_AtomicIncrement(PRInt32 *val) { return _PR_MD_ATOMIC_INCREMENT(val); } PR_IMPLEMENT(PRInt32) PR_AtomicDecrement(PRInt32 *val) { return _PR_MD_ATOMIC_DECREMENT(val); } PR_IMPLEMENT(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval) { return _PR_MD_ATOMIC_SET(val, newval); } PR_IMPLEMENT(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val) { return _PR_MD_ATOMIC_ADD(ptr, val); } /* * For platforms, which don't support the CAS (compare-and-swap) instruction * (or an equivalent), the stack operations are implemented by use of PRLock */ PR_IMPLEMENT(PRStack *) PR_CreateStack(const char *stack_name) { PRStack *stack; if (!_pr_initialized) { _PR_ImplicitInitialization(); } if ((stack = PR_NEW(PRStack)) == NULL) { return NULL; } if (stack_name) { stack->prstk_name = (char *) PR_Malloc(strlen(stack_name) + 1); if (stack->prstk_name == NULL) { PR_DELETE(stack); return NULL; } strcpy(stack->prstk_name, stack_name); } else stack->prstk_name = NULL; #ifndef _PR_HAVE_ATOMIC_CAS stack->prstk_lock = PR_NewLock(); if (stack->prstk_lock == NULL) { PR_Free(stack->prstk_name); PR_DELETE(stack); return NULL; } #endif /* !_PR_HAVE_ATOMIC_CAS */ stack->prstk_head.prstk_elem_next = NULL; return stack; } PR_IMPLEMENT(PRStatus) PR_DestroyStack(PRStack *stack) { if (stack->prstk_head.prstk_elem_next != NULL) { PR_SetError(PR_INVALID_STATE_ERROR, 0); return PR_FAILURE; } if (stack->prstk_name) PR_Free(stack->prstk_name); #ifndef _PR_HAVE_ATOMIC_CAS PR_DestroyLock(stack->prstk_lock); #endif /* !_PR_HAVE_ATOMIC_CAS */ PR_DELETE(stack); return PR_SUCCESS; } #ifndef _PR_HAVE_ATOMIC_CAS PR_IMPLEMENT(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem) { PR_Lock(stack->prstk_lock); stack_elem->prstk_elem_next = stack->prstk_head.prstk_elem_next; stack->prstk_head.prstk_elem_next = stack_elem; PR_Unlock(stack->prstk_lock); return; } PR_IMPLEMENT(PRStackElem *) PR_StackPop(PRStack *stack) { PRStackElem *element; PR_Lock(stack->prstk_lock); element = stack->prstk_head.prstk_elem_next; if (element != NULL) { stack->prstk_head.prstk_elem_next = element->prstk_elem_next; element->prstk_elem_next = NULL; /* debugging aid */ } PR_Unlock(stack->prstk_lock); return element; } #endif /* !_PR_HAVE_ATOMIC_CAS */ nspr-4.11/nspr/pr/src/misc/praton.c0000644000000000000000000001675712623070344015364 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /******************************************************************************* * The following function pr_inet_aton is based on the BSD function inet_aton * with some modifications. The license and copyright notices applying to this * function appear below. Modifications are also according to the license below. ******************************************************************************/ #include "prnetdb.h" /* * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #define XX 127 static const unsigned char index_hex[256] = { XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,XX,XX, XX,XX,XX,XX, XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, }; static PRBool _isdigit(char c) { return c >= '0' && c <= '9'; } static PRBool _isxdigit(char c) { return index_hex[(unsigned char) c] != XX; } static PRBool _isspace(char c) { return c == ' ' || (c >= '\t' && c <= '\r'); } #undef XX int pr_inet_aton(const char *cp, PRUint32 *addr) { PRUint32 val; int base, n; char c; PRUint8 parts[4]; PRUint8 *pp = parts; int digit; c = *cp; for (;;) { /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ if (!_isdigit(c)) return (0); val = 0; base = 10; digit = 0; if (c == '0') { c = *++cp; if (c == 'x' || c == 'X') base = 16, c = *++cp; else { base = 8; digit = 1; } } for (;;) { if (_isdigit(c)) { if (base == 8 && (c == '8' || c == '9')) return (0); val = (val * base) + (c - '0'); c = *++cp; digit = 1; } else if (base == 16 && _isxdigit(c)) { val = (val << 4) + index_hex[(unsigned char) c]; c = *++cp; digit = 1; } else break; } if (c == '.') { /* * Internet format: * a.b.c.d * a.b.c (with c treated as 16 bits) * a.b (with b treated as 24 bits) */ if (pp >= parts + 3 || val > 0xffU) return (0); *pp++ = val; c = *++cp; } else break; } /* * Check for trailing characters. */ if (c != '\0' && !_isspace(c)) return (0); /* * Did we get a valid digit? */ if (!digit) return (0); /* * Concoct the address according to * the number of parts specified. */ n = pp - parts + 1; switch (n) { case 1: /*%< a -- 32 bits */ break; case 2: /*%< a.b -- 8.24 bits */ if (val > 0xffffffU) return (0); val |= parts[0] << 24; break; case 3: /*%< a.b.c -- 8.8.16 bits */ if (val > 0xffffU) return (0); val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /*%< a.b.c.d -- 8.8.8.8 bits */ if (val > 0xffU) return (0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } *addr = PR_htonl(val); return (1); } nspr-4.11/nspr/pr/src/misc/prcountr.c0000644000000000000000000002635612623070344015731 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prcountr.c -- NSPR Instrumentation Counters ** ** Implement the interface defined in prcountr.h ** ** Design Notes: ** ** The Counter Facility (CF) has a single anchor: qNameList. ** The anchor is a PRCList. qNameList is a list of links in QName ** structures. From qNameList any QName structure and its ** associated RName structure can be located. ** ** For each QName, a list of RName structures is anchored at ** rnLink in the QName structure. ** ** The counter itself is embedded in the RName structure. ** ** For manipulating the counter database, single lock is used to ** protect the entire list: counterLock. ** ** A PRCounterHandle, defined in prcountr.h, is really a pointer ** to a RName structure. References by PRCounterHandle are ** dead-reconed to the RName structure. The PRCounterHandle is ** "overloaded" for traversing the QName structures; only the ** function PR_FindNextQnameHandle() uses this overloading. ** ** ** ToDo (lth): decide on how to lock or atomically update ** individual counters. Candidates are: the global lock; a lock ** per RName structure; Atomic operations (Note that there are ** not adaquate atomic operations (yet) to achieve this goal). At ** this writing (6/19/98) , the update of the counter variable in ** a QName structure is unprotected. ** */ #include "prcountr.h" #include "prclist.h" #include "prlock.h" #include "prlog.h" #include "prmem.h" #include /* ** */ typedef struct QName { PRCList link; PRCList rNameList; char name[PRCOUNTER_NAME_MAX+1]; } QName; /* ** */ typedef struct RName { PRCList link; QName *qName; PRLock *lock; volatile PRUint32 counter; char name[PRCOUNTER_NAME_MAX+1]; char desc[PRCOUNTER_DESC_MAX+1]; } RName; /* ** Define the Counter Facility database */ static PRLock *counterLock; static PRCList qNameList; static PRLogModuleInfo *lm; /* ** _PR_CounterInitialize() -- Initialize the Counter Facility ** */ static void _PR_CounterInitialize( void ) { /* ** This function should be called only once */ PR_ASSERT( counterLock == NULL ); counterLock = PR_NewLock(); PR_INIT_CLIST( &qNameList ); lm = PR_NewLogModule("counters"); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Initialization complete")); return; } /* end _PR_CounterInitialize() */ /* ** PR_CreateCounter() -- Create a counter ** ** ValidateArguments ** Lock ** if (qName not already in database) ** NewQname ** if (rName already in database ) ** Assert ** else NewRname ** NewCounter ** link 'em up ** Unlock ** */ PR_IMPLEMENT(PRCounterHandle) PR_CreateCounter( const char *qName, const char *rName, const char *description ) { QName *qnp; RName *rnp; PRBool matchQname = PR_FALSE; /* Self initialize, if necessary */ if ( counterLock == NULL ) _PR_CounterInitialize(); /* Validate input arguments */ PR_ASSERT( strlen(qName) <= PRCOUNTER_NAME_MAX ); PR_ASSERT( strlen(rName) <= PRCOUNTER_NAME_MAX ); PR_ASSERT( strlen(description) <= PRCOUNTER_DESC_MAX ); /* Lock the Facility */ PR_Lock( counterLock ); /* Do we already have a matching QName? */ if (!PR_CLIST_IS_EMPTY( &qNameList )) { qnp = (QName *) PR_LIST_HEAD( &qNameList ); do { if ( strcmp(qnp->name, qName) == 0) { matchQname = PR_TRUE; break; } qnp = (QName *)PR_NEXT_LINK( &qnp->link ); } while( qnp != (QName *)&qNameList ); } /* ** If we did not find a matching QName, ** allocate one and initialize it. ** link it onto the qNameList. ** */ if ( matchQname != PR_TRUE ) { qnp = PR_NEWZAP( QName ); PR_ASSERT( qnp != NULL ); PR_INIT_CLIST( &qnp->link ); PR_INIT_CLIST( &qnp->rNameList ); strcpy( qnp->name, qName ); PR_APPEND_LINK( &qnp->link, &qNameList ); } /* Do we already have a matching RName? */ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList )) { rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList ); do { /* ** No duplicate RNames are allowed within a QName ** */ PR_ASSERT( strcmp(rnp->name, rName)); rnp = (RName *)PR_NEXT_LINK( &rnp->link ); } while( rnp != (RName *)&qnp->rNameList ); } /* Get a new RName structure; initialize its members */ rnp = PR_NEWZAP( RName ); PR_ASSERT( rnp != NULL ); PR_INIT_CLIST( &rnp->link ); strcpy( rnp->name, rName ); strcpy( rnp->desc, description ); rnp->lock = PR_NewLock(); if ( rnp->lock == NULL ) { PR_ASSERT(0); } PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */ rnp->qName = qnp; /* point the RName to the QName */ /* Unlock the Facility */ PR_Unlock( counterLock ); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Create: QName: %s %p, RName: %s %p\n\t", qName, qnp, rName, rnp )); return((PRCounterHandle)rnp); } /* end PR_CreateCounter() */ /* ** */ PR_IMPLEMENT(void) PR_DestroyCounter( PRCounterHandle handle ) { RName *rnp = (RName *)handle; QName *qnp = rnp->qName; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting: QName: %s, RName: %s", qnp->name, rnp->name)); /* Lock the Facility */ PR_Lock( counterLock ); /* ** Remove RName from the list of RNames in QName ** and free RName */ PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting RName: %s, %p", rnp->name, rnp)); PR_REMOVE_LINK( &rnp->link ); PR_Free( rnp->lock ); PR_DELETE( rnp ); /* ** If this is the last RName within QName ** remove QName from the qNameList and free it */ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) ) { PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Deleting unused QName: %s, %p", qnp->name, qnp)); PR_REMOVE_LINK( &qnp->link ); PR_DELETE( qnp ); } /* Unlock the Facility */ PR_Unlock( counterLock ); return; } /* end PR_DestroyCounter() */ /* ** */ PR_IMPLEMENT(PRCounterHandle) PR_GetCounterHandleFromName( const char *qName, const char *rName ) { const char *qn, *rn, *desc; PRCounterHandle qh, rh = NULL; RName *rnp = NULL; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounterHandleFromName:\n\t" "QName: %s, RName: %s", qName, rName )); qh = PR_FindNextCounterQname( NULL ); while (qh != NULL) { rh = PR_FindNextCounterRname( NULL, qh ); while ( rh != NULL ) { PR_GetCounterNameFromHandle( rh, &qn, &rn, &desc ); if ( (strcmp( qName, qn ) == 0) && (strcmp( rName, rn ) == 0 )) { rnp = (RName *)rh; goto foundIt; } rh = PR_FindNextCounterRname( rh, qh ); } qh = PR_FindNextCounterQname( NULL ); } foundIt: PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp )); return(rh); } /* end PR_GetCounterHandleFromName() */ /* ** */ PR_IMPLEMENT(void) PR_GetCounterNameFromHandle( PRCounterHandle handle, const char **qName, const char **rName, const char **description ) { RName *rnp = (RName *)handle; QName *qnp = rnp->qName; *qName = qnp->name; *rName = rnp->name; *description = rnp->desc; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterNameFromHandle: " "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s", qnp, rnp, qnp->name, rnp->name, rnp->desc )); return; } /* end PR_GetCounterNameFromHandle() */ /* ** */ PR_IMPLEMENT(void) PR_IncrementCounter( PRCounterHandle handle ) { PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter++; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Increment: %p, %ld", handle, ((RName *)handle)->counter )); return; } /* end PR_IncrementCounter() */ /* ** */ PR_IMPLEMENT(void) PR_DecrementCounter( PRCounterHandle handle ) { PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter--; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: Decrement: %p, %ld", handle, ((RName *)handle)->counter )); return; } /* end PR_DecrementCounter() */ /* ** */ PR_IMPLEMENT(void) PR_AddToCounter( PRCounterHandle handle, PRUint32 value ) { PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter += value; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: AddToCounter: %p, %ld", handle, ((RName *)handle)->counter )); return; } /* end PR_AddToCounter() */ /* ** */ PR_IMPLEMENT(void) PR_SubtractFromCounter( PRCounterHandle handle, PRUint32 value ) { PR_Lock(((RName *)handle)->lock); ((RName *)handle)->counter -= value; PR_Unlock(((RName *)handle)->lock); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SubtractFromCounter: %p, %ld", handle, ((RName *)handle)->counter )); return; } /* end PR_SubtractFromCounter() */ /* ** */ PR_IMPLEMENT(PRUint32) PR_GetCounter( PRCounterHandle handle ) { PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetCounter: %p, %ld", handle, ((RName *)handle)->counter )); return(((RName *)handle)->counter); } /* end PR_GetCounter() */ /* ** */ PR_IMPLEMENT(void) PR_SetCounter( PRCounterHandle handle, PRUint32 value ) { ((RName *)handle)->counter = value; PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: SetCounter: %p, %ld", handle, ((RName *)handle)->counter )); return; } /* end PR_SetCounter() */ /* ** */ PR_IMPLEMENT(PRCounterHandle) PR_FindNextCounterQname( PRCounterHandle handle ) { QName *qnp = (QName *)handle; if ( PR_CLIST_IS_EMPTY( &qNameList )) qnp = NULL; else if ( qnp == NULL ) qnp = (QName *)PR_LIST_HEAD( &qNameList ); else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList ) qnp = NULL; else qnp = (QName *)PR_NEXT_LINK( &qnp->link ); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextQname: Handle: %p, Returns: %p", handle, qnp )); return((PRCounterHandle)qnp); } /* end PR_FindNextCounterQname() */ /* ** */ PR_IMPLEMENT(PRCounterHandle) PR_FindNextCounterRname( PRCounterHandle rhandle, PRCounterHandle qhandle ) { RName *rnp = (RName *)rhandle; QName *qnp = (QName *)qhandle; if ( PR_CLIST_IS_EMPTY( &qnp->rNameList )) rnp = NULL; else if ( rnp == NULL ) rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList ); else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList ) rnp = NULL; else rnp = (RName *)PR_NEXT_LINK( &rnp->link ); PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", rhandle, qhandle, rnp )); return((PRCounterHandle)rnp); } /* end PR_FindNextCounterRname() */ nspr-4.11/nspr/pr/src/misc/prdtoa.c0000644000000000000000000022023212623070344015333 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This file is based on the third-party code dtoa.c. We minimize our * modifications to third-party code to make it easy to merge new versions. * The author of dtoa.c was not willing to add the parentheses suggested by * GCC, so we suppress these warnings. */ #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) #pragma GCC diagnostic ignored "-Wparentheses" #endif #include "primpl.h" #include "prbit.h" #define MULTIPLE_THREADS #define ACQUIRE_DTOA_LOCK(n) PR_Lock(dtoa_lock[n]) #define FREE_DTOA_LOCK(n) PR_Unlock(dtoa_lock[n]) static PRLock *dtoa_lock[2]; void _PR_InitDtoa(void) { dtoa_lock[0] = PR_NewLock(); dtoa_lock[1] = PR_NewLock(); } void _PR_CleanupDtoa(void) { PR_DestroyLock(dtoa_lock[0]); dtoa_lock[0] = NULL; PR_DestroyLock(dtoa_lock[1]); dtoa_lock[1] = NULL; /* FIXME: deal with freelist and p5s. */ } #if !defined(__ARM_EABI__) \ && (defined(__arm) || defined(__arm__) || defined(__arm26__) \ || defined(__arm32__)) #define IEEE_ARM #elif defined(IS_LITTLE_ENDIAN) #define IEEE_8087 #else #define IEEE_MC68k #endif #define Long PRInt32 #define ULong PRUint32 #define NO_LONG_LONG #define No_Hex_NaN /**************************************************************** * * The author of this software is David M. Gay. * * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. * * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. * ***************************************************************/ /* Please send bug reports to David M. Gay (dmg at acm dot org, * with " at " changed at "@" and " dot " changed to "."). */ /* On a machine with IEEE extended-precision registers, it is * necessary to specify double-precision (53-bit) rounding precision * before invoking strtod or dtoa. If the machine uses (the equivalent * of) Intel 80x87 arithmetic, the call * _control87(PC_53, MCW_PC); * does this with many compilers. Whether this or another call is * appropriate depends on the compiler; for this to work, it may be * necessary to #include "float.h" or another system-dependent header * file. */ /* strtod for IEEE-, VAX-, and IBM-arithmetic machines. * * This strtod returns a nearest machine number to the input decimal * string (or sets errno to ERANGE). With IEEE arithmetic, ties are * broken by the IEEE round-even rule. Otherwise ties are broken by * biased rounding (add half and chop). * * Inspired loosely by William D. Clinger's paper "How to Read Floating * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. * * Modifications: * * 1. We only require IEEE, IBM, or VAX double-precision * arithmetic (not IEEE double-extended). * 2. We get by with floating-point arithmetic in a case that * Clinger missed -- when we're computing d * 10^n * for a small integer d and the integer n is not too * much larger than 22 (the maximum integer k for which * we can represent 10^k exactly), we may be able to * compute (d*10^k) * 10^(e-k) with just one roundoff. * 3. Rather than a bit-at-a-time adjustment of the binary * result in the hard case, we use floating-point * arithmetic to determine the adjustment to within * one bit; only in really hard cases do we need to * compute a second residual. * 4. Because of 3., we don't need a large table of powers of 10 * for ten-to-e (just some small tables, e.g. of 10^k * for 0 <= k <= 22). */ /* * #define IEEE_8087 for IEEE-arithmetic machines where the least * significant byte has the lowest address. * #define IEEE_MC68k for IEEE-arithmetic machines where the most * significant byte has the lowest address. * #define IEEE_ARM for IEEE-arithmetic machines where the two words * in a double are stored in big endian order but the two shorts * in a word are still stored in little endian order. * #define Long int on machines with 32-bit ints and 64-bit longs. * #define IBM for IBM mainframe-style floating-point arithmetic. * #define VAX for VAX-style floating-point arithmetic (D_floating). * #define No_leftright to omit left-right logic in fast floating-point * computation of dtoa. * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 * and strtod and dtoa should round accordingly. * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 * and Honor_FLT_ROUNDS is not #defined. * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines * that use extended-precision instructions to compute rounded * products and quotients) with IBM. * #define ROUND_BIASED for IEEE-format with biased rounding. * #define Inaccurate_Divide for IEEE-format with correctly rounded * products but inaccurate quotients, e.g., for Intel i860. * #define NO_LONG_LONG on machines that do not have a "long long" * integer type (of >= 64 bits). On such machines, you can * #define Just_16 to store 16 bits per 32-bit Long when doing * high-precision integer arithmetic. Whether this speeds things * up or slows things down depends on the machine and the number * being converted. If long long is available and the name is * something other than "long long", #define Llong to be the name, * and if "unsigned Llong" does not work as an unsigned version of * Llong, #define #ULLong to be the corresponding unsigned type. * #define KR_headers for old-style C function headers. * #define Bad_float_h if your system lacks a float.h or if it does not * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) * if memory is available and otherwise does something you deem * appropriate. If MALLOC is undefined, malloc will be invoked * directly -- and assumed always to succeed. Similarly, if you * want something other than the system's free() to be called to * recycle memory acquired from MALLOC, #define FREE to be the * name of the alternate routine. (FREE or free is only called in * pathological cases, e.g., in a dtoa call after a dtoa return in * mode 3 with thousands of digits requested.) * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making * memory allocations from a private pool of memory when possible. * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, * unless #defined to be a different length. This default length * suffices to get rid of MALLOC calls except for unusual cases, * such as decimal-to-binary conversion of a very long string of * digits. The longest string dtoa can return is about 751 bytes * long. For conversions by strtod of strings of 800 digits and * all dtoa conversions in single-threaded executions with 8-byte * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte * pointers, PRIVATE_MEM >= 7112 appears adequate. * #define INFNAN_CHECK on IEEE systems to cause strtod to check for * Infinity and NaN (case insensitively). On some systems (e.g., * some HP systems), it may be necessary to #define NAN_WORD0 * appropriately -- to the most significant word of a quiet NaN. * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, * strtod also accepts (case insensitively) strings of the form * NaN(x), where x is a string of hexadecimal digits and spaces; * if there is only one string of hexadecimal digits, it is taken * for the 52 fraction bits of the resulting NaN; if there are two * or more strings of hex digits, the first is for the high 20 bits, * the second and subsequent for the low 32 bits, with intervening * white space ignored; but if this results in none of the 52 * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 * and NAN_WORD1 are used instead. * #define MULTIPLE_THREADS if the system offers preemptively scheduled * multiple threads. In this case, you must provide (or suitably * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed * in pow5mult, ensures lazy evaluation of only one copy of high * powers of 5; omitting this lock would introduce a small * probability of wasting memory, but would otherwise be harmless.) * You must also invoke freedtoa(s) to free the value s returned by * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that * avoids underflows on inputs whose result does not underflow. * If you #define NO_IEEE_Scale on a machine that uses IEEE-format * floating-point numbers and flushes underflows to zero rather * than implementing gradual underflow, then you must also #define * Sudden_Underflow. * #define USE_LOCALE to use the current locale's decimal_point value. * #define SET_INEXACT if IEEE arithmetic is being used and extra * computation should be done to set the inexact flag when the * result is inexact and avoid setting inexact when the result * is exact. In this case, dtoa.c must be compiled in * an environment, perhaps provided by #include "dtoa.c" in a * suitable wrapper, that defines two functions, * int get_inexact(void); * void clear_inexact(void); * such that get_inexact() returns a nonzero value if the * inexact bit is already set, and clear_inexact() sets the * inexact bit to 0. When SET_INEXACT is #defined, strtod * also does extra computations to set the underflow and overflow * flags when appropriate (i.e., when the result is tiny and * inexact or when it is a numeric value rounded to +-infinity). * #define NO_ERRNO if strtod should not assign errno = ERANGE when * the result overflows to +-Infinity or underflows to 0. */ #ifndef Long #define Long long #endif #ifndef ULong typedef unsigned Long ULong; #endif #ifdef DEBUG #include "stdio.h" #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} #endif #include "stdlib.h" #include "string.h" #ifdef USE_LOCALE #include "locale.h" #endif #ifdef MALLOC #ifdef KR_headers extern char *MALLOC(); #else extern void *MALLOC(size_t); #endif #else #define MALLOC malloc #endif #ifndef Omit_Private_Memory #ifndef PRIVATE_MEM #define PRIVATE_MEM 2304 #endif #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) static double private_mem[PRIVATE_mem], *pmem_next = private_mem; #endif #undef IEEE_Arith #undef Avoid_Underflow #ifdef IEEE_MC68k #define IEEE_Arith #endif #ifdef IEEE_8087 #define IEEE_Arith #endif #ifdef IEEE_ARM #define IEEE_Arith #endif #include "errno.h" #ifdef Bad_float_h #ifdef IEEE_Arith #define DBL_DIG 15 #define DBL_MAX_10_EXP 308 #define DBL_MAX_EXP 1024 #define FLT_RADIX 2 #endif /*IEEE_Arith*/ #ifdef IBM #define DBL_DIG 16 #define DBL_MAX_10_EXP 75 #define DBL_MAX_EXP 63 #define FLT_RADIX 16 #define DBL_MAX 7.2370055773322621e+75 #endif #ifdef VAX #define DBL_DIG 16 #define DBL_MAX_10_EXP 38 #define DBL_MAX_EXP 127 #define FLT_RADIX 2 #define DBL_MAX 1.7014118346046923e+38 #endif #ifndef LONG_MAX #define LONG_MAX 2147483647 #endif #else /* ifndef Bad_float_h */ #include "float.h" /* * MacOS 10.2 defines the macro FLT_ROUNDS to an internal function * which does not exist on 10.1. We can safely #define it to 1 here * to allow 10.2 builds to run on 10.1, since we can't use fesetround() * (which does not exist on 10.1 either). */ #if defined(XP_MACOSX) && (!defined(MAC_OS_X_VERSION_10_2) || \ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_2) #undef FLT_ROUNDS #define FLT_ROUNDS 1 #endif /* DT < 10.2 */ #endif /* Bad_float_h */ #ifndef __MATH_H__ #include "math.h" #endif #ifdef __cplusplus extern "C" { #endif #ifndef CONST #ifdef KR_headers #define CONST /* blank */ #else #define CONST const #endif #endif #if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) + defined(VAX) + defined(IBM) != 1 Exactly one of IEEE_8087, IEEE_MC68k, IEEE_ARM, VAX, or IBM should be defined. #endif typedef union { double d; ULong L[2]; } U; #define dval(x) (x).d #ifdef IEEE_8087 #define word0(x) (x).L[1] #define word1(x) (x).L[0] #else #define word0(x) (x).L[0] #define word1(x) (x).L[1] #endif /* The following definition of Storeinc is appropriate for MIPS processors. * An alternative that might be better on some machines is * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) */ #if defined(IEEE_8087) + defined(IEEE_ARM) + defined(VAX) #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ ((unsigned short *)a)[0] = (unsigned short)c, a++) #else #define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ ((unsigned short *)a)[1] = (unsigned short)c, a++) #endif /* #define P DBL_MANT_DIG */ /* Ten_pmax = floor(P*log(2)/log(5)) */ /* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ /* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ /* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ #ifdef IEEE_Arith #define Exp_shift 20 #define Exp_shift1 20 #define Exp_msk1 0x100000 #define Exp_msk11 0x100000 #define Exp_mask 0x7ff00000 #define P 53 #define Bias 1023 #define Emin (-1022) #define Exp_1 0x3ff00000 #define Exp_11 0x3ff00000 #define Ebits 11 #define Frac_mask 0xfffff #define Frac_mask1 0xfffff #define Ten_pmax 22 #define Bletch 0x10 #define Bndry_mask 0xfffff #define Bndry_mask1 0xfffff #define LSB 1 #define Sign_bit 0x80000000 #define Log2P 1 #define Tiny0 0 #define Tiny1 1 #define Quick_max 14 #define Int_max 14 #ifndef NO_IEEE_Scale #define Avoid_Underflow #ifdef Flush_Denorm /* debugging option */ #undef Sudden_Underflow #endif #endif #ifndef Flt_Rounds #ifdef FLT_ROUNDS #define Flt_Rounds FLT_ROUNDS #else #define Flt_Rounds 1 #endif #endif /*Flt_Rounds*/ #ifdef Honor_FLT_ROUNDS #define Rounding rounding #undef Check_FLT_ROUNDS #define Check_FLT_ROUNDS #else #define Rounding Flt_Rounds #endif #else /* ifndef IEEE_Arith */ #undef Check_FLT_ROUNDS #undef Honor_FLT_ROUNDS #undef SET_INEXACT #undef Sudden_Underflow #define Sudden_Underflow #ifdef IBM #undef Flt_Rounds #define Flt_Rounds 0 #define Exp_shift 24 #define Exp_shift1 24 #define Exp_msk1 0x1000000 #define Exp_msk11 0x1000000 #define Exp_mask 0x7f000000 #define P 14 #define Bias 65 #define Exp_1 0x41000000 #define Exp_11 0x41000000 #define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ #define Frac_mask 0xffffff #define Frac_mask1 0xffffff #define Bletch 4 #define Ten_pmax 22 #define Bndry_mask 0xefffff #define Bndry_mask1 0xffffff #define LSB 1 #define Sign_bit 0x80000000 #define Log2P 4 #define Tiny0 0x100000 #define Tiny1 0 #define Quick_max 14 #define Int_max 15 #else /* VAX */ #undef Flt_Rounds #define Flt_Rounds 1 #define Exp_shift 23 #define Exp_shift1 7 #define Exp_msk1 0x80 #define Exp_msk11 0x800000 #define Exp_mask 0x7f80 #define P 56 #define Bias 129 #define Exp_1 0x40800000 #define Exp_11 0x4080 #define Ebits 8 #define Frac_mask 0x7fffff #define Frac_mask1 0xffff007f #define Ten_pmax 24 #define Bletch 2 #define Bndry_mask 0xffff007f #define Bndry_mask1 0xffff007f #define LSB 0x10000 #define Sign_bit 0x8000 #define Log2P 1 #define Tiny0 0x80 #define Tiny1 0 #define Quick_max 15 #define Int_max 15 #endif /* IBM, VAX */ #endif /* IEEE_Arith */ #ifndef IEEE_Arith #define ROUND_BIASED #endif #ifdef RND_PRODQUOT #define rounded_product(a,b) a = rnd_prod(a, b) #define rounded_quotient(a,b) a = rnd_quot(a, b) #ifdef KR_headers extern double rnd_prod(), rnd_quot(); #else extern double rnd_prod(double, double), rnd_quot(double, double); #endif #else #define rounded_product(a,b) a *= b #define rounded_quotient(a,b) a /= b #endif #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) #define Big1 0xffffffff #ifndef Pack_32 #define Pack_32 #endif #ifdef KR_headers #define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff) #else #define FFFFFFFF 0xffffffffUL #endif #ifdef NO_LONG_LONG #undef ULLong #ifdef Just_16 #undef Pack_32 /* When Pack_32 is not defined, we store 16 bits per 32-bit Long. * This makes some inner loops simpler and sometimes saves work * during multiplications, but it often seems to make things slightly * slower. Hence the default is now to store 32 bits per Long. */ #endif #else /* long long available */ #ifndef Llong #define Llong long long #endif #ifndef ULLong #define ULLong unsigned Llong #endif #endif /* NO_LONG_LONG */ #ifndef MULTIPLE_THREADS #define ACQUIRE_DTOA_LOCK(n) /*nothing*/ #define FREE_DTOA_LOCK(n) /*nothing*/ #endif #define Kmax 7 struct Bigint { struct Bigint *next; int k, maxwds, sign, wds; ULong x[1]; }; typedef struct Bigint Bigint; static Bigint *freelist[Kmax+1]; static Bigint * Balloc #ifdef KR_headers (k) int k; #else (int k) #endif { int x; Bigint *rv; #ifndef Omit_Private_Memory unsigned int len; #endif ACQUIRE_DTOA_LOCK(0); /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ /* but this case seems very unlikely. */ if (k <= Kmax && (rv = freelist[k])) freelist[k] = rv->next; else { x = 1 << k; #ifdef Omit_Private_Memory rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); #else len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) /sizeof(double); if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) { rv = (Bigint*)pmem_next; pmem_next += len; } else rv = (Bigint*)MALLOC(len*sizeof(double)); #endif rv->k = k; rv->maxwds = x; } FREE_DTOA_LOCK(0); rv->sign = rv->wds = 0; return rv; } static void Bfree #ifdef KR_headers (v) Bigint *v; #else (Bigint *v) #endif { if (v) { if (v->k > Kmax) #ifdef FREE FREE((void*)v); #else free((void*)v); #endif else { ACQUIRE_DTOA_LOCK(0); v->next = freelist[v->k]; freelist[v->k] = v; FREE_DTOA_LOCK(0); } } } #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ y->wds*sizeof(Long) + 2*sizeof(int)) static Bigint * multadd #ifdef KR_headers (b, m, a) Bigint *b; int m, a; #else (Bigint *b, int m, int a) /* multiply by m and add a */ #endif { int i, wds; #ifdef ULLong ULong *x; ULLong carry, y; #else ULong carry, *x, y; #ifdef Pack_32 ULong xi, z; #endif #endif Bigint *b1; wds = b->wds; x = b->x; i = 0; carry = a; do { #ifdef ULLong y = *x * (ULLong)m + carry; carry = y >> 32; *x++ = y & FFFFFFFF; #else #ifdef Pack_32 xi = *x; y = (xi & 0xffff) * m + carry; z = (xi >> 16) * m + (y >> 16); carry = z >> 16; *x++ = (z << 16) + (y & 0xffff); #else y = *x * m + carry; carry = y >> 16; *x++ = y & 0xffff; #endif #endif } while(++i < wds); if (carry) { if (wds >= b->maxwds) { b1 = Balloc(b->k+1); Bcopy(b1, b); Bfree(b); b = b1; } b->x[wds++] = carry; b->wds = wds; } return b; } static Bigint * s2b #ifdef KR_headers (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9; #else (CONST char *s, int nd0, int nd, ULong y9) #endif { Bigint *b; int i, k; Long x, y; x = (nd + 8) / 9; for(k = 0, y = 1; x > y; y <<= 1, k++) ; #ifdef Pack_32 b = Balloc(k); b->x[0] = y9; b->wds = 1; #else b = Balloc(k+1); b->x[0] = y9 & 0xffff; b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; #endif i = 9; if (9 < nd0) { s += 9; do b = multadd(b, 10, *s++ - '0'); while(++i < nd0); s++; } else s += 10; for(; i < nd; i++) b = multadd(b, 10, *s++ - '0'); return b; } static int hi0bits #ifdef KR_headers (x) register ULong x; #else (register ULong x) #endif { #ifdef PR_HAVE_BUILTIN_BITSCAN32 return( (!x) ? 32 : pr_bitscan_clz32(x) ); #else register int k = 0; if (!(x & 0xffff0000)) { k = 16; x <<= 16; } if (!(x & 0xff000000)) { k += 8; x <<= 8; } if (!(x & 0xf0000000)) { k += 4; x <<= 4; } if (!(x & 0xc0000000)) { k += 2; x <<= 2; } if (!(x & 0x80000000)) { k++; if (!(x & 0x40000000)) return 32; } return k; #endif /* PR_HAVE_BUILTIN_BITSCAN32 */ } static int lo0bits #ifdef KR_headers (y) ULong *y; #else (ULong *y) #endif { #ifdef PR_HAVE_BUILTIN_BITSCAN32 int k; ULong x = *y; if (x>1) *y = ( x >> (k = pr_bitscan_ctz32(x)) ); else k = ((x ^ 1) << 5); #else register int k; register ULong x = *y; if (x & 7) { if (x & 1) return 0; if (x & 2) { *y = x >> 1; return 1; } *y = x >> 2; return 2; } k = 0; if (!(x & 0xffff)) { k = 16; x >>= 16; } if (!(x & 0xff)) { k += 8; x >>= 8; } if (!(x & 0xf)) { k += 4; x >>= 4; } if (!(x & 0x3)) { k += 2; x >>= 2; } if (!(x & 1)) { k++; x >>= 1; if (!x) return 32; } *y = x; #endif /* PR_HAVE_BUILTIN_BITSCAN32 */ return k; } static Bigint * i2b #ifdef KR_headers (i) int i; #else (int i) #endif { Bigint *b; b = Balloc(1); b->x[0] = i; b->wds = 1; return b; } static Bigint * mult #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { Bigint *c; int k, wa, wb, wc; ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; ULong y; #ifdef ULLong ULLong carry, z; #else ULong carry, z; #ifdef Pack_32 ULong z2; #endif #endif if (a->wds < b->wds) { c = a; a = b; b = c; } k = a->k; wa = a->wds; wb = b->wds; wc = wa + wb; if (wc > a->maxwds) k++; c = Balloc(k); for(x = c->x, xa = x + wc; x < xa; x++) *x = 0; xa = a->x; xae = xa + wa; xb = b->x; xbe = xb + wb; xc0 = c->x; #ifdef ULLong for(; xb < xbe; xc0++) { if (y = *xb++) { x = xa; xc = xc0; carry = 0; do { z = *x++ * (ULLong)y + *xc + carry; carry = z >> 32; *xc++ = z & FFFFFFFF; } while(x < xae); *xc = carry; } } #else #ifdef Pack_32 for(; xb < xbe; xb++, xc0++) { if (y = *xb & 0xffff) { x = xa; xc = xc0; carry = 0; do { z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; carry = z >> 16; z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; carry = z2 >> 16; Storeinc(xc, z2, z); } while(x < xae); *xc = carry; } if (y = *xb >> 16) { x = xa; xc = xc0; carry = 0; z2 = *xc; do { z = (*x & 0xffff) * y + (*xc >> 16) + carry; carry = z >> 16; Storeinc(xc, z, z2); z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; carry = z2 >> 16; } while(x < xae); *xc = z2; } } #else for(; xb < xbe; xc0++) { if (y = *xb++) { x = xa; xc = xc0; carry = 0; do { z = *x++ * y + *xc + carry; carry = z >> 16; *xc++ = z & 0xffff; } while(x < xae); *xc = carry; } } #endif #endif for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; c->wds = wc; return c; } static Bigint *p5s; static Bigint * pow5mult #ifdef KR_headers (b, k) Bigint *b; int k; #else (Bigint *b, int k) #endif { Bigint *b1, *p5, *p51; int i; static int p05[3] = { 5, 25, 125 }; if (i = k & 3) b = multadd(b, p05[i-1], 0); if (!(k >>= 2)) return b; if (!(p5 = p5s)) { /* first time */ #ifdef MULTIPLE_THREADS ACQUIRE_DTOA_LOCK(1); if (!(p5 = p5s)) { p5 = p5s = i2b(625); p5->next = 0; } FREE_DTOA_LOCK(1); #else p5 = p5s = i2b(625); p5->next = 0; #endif } for(;;) { if (k & 1) { b1 = mult(b, p5); Bfree(b); b = b1; } if (!(k >>= 1)) break; if (!(p51 = p5->next)) { #ifdef MULTIPLE_THREADS ACQUIRE_DTOA_LOCK(1); if (!(p51 = p5->next)) { p51 = p5->next = mult(p5,p5); p51->next = 0; } FREE_DTOA_LOCK(1); #else p51 = p5->next = mult(p5,p5); p51->next = 0; #endif } p5 = p51; } return b; } static Bigint * lshift #ifdef KR_headers (b, k) Bigint *b; int k; #else (Bigint *b, int k) #endif { int i, k1, n, n1; Bigint *b1; ULong *x, *x1, *xe, z; #ifdef Pack_32 n = k >> 5; #else n = k >> 4; #endif k1 = b->k; n1 = n + b->wds + 1; for(i = b->maxwds; n1 > i; i <<= 1) k1++; b1 = Balloc(k1); x1 = b1->x; for(i = 0; i < n; i++) *x1++ = 0; x = b->x; xe = x + b->wds; #ifdef Pack_32 if (k &= 0x1f) { k1 = 32 - k; z = 0; do { *x1++ = *x << k | z; z = *x++ >> k1; } while(x < xe); if (*x1 = z) ++n1; } #else if (k &= 0xf) { k1 = 16 - k; z = 0; do { *x1++ = *x << k & 0xffff | z; z = *x++ >> k1; } while(x < xe); if (*x1 = z) ++n1; } #endif else do *x1++ = *x++; while(x < xe); b1->wds = n1 - 1; Bfree(b); return b1; } static int cmp #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { ULong *xa, *xa0, *xb, *xb0; int i, j; i = a->wds; j = b->wds; #ifdef DEBUG if (i > 1 && !a->x[i-1]) Bug("cmp called with a->x[a->wds-1] == 0"); if (j > 1 && !b->x[j-1]) Bug("cmp called with b->x[b->wds-1] == 0"); #endif if (i -= j) return i; xa0 = a->x; xa = xa0 + j; xb0 = b->x; xb = xb0 + j; for(;;) { if (*--xa != *--xb) return *xa < *xb ? -1 : 1; if (xa <= xa0) break; } return 0; } static Bigint * diff #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { Bigint *c; int i, wa, wb; ULong *xa, *xae, *xb, *xbe, *xc; #ifdef ULLong ULLong borrow, y; #else ULong borrow, y; #ifdef Pack_32 ULong z; #endif #endif i = cmp(a,b); if (!i) { c = Balloc(0); c->wds = 1; c->x[0] = 0; return c; } if (i < 0) { c = a; a = b; b = c; i = 1; } else i = 0; c = Balloc(a->k); c->sign = i; wa = a->wds; xa = a->x; xae = xa + wa; wb = b->wds; xb = b->x; xbe = xb + wb; xc = c->x; borrow = 0; #ifdef ULLong do { y = (ULLong)*xa++ - *xb++ - borrow; borrow = y >> 32 & (ULong)1; *xc++ = y & FFFFFFFF; } while(xb < xbe); while(xa < xae) { y = *xa++ - borrow; borrow = y >> 32 & (ULong)1; *xc++ = y & FFFFFFFF; } #else #ifdef Pack_32 do { y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(xc, z, y); } while(xb < xbe); while(xa < xae) { y = (*xa & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*xa++ >> 16) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(xc, z, y); } #else do { y = *xa++ - *xb++ - borrow; borrow = (y & 0x10000) >> 16; *xc++ = y & 0xffff; } while(xb < xbe); while(xa < xae) { y = *xa++ - borrow; borrow = (y & 0x10000) >> 16; *xc++ = y & 0xffff; } #endif #endif while(!*--xc) wa--; c->wds = wa; return c; } static double ulp #ifdef KR_headers (dx) double dx; #else (double dx) #endif { register Long L; U x, a; dval(x) = dx; L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; #ifndef Avoid_Underflow #ifndef Sudden_Underflow if (L > 0) { #endif #endif #ifdef IBM L |= Exp_msk1 >> 4; #endif word0(a) = L; word1(a) = 0; #ifndef Avoid_Underflow #ifndef Sudden_Underflow } else { L = -L >> Exp_shift; if (L < Exp_shift) { word0(a) = 0x80000 >> L; word1(a) = 0; } else { word0(a) = 0; L -= Exp_shift; word1(a) = L >= 31 ? 1 : 1 << 31 - L; } } #endif #endif return dval(a); } static double b2d #ifdef KR_headers (a, e) Bigint *a; int *e; #else (Bigint *a, int *e) #endif { ULong *xa, *xa0, w, y, z; int k; U d; #ifdef VAX ULong d0, d1; #else #define d0 word0(d) #define d1 word1(d) #endif xa0 = a->x; xa = xa0 + a->wds; y = *--xa; #ifdef DEBUG if (!y) Bug("zero y in b2d"); #endif k = hi0bits(y); *e = 32 - k; #ifdef Pack_32 if (k < Ebits) { d0 = Exp_1 | y >> Ebits - k; w = xa > xa0 ? *--xa : 0; d1 = y << (32-Ebits) + k | w >> Ebits - k; goto ret_d; } z = xa > xa0 ? *--xa : 0; if (k -= Ebits) { d0 = Exp_1 | y << k | z >> 32 - k; y = xa > xa0 ? *--xa : 0; d1 = z << k | y >> 32 - k; } else { d0 = Exp_1 | y; d1 = z; } #else if (k < Ebits + 16) { z = xa > xa0 ? *--xa : 0; d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; w = xa > xa0 ? *--xa : 0; y = xa > xa0 ? *--xa : 0; d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; goto ret_d; } z = xa > xa0 ? *--xa : 0; w = xa > xa0 ? *--xa : 0; k -= Ebits + 16; d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; y = xa > xa0 ? *--xa : 0; d1 = w << k + 16 | y << k; #endif ret_d: #ifdef VAX word0(d) = d0 >> 16 | d0 << 16; word1(d) = d1 >> 16 | d1 << 16; #else #undef d0 #undef d1 #endif return dval(d); } static Bigint * d2b #ifdef KR_headers (dd, e, bits) double dd; int *e, *bits; #else (double dd, int *e, int *bits) #endif { U d; Bigint *b; int de, k; ULong *x, y, z; #ifndef Sudden_Underflow int i; #endif #ifdef VAX ULong d0, d1; #endif dval(d) = dd; #ifdef VAX d0 = word0(d) >> 16 | word0(d) << 16; d1 = word1(d) >> 16 | word1(d) << 16; #else #define d0 word0(d) #define d1 word1(d) #endif #ifdef Pack_32 b = Balloc(1); #else b = Balloc(2); #endif x = b->x; z = d0 & Frac_mask; d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ #ifdef Sudden_Underflow de = (int)(d0 >> Exp_shift); #ifndef IBM z |= Exp_msk11; #endif #else if (de = (int)(d0 >> Exp_shift)) z |= Exp_msk1; #endif #ifdef Pack_32 if (y = d1) { if (k = lo0bits(&y)) { x[0] = y | z << 32 - k; z >>= k; } else x[0] = y; #ifndef Sudden_Underflow i = #endif b->wds = (x[1] = z) ? 2 : 1; } else { k = lo0bits(&z); x[0] = z; #ifndef Sudden_Underflow i = #endif b->wds = 1; k += 32; } #else if (y = d1) { if (k = lo0bits(&y)) if (k >= 16) { x[0] = y | z << 32 - k & 0xffff; x[1] = z >> k - 16 & 0xffff; x[2] = z >> k; i = 2; } else { x[0] = y & 0xffff; x[1] = y >> 16 | z << 16 - k & 0xffff; x[2] = z >> k & 0xffff; x[3] = z >> k+16; i = 3; } else { x[0] = y & 0xffff; x[1] = y >> 16; x[2] = z & 0xffff; x[3] = z >> 16; i = 3; } } else { #ifdef DEBUG if (!z) Bug("Zero passed to d2b"); #endif k = lo0bits(&z); if (k >= 16) { x[0] = z; i = 0; } else { x[0] = z & 0xffff; x[1] = z >> 16; i = 1; } k += 32; } while(!x[i]) --i; b->wds = i + 1; #endif #ifndef Sudden_Underflow if (de) { #endif #ifdef IBM *e = (de - Bias - (P-1) << 2) + k; *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); #else *e = de - Bias - (P-1) + k; *bits = P - k; #endif #ifndef Sudden_Underflow } else { *e = de - Bias - (P-1) + 1 + k; #ifdef Pack_32 *bits = 32*i - hi0bits(x[i-1]); #else *bits = (i+2)*16 - hi0bits(x[i]); #endif } #endif return b; } #undef d0 #undef d1 static double ratio #ifdef KR_headers (a, b) Bigint *a, *b; #else (Bigint *a, Bigint *b) #endif { U da, db; int k, ka, kb; dval(da) = b2d(a, &ka); dval(db) = b2d(b, &kb); #ifdef Pack_32 k = ka - kb + 32*(a->wds - b->wds); #else k = ka - kb + 16*(a->wds - b->wds); #endif #ifdef IBM if (k > 0) { word0(da) += (k >> 2)*Exp_msk1; if (k &= 3) dval(da) *= 1 << k; } else { k = -k; word0(db) += (k >> 2)*Exp_msk1; if (k &= 3) dval(db) *= 1 << k; } #else if (k > 0) word0(da) += k*Exp_msk1; else { k = -k; word0(db) += k*Exp_msk1; } #endif return dval(da) / dval(db); } static CONST double tens[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22 #ifdef VAX , 1e23, 1e24 #endif }; static CONST double #ifdef IEEE_Arith bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, #ifdef Avoid_Underflow 9007199254740992.*9007199254740992.e-256 /* = 2^106 * 1e-53 */ #else 1e-256 #endif }; /* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ /* flag unnecessarily. It leads to a song and dance at the end of strtod. */ #define Scale_Bit 0x10 #define n_bigtens 5 #else #ifdef IBM bigtens[] = { 1e16, 1e32, 1e64 }; static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 }; #define n_bigtens 3 #else bigtens[] = { 1e16, 1e32 }; static CONST double tinytens[] = { 1e-16, 1e-32 }; #define n_bigtens 2 #endif #endif #ifndef IEEE_Arith #undef INFNAN_CHECK #endif #ifdef INFNAN_CHECK #ifndef NAN_WORD0 #define NAN_WORD0 0x7ff80000 #endif #ifndef NAN_WORD1 #define NAN_WORD1 0 #endif static int match #ifdef KR_headers (sp, t) char **sp, *t; #else (CONST char **sp, char *t) #endif { int c, d; CONST char *s = *sp; while(d = *t++) { if ((c = *++s) >= 'A' && c <= 'Z') c += 'a' - 'A'; if (c != d) return 0; } *sp = s + 1; return 1; } #ifndef No_Hex_NaN static void hexnan #ifdef KR_headers (rvp, sp) double *rvp; CONST char **sp; #else (double *rvp, CONST char **sp) #endif { ULong c, x[2]; CONST char *s; int havedig, udx0, xshift; x[0] = x[1] = 0; havedig = xshift = 0; udx0 = 1; s = *sp; while(c = *(CONST unsigned char*)++s) { if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'a' && c <= 'f') c += 10 - 'a'; else if (c >= 'A' && c <= 'F') c += 10 - 'A'; else if (c <= ' ') { if (udx0 && havedig) { udx0 = 0; xshift = 1; } continue; } else if (/*(*/ c == ')' && havedig) { *sp = s + 1; break; } else return; /* invalid form: don't change *sp */ havedig = 1; if (xshift) { xshift = 0; x[0] = x[1]; x[1] = 0; } if (udx0) x[0] = (x[0] << 4) | (x[1] >> 28); x[1] = (x[1] << 4) | c; } if ((x[0] &= 0xfffff) || x[1]) { word0(*rvp) = Exp_mask | x[0]; word1(*rvp) = x[1]; } } #endif /*No_Hex_NaN*/ #endif /* INFNAN_CHECK */ PR_IMPLEMENT(double) PR_strtod #ifdef KR_headers (s00, se) CONST char *s00; char **se; #else (CONST char *s00, char **se) #endif { #ifdef Avoid_Underflow int scale; #endif int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; CONST char *s, *s0, *s1; double aadj, aadj1, adj; U aadj2, rv, rv0; Long L; ULong y, z; Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; #ifdef SET_INEXACT int inexact, oldinexact; #endif #ifdef Honor_FLT_ROUNDS int rounding; #endif #ifdef USE_LOCALE CONST char *s2; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); sign = nz0 = nz = 0; dval(rv) = 0.; for(s = s00;;s++) switch(*s) { case '-': sign = 1; /* no break */ case '+': if (*++s) goto break2; /* no break */ case 0: goto ret0; case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': continue; default: goto break2; } break2: if (*s == '0') { nz0 = 1; while(*++s == '0') ; if (!*s) goto ret; } s0 = s; y = z = 0; for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) if (nd < 9) y = 10*y + c - '0'; else if (nd < 16) z = 10*z + c - '0'; nd0 = nd; #ifdef USE_LOCALE s1 = localeconv()->decimal_point; if (c == *s1) { c = '.'; if (*++s1) { s2 = s; for(;;) { if (*++s2 != *s1) { c = 0; break; } if (!*++s1) { s = s2; break; } } } } #endif if (c == '.') { c = *++s; if (!nd) { for(; c == '0'; c = *++s) nz++; if (c > '0' && c <= '9') { s0 = s; nf += nz; nz = 0; goto have_dig; } goto dig_done; } for(; c >= '0' && c <= '9'; c = *++s) { have_dig: nz++; if (c -= '0') { nf += nz; for(i = 1; i < nz; i++) if (nd++ < 9) y *= 10; else if (nd <= DBL_DIG + 1) z *= 10; if (nd++ < 9) y = 10*y + c; else if (nd <= DBL_DIG + 1) z = 10*z + c; nz = 0; } } } dig_done: if (nd > 64 * 1024) goto ret0; e = 0; if (c == 'e' || c == 'E') { if (!nd && !nz && !nz0) { goto ret0; } s00 = s; esign = 0; switch(c = *++s) { case '-': esign = 1; case '+': c = *++s; } if (c >= '0' && c <= '9') { while(c == '0') c = *++s; if (c > '0' && c <= '9') { L = c - '0'; s1 = s; while((c = *++s) >= '0' && c <= '9') L = 10*L + c - '0'; if (s - s1 > 8 || L > 19999) /* Avoid confusion from exponents * so large that e might overflow. */ e = 19999; /* safe for 16 bit ints */ else e = (int)L; if (esign) e = -e; } else e = 0; } else s = s00; } if (!nd) { if (!nz && !nz0) { #ifdef INFNAN_CHECK /* Check for Nan and Infinity */ switch(c) { case 'i': case 'I': if (match(&s,"nf")) { --s; if (!match(&s,"inity")) ++s; word0(rv) = 0x7ff00000; word1(rv) = 0; goto ret; } break; case 'n': case 'N': if (match(&s, "an")) { word0(rv) = NAN_WORD0; word1(rv) = NAN_WORD1; #ifndef No_Hex_NaN if (*s == '(') /*)*/ hexnan(&rv, &s); #endif goto ret; } } #endif /* INFNAN_CHECK */ ret0: s = s00; sign = 0; } goto ret; } e1 = e -= nf; /* Now we have nd0 digits, starting at s0, followed by a * decimal point, followed by nd-nd0 digits. The number we're * after is the integer represented by those digits times * 10**e */ if (!nd0) nd0 = nd; k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; dval(rv) = y; if (k > 9) { #ifdef SET_INEXACT if (k > DBL_DIG) oldinexact = get_inexact(); #endif dval(rv) = tens[k - 9] * dval(rv) + z; } bd0 = 0; if (nd <= DBL_DIG #ifndef RND_PRODQUOT #ifndef Honor_FLT_ROUNDS && Flt_Rounds == 1 #endif #endif ) { if (!e) goto ret; if (e > 0) { if (e <= Ten_pmax) { #ifdef VAX goto vax_ovfl_check; #else #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv = -rv; sign = 0; } #endif /* rv = */ rounded_product(dval(rv), tens[e]); goto ret; #endif } i = DBL_DIG - nd; if (e <= Ten_pmax + i) { /* A fancier test would sometimes let us do * this for larger i values. */ #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv = -rv; sign = 0; } #endif e -= i; dval(rv) *= tens[i]; #ifdef VAX /* VAX exponent range is so narrow we must * worry about overflow here... */ vax_ovfl_check: word0(rv) -= P*Exp_msk1; /* rv = */ rounded_product(dval(rv), tens[e]); if ((word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) goto ovfl; word0(rv) += P*Exp_msk1; #else /* rv = */ rounded_product(dval(rv), tens[e]); #endif goto ret; } } #ifndef Inaccurate_Divide else if (e >= -Ten_pmax) { #ifdef Honor_FLT_ROUNDS /* round correctly FLT_ROUNDS = 2 or 3 */ if (sign) { rv = -rv; sign = 0; } #endif /* rv = */ rounded_quotient(dval(rv), tens[-e]); goto ret; } #endif } e1 += nd - k; #ifdef IEEE_Arith #ifdef SET_INEXACT inexact = 1; if (k <= DBL_DIG) oldinexact = get_inexact(); #endif #ifdef Avoid_Underflow scale = 0; #endif #ifdef Honor_FLT_ROUNDS if ((rounding = Flt_Rounds) >= 2) { if (sign) rounding = rounding == 2 ? 0 : 2; else if (rounding != 2) rounding = 0; } #endif #endif /*IEEE_Arith*/ /* Get starting approximation = rv * 10**e1 */ if (e1 > 0) { if (i = e1 & 15) dval(rv) *= tens[i]; if (e1 &= ~15) { if (e1 > DBL_MAX_10_EXP) { ovfl: #ifndef NO_ERRNO PR_SetError(PR_RANGE_ERROR, 0); #endif /* Can't trust HUGE_VAL */ #ifdef IEEE_Arith #ifdef Honor_FLT_ROUNDS switch(rounding) { case 0: /* toward 0 */ case 3: /* toward -infinity */ word0(rv) = Big0; word1(rv) = Big1; break; default: word0(rv) = Exp_mask; word1(rv) = 0; } #else /*Honor_FLT_ROUNDS*/ word0(rv) = Exp_mask; word1(rv) = 0; #endif /*Honor_FLT_ROUNDS*/ #ifdef SET_INEXACT /* set overflow bit */ dval(rv0) = 1e300; dval(rv0) *= dval(rv0); #endif #else /*IEEE_Arith*/ word0(rv) = Big0; word1(rv) = Big1; #endif /*IEEE_Arith*/ if (bd0) goto retfree; goto ret; } e1 >>= 4; for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) dval(rv) *= bigtens[j]; /* The last multiplication could overflow. */ word0(rv) -= P*Exp_msk1; dval(rv) *= bigtens[j]; if ((z = word0(rv) & Exp_mask) > Exp_msk1*(DBL_MAX_EXP+Bias-P)) goto ovfl; if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { /* set to largest number */ /* (Can't trust DBL_MAX) */ word0(rv) = Big0; word1(rv) = Big1; } else word0(rv) += P*Exp_msk1; } } else if (e1 < 0) { e1 = -e1; if (i = e1 & 15) dval(rv) /= tens[i]; if (e1 >>= 4) { if (e1 >= 1 << n_bigtens) goto undfl; #ifdef Avoid_Underflow if (e1 & Scale_Bit) scale = 2*P; for(j = 0; e1 > 0; j++, e1 >>= 1) if (e1 & 1) dval(rv) *= tinytens[j]; if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask) >> Exp_shift)) > 0) { /* scaled rv is denormal; zap j low bits */ if (j >= 32) { word1(rv) = 0; if (j >= 53) word0(rv) = (P+2)*Exp_msk1; else word0(rv) &= 0xffffffff << j-32; } else word1(rv) &= 0xffffffff << j; } #else for(j = 0; e1 > 1; j++, e1 >>= 1) if (e1 & 1) dval(rv) *= tinytens[j]; /* The last multiplication could underflow. */ dval(rv0) = dval(rv); dval(rv) *= tinytens[j]; if (!dval(rv)) { dval(rv) = 2.*dval(rv0); dval(rv) *= tinytens[j]; #endif if (!dval(rv)) { undfl: dval(rv) = 0.; #ifndef NO_ERRNO PR_SetError(PR_RANGE_ERROR, 0); #endif if (bd0) goto retfree; goto ret; } #ifndef Avoid_Underflow word0(rv) = Tiny0; word1(rv) = Tiny1; /* The refinement below will clean * this approximation up. */ } #endif } } /* Now the hard part -- adjusting rv to the correct value.*/ /* Put digits into bd: true value = bd * 10^e */ bd0 = s2b(s0, nd0, nd, y); for(;;) { bd = Balloc(bd0->k); Bcopy(bd, bd0); bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ bs = i2b(1); if (e >= 0) { bb2 = bb5 = 0; bd2 = bd5 = e; } else { bb2 = bb5 = -e; bd2 = bd5 = 0; } if (bbe >= 0) bb2 += bbe; else bd2 -= bbe; bs2 = bb2; #ifdef Honor_FLT_ROUNDS if (rounding != 1) bs2++; #endif #ifdef Avoid_Underflow j = bbe - scale; i = j + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j += P - Emin; else j = P + 1 - bbbits; #else /*Avoid_Underflow*/ #ifdef Sudden_Underflow #ifdef IBM j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); #else j = P + 1 - bbbits; #endif #else /*Sudden_Underflow*/ j = bbe; i = j + bbbits - 1; /* logb(rv) */ if (i < Emin) /* denormal */ j += P - Emin; else j = P + 1 - bbbits; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ bb2 += j; bd2 += j; #ifdef Avoid_Underflow bd2 += scale; #endif i = bb2 < bd2 ? bb2 : bd2; if (i > bs2) i = bs2; if (i > 0) { bb2 -= i; bd2 -= i; bs2 -= i; } if (bb5 > 0) { bs = pow5mult(bs, bb5); bb1 = mult(bs, bb); Bfree(bb); bb = bb1; } if (bb2 > 0) bb = lshift(bb, bb2); if (bd5 > 0) bd = pow5mult(bd, bd5); if (bd2 > 0) bd = lshift(bd, bd2); if (bs2 > 0) bs = lshift(bs, bs2); delta = diff(bb, bd); dsign = delta->sign; delta->sign = 0; i = cmp(delta, bs); #ifdef Honor_FLT_ROUNDS if (rounding != 1) { if (i < 0) { /* Error is less than an ulp */ if (!delta->x[0] && delta->wds <= 1) { /* exact */ #ifdef SET_INEXACT inexact = 0; #endif break; } if (rounding) { if (dsign) { adj = 1.; goto apply_adj; } } else if (!dsign) { adj = -1.; if (!word1(rv) && !(word0(rv) & Frac_mask)) { y = word0(rv) & Exp_mask; #ifdef Avoid_Underflow if (!scale || y > 2*P*Exp_msk1) #else if (y) #endif { delta = lshift(delta,Log2P); if (cmp(delta, bs) <= 0) adj = -0.5; } } apply_adj: #ifdef Avoid_Underflow if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) word0(adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { word0(rv) += P*Exp_msk1; dval(rv) += adj*ulp(dval(rv)); word0(rv) -= P*Exp_msk1; } else #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ dval(rv) += adj*ulp(dval(rv)); } break; } adj = ratio(delta, bs); if (adj < 1.) adj = 1.; if (adj <= 0x7ffffffe) { /* adj = rounding ? ceil(adj) : floor(adj); */ y = adj; if (y != adj) { if (!((rounding>>1) ^ dsign)) y++; adj = y; } } #ifdef Avoid_Underflow if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) word0(adj) += (2*P+1)*Exp_msk1 - y; #else #ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { word0(rv) += P*Exp_msk1; adj *= ulp(dval(rv)); if (dsign) dval(rv) += adj; else dval(rv) -= adj; word0(rv) -= P*Exp_msk1; goto cont; } #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ adj *= ulp(dval(rv)); if (dsign) dval(rv) += adj; else dval(rv) -= adj; goto cont; } #endif /*Honor_FLT_ROUNDS*/ if (i < 0) { /* Error is less than half an ulp -- check for * special case of mantissa a power of two. */ if (dsign || word1(rv) || word0(rv) & Bndry_mask #ifdef IEEE_Arith #ifdef Avoid_Underflow || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1 #else || (word0(rv) & Exp_mask) <= Exp_msk1 #endif #endif ) { #ifdef SET_INEXACT if (!delta->x[0] && delta->wds <= 1) inexact = 0; #endif break; } if (!delta->x[0] && delta->wds <= 1) { /* exact result */ #ifdef SET_INEXACT inexact = 0; #endif break; } delta = lshift(delta,Log2P); if (cmp(delta, bs) > 0) goto drop_down; break; } if (i == 0) { /* exactly half-way between */ if (dsign) { if ((word0(rv) & Bndry_mask1) == Bndry_mask1 && word1(rv) == ( #ifdef Avoid_Underflow (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : #endif 0xffffffff)) { /*boundary case -- increment exponent*/ word0(rv) = (word0(rv) & Exp_mask) + Exp_msk1 #ifdef IBM | Exp_msk1 >> 4 #endif ; word1(rv) = 0; #ifdef Avoid_Underflow dsign = 0; #endif break; } } else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { drop_down: /* boundary case -- decrement exponent */ #ifdef Sudden_Underflow /*{{*/ L = word0(rv) & Exp_mask; #ifdef IBM if (L < Exp_msk1) #else #ifdef Avoid_Underflow if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) #else if (L <= Exp_msk1) #endif /*Avoid_Underflow*/ #endif /*IBM*/ goto undfl; L -= Exp_msk1; #else /*Sudden_Underflow}{*/ #ifdef Avoid_Underflow if (scale) { L = word0(rv) & Exp_mask; if (L <= (2*P+1)*Exp_msk1) { if (L > (P+2)*Exp_msk1) /* round even ==> */ /* accept rv */ break; /* rv = smallest denormal */ goto undfl; } } #endif /*Avoid_Underflow*/ L = (word0(rv) & Exp_mask) - Exp_msk1; #endif /*Sudden_Underflow}}*/ word0(rv) = L | Bndry_mask1; word1(rv) = 0xffffffff; #ifdef IBM goto cont; #else break; #endif } #ifndef ROUND_BIASED if (!(word1(rv) & LSB)) break; #endif if (dsign) dval(rv) += ulp(dval(rv)); #ifndef ROUND_BIASED else { dval(rv) -= ulp(dval(rv)); #ifndef Sudden_Underflow if (!dval(rv)) goto undfl; #endif } #ifdef Avoid_Underflow dsign = 1 - dsign; #endif #endif break; } if ((aadj = ratio(delta, bs)) <= 2.) { if (dsign) aadj = aadj1 = 1.; else if (word1(rv) || word0(rv) & Bndry_mask) { #ifndef Sudden_Underflow if (word1(rv) == Tiny1 && !word0(rv)) goto undfl; #endif aadj = 1.; aadj1 = -1.; } else { /* special case -- power of FLT_RADIX to be */ /* rounded down... */ if (aadj < 2./FLT_RADIX) aadj = 1./FLT_RADIX; else aadj *= 0.5; aadj1 = -aadj; } } else { aadj *= 0.5; aadj1 = dsign ? aadj : -aadj; #ifdef Check_FLT_ROUNDS switch(Rounding) { case 2: /* towards +infinity */ aadj1 -= 0.5; break; case 0: /* towards 0 */ case 3: /* towards -infinity */ aadj1 += 0.5; } #else if (Flt_Rounds == 0) aadj1 += 0.5; #endif /*Check_FLT_ROUNDS*/ } y = word0(rv) & Exp_mask; /* Check for overflow */ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { dval(rv0) = dval(rv); word0(rv) -= P*Exp_msk1; adj = aadj1 * ulp(dval(rv)); dval(rv) += adj; if ((word0(rv) & Exp_mask) >= Exp_msk1*(DBL_MAX_EXP+Bias-P)) { if (word0(rv0) == Big0 && word1(rv0) == Big1) goto ovfl; word0(rv) = Big0; word1(rv) = Big1; goto cont; } else word0(rv) += P*Exp_msk1; } else { #ifdef Avoid_Underflow if (scale && y <= 2*P*Exp_msk1) { if (aadj <= 0x7fffffff) { if ((z = aadj) <= 0) z = 1; aadj = z; aadj1 = dsign ? aadj : -aadj; } dval(aadj2) = aadj1; word0(aadj2) += (2*P+1)*Exp_msk1 - y; aadj1 = dval(aadj2); } adj = aadj1 * ulp(dval(rv)); dval(rv) += adj; #else #ifdef Sudden_Underflow if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { dval(rv0) = dval(rv); word0(rv) += P*Exp_msk1; adj = aadj1 * ulp(dval(rv)); dval(rv) += adj; #ifdef IBM if ((word0(rv) & Exp_mask) < P*Exp_msk1) #else if ((word0(rv) & Exp_mask) <= P*Exp_msk1) #endif { if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) goto undfl; word0(rv) = Tiny0; word1(rv) = Tiny1; goto cont; } else word0(rv) -= P*Exp_msk1; } else { adj = aadj1 * ulp(dval(rv)); dval(rv) += adj; } #else /*Sudden_Underflow*/ /* Compute adj so that the IEEE rounding rules will * correctly round rv + adj in some half-way cases. * If rv * ulp(rv) is denormalized (i.e., * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid * trouble from bits lost to denormalization; * example: 1.2e-307 . */ if (y <= (P-1)*Exp_msk1 && aadj > 1.) { aadj1 = (double)(int)(aadj + 0.5); if (!dsign) aadj1 = -aadj1; } adj = aadj1 * ulp(dval(rv)); dval(rv) += adj; #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ } z = word0(rv) & Exp_mask; #ifndef SET_INEXACT #ifdef Avoid_Underflow if (!scale) #endif if (y == z) { /* Can we stop now? */ L = (Long)aadj; aadj -= L; /* The tolerances below are conservative. */ if (dsign || word1(rv) || word0(rv) & Bndry_mask) { if (aadj < .4999999 || aadj > .5000001) break; } else if (aadj < .4999999/FLT_RADIX) break; } #endif cont: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(delta); } #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { word0(rv0) = Exp_1 + (70 << Exp_shift); word1(rv0) = 0; dval(rv0) += 1.; } } else if (!oldinexact) clear_inexact(); #endif #ifdef Avoid_Underflow if (scale) { word0(rv0) = Exp_1 - 2*P*Exp_msk1; word1(rv0) = 0; dval(rv) *= dval(rv0); #ifndef NO_ERRNO /* try to avoid the bug of testing an 8087 register value */ if (word0(rv) == 0 && word1(rv) == 0) PR_SetError(PR_RANGE_ERROR, 0); #endif } #endif /* Avoid_Underflow */ #ifdef SET_INEXACT if (inexact && !(word0(rv) & Exp_mask)) { /* set underflow bit */ dval(rv0) = 1e-300; dval(rv0) *= dval(rv0); } #endif retfree: Bfree(bb); Bfree(bd); Bfree(bs); Bfree(bd0); Bfree(delta); ret: if (se) *se = (char *)s; return sign ? -dval(rv) : dval(rv); } static int quorem #ifdef KR_headers (b, S) Bigint *b, *S; #else (Bigint *b, Bigint *S) #endif { int n; ULong *bx, *bxe, q, *sx, *sxe; #ifdef ULLong ULLong borrow, carry, y, ys; #else ULong borrow, carry, y, ys; #ifdef Pack_32 ULong si, z, zs; #endif #endif n = S->wds; #ifdef DEBUG /*debug*/ if (b->wds > n) /*debug*/ Bug("oversize b in quorem"); #endif if (b->wds < n) return 0; sx = S->x; sxe = sx + --n; bx = b->x; bxe = bx + n; q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ #ifdef DEBUG /*debug*/ if (q > 9) /*debug*/ Bug("oversized quotient in quorem"); #endif if (q) { borrow = 0; carry = 0; do { #ifdef ULLong ys = *sx++ * (ULLong)q + carry; carry = ys >> 32; y = *bx - (ys & FFFFFFFF) - borrow; borrow = y >> 32 & (ULong)1; *bx++ = y & FFFFFFFF; #else #ifdef Pack_32 si = *sx++; ys = (si & 0xffff) * q + carry; zs = (si >> 16) * q + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*bx >> 16) - (zs & 0xffff) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(bx, z, y); #else ys = *sx++ * q + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; *bx++ = y & 0xffff; #endif #endif } while(sx <= sxe); if (!*bxe) { bx = b->x; while(--bxe > bx && !*bxe) --n; b->wds = n; } } if (cmp(b, S) >= 0) { q++; borrow = 0; carry = 0; bx = b->x; sx = S->x; do { #ifdef ULLong ys = *sx++ + carry; carry = ys >> 32; y = *bx - (ys & FFFFFFFF) - borrow; borrow = y >> 32 & (ULong)1; *bx++ = y & FFFFFFFF; #else #ifdef Pack_32 si = *sx++; ys = (si & 0xffff) + carry; zs = (si >> 16) + (ys >> 16); carry = zs >> 16; y = (*bx & 0xffff) - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; z = (*bx >> 16) - (zs & 0xffff) - borrow; borrow = (z & 0x10000) >> 16; Storeinc(bx, z, y); #else ys = *sx++ + carry; carry = ys >> 16; y = *bx - (ys & 0xffff) - borrow; borrow = (y & 0x10000) >> 16; *bx++ = y & 0xffff; #endif #endif } while(sx <= sxe); bx = b->x; bxe = bx + n; if (!*bxe) { while(--bxe > bx && !*bxe) --n; b->wds = n; } } return q; } #ifndef MULTIPLE_THREADS static char *dtoa_result; #endif static char * #ifdef KR_headers rv_alloc(i) int i; #else rv_alloc(int i) #endif { int j, k, *r; j = sizeof(ULong); for(k = 0; sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i; j <<= 1) k++; r = (int*)Balloc(k); *r = k; return #ifndef MULTIPLE_THREADS dtoa_result = #endif (char *)(r+1); } static char * #ifdef KR_headers nrv_alloc(s, rve, n) char *s, **rve; int n; #else nrv_alloc(char *s, char **rve, int n) #endif { char *rv, *t; t = rv = rv_alloc(n); while(*t = *s++) t++; if (rve) *rve = t; return rv; } /* freedtoa(s) must be used to free values s returned by dtoa * when MULTIPLE_THREADS is #defined. It should be used in all cases, * but for consistency with earlier versions of dtoa, it is optional * when MULTIPLE_THREADS is not defined. */ static void #ifdef KR_headers freedtoa(s) char *s; #else freedtoa(char *s) #endif { Bigint *b = (Bigint *)((int *)s - 1); b->maxwds = 1 << (b->k = *(int*)b); Bfree(b); #ifndef MULTIPLE_THREADS if (s == dtoa_result) dtoa_result = 0; #endif } /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. * * Inspired by "How to Print Floating-Point Numbers Accurately" by * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. * * Modifications: * 1. Rather than iterating, we use a simple numeric overestimate * to determine k = floor(log10(d)). We scale relevant * quantities using O(log2(k)) rather than O(k) multiplications. * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't * try to generate digits strictly left to right. Instead, we * compute with fewer bits and propagate the carry if necessary * when rounding the final digit up. This is often faster. * 3. Under the assumption that input will be rounded nearest, * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. * That is, we allow equality in stopping tests when the * round-nearest rule will give the same floating-point value * as would satisfaction of the stopping test with strict * inequality. * 4. We remove common factors of powers of 2 from relevant * quantities. * 5. When converting floating-point integers less than 1e16, * we use floating-point arithmetic rather than resorting * to multiple-precision integers. * 6. When asked to produce fewer than 15 digits, we first try * to get by with floating-point arithmetic; we resort to * multiple-precision integer arithmetic only if we cannot * guarantee that the floating-point calculation has given * the correctly rounded result. For k requested digits and * "uniformly" distributed input, the probability is * something like 10^(k-15) that we must resort to the Long * calculation. */ static char * dtoa #ifdef KR_headers (dd, mode, ndigits, decpt, sign, rve) double dd; int mode, ndigits, *decpt, *sign; char **rve; #else (double dd, int mode, int ndigits, int *decpt, int *sign, char **rve) #endif { /* Arguments ndigits, decpt, sign are similar to those of ecvt and fcvt; trailing zeros are suppressed from the returned string. If not null, *rve is set to point to the end of the return value. If d is +-Infinity or NaN, then *decpt is set to 9999. mode: 0 ==> shortest string that yields d when read in and rounded to nearest. 1 ==> like 0, but with Steele & White stopping rule; e.g. with IEEE P754 arithmetic , mode 0 gives 1e23 whereas mode 1 gives 9.999999999999999e22. 2 ==> max(1,ndigits) significant digits. This gives a return value similar to that of ecvt, except that trailing zeros are suppressed. 3 ==> through ndigits past the decimal point. This gives a return value similar to that from fcvt, except that trailing zeros are suppressed, and ndigits can be negative. 4,5 ==> similar to 2 and 3, respectively, but (in round-nearest mode) with the tests of mode 0 to possibly return a shorter string that rounds to d. With IEEE arithmetic and compilation with -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same as modes 2 and 3 when FLT_ROUNDS != 1. 6-9 ==> Debugging modes similar to mode - 4: don't try fast floating-point estimate (if applicable). Values of mode other than 0-9 are treated as mode 0. Sufficient space is allocated to the return value to hold the suppressed trailing zeros. */ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, spec_case, try_quick; Long L; #ifndef Sudden_Underflow int denorm; ULong x; #endif Bigint *b, *b1, *delta, *mlo, *mhi, *S; U d, d2, eps; double ds; char *s, *s0; #ifdef Honor_FLT_ROUNDS int rounding; #endif #ifdef SET_INEXACT int inexact, oldinexact; #endif #ifndef MULTIPLE_THREADS if (dtoa_result) { freedtoa(dtoa_result); dtoa_result = 0; } #endif dval(d) = dd; if (word0(d) & Sign_bit) { /* set sign for everything, including 0's and NaNs */ *sign = 1; word0(d) &= ~Sign_bit; /* clear sign bit */ } else *sign = 0; #if defined(IEEE_Arith) + defined(VAX) #ifdef IEEE_Arith if ((word0(d) & Exp_mask) == Exp_mask) #else if (word0(d) == 0x8000) #endif { /* Infinity or NaN */ *decpt = 9999; #ifdef IEEE_Arith if (!word1(d) && !(word0(d) & 0xfffff)) return nrv_alloc("Infinity", rve, 8); #endif return nrv_alloc("NaN", rve, 3); } #endif #ifdef IBM dval(d) += 0; /* normalize */ #endif if (!dval(d)) { *decpt = 1; return nrv_alloc("0", rve, 1); } #ifdef SET_INEXACT try_quick = oldinexact = get_inexact(); inexact = 1; #endif #ifdef Honor_FLT_ROUNDS if ((rounding = Flt_Rounds) >= 2) { if (*sign) rounding = rounding == 2 ? 0 : 2; else if (rounding != 2) rounding = 0; } #endif b = d2b(dval(d), &be, &bbits); #ifdef Sudden_Underflow i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); #else if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) { #endif dval(d2) = dval(d); word0(d2) &= Frac_mask1; word0(d2) |= Exp_11; #ifdef IBM if (j = 11 - hi0bits(word0(d2) & Frac_mask)) dval(d2) /= 1 << j; #endif /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 * log10(x) = log(x) / log(10) * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) * * This suggests computing an approximation k to log10(d) by * * k = (i - Bias)*0.301029995663981 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); * * We want k to be too large rather than too small. * The error in the first-order Taylor series approximation * is in our favor, so we just round up the constant enough * to compensate for any error in the multiplication of * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, * adding 1e-13 to the constant term more than suffices. * Hence we adjust the constant term to 0.1760912590558. * (We could get a more accurate k by invoking log10, * but this is probably not worthwhile.) */ i -= Bias; #ifdef IBM i <<= 2; i += j; #endif #ifndef Sudden_Underflow denorm = 0; } else { /* d is denormalized */ i = bbits + be + (Bias + (P-1) - 1); x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32 : word1(d) << 32 - i; dval(d2) = x; word0(d2) -= 31*Exp_msk1; /* adjust exponent */ i -= (Bias + (P-1) - 1) + 1; denorm = 1; } #endif ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; k = (int)ds; if (ds < 0. && ds != k) k--; /* want k = floor(ds) */ k_check = 1; if (k >= 0 && k <= Ten_pmax) { if (dval(d) < tens[k]) k--; k_check = 0; } j = bbits - i - 1; if (j >= 0) { b2 = 0; s2 = j; } else { b2 = -j; s2 = 0; } if (k >= 0) { b5 = 0; s5 = k; s2 += k; } else { b2 -= k; b5 = -k; s5 = 0; } if (mode < 0 || mode > 9) mode = 0; #ifndef SET_INEXACT #ifdef Check_FLT_ROUNDS try_quick = Rounding == 1; #else try_quick = 1; #endif #endif /*SET_INEXACT*/ if (mode > 5) { mode -= 4; try_quick = 0; } leftright = 1; switch(mode) { case 0: case 1: ilim = ilim1 = -1; i = 18; ndigits = 0; break; case 2: leftright = 0; /* no break */ case 4: if (ndigits <= 0) ndigits = 1; ilim = ilim1 = i = ndigits; break; case 3: leftright = 0; /* no break */ case 5: i = ndigits + k + 1; ilim = i; ilim1 = i - 1; if (i <= 0) i = 1; } s = s0 = rv_alloc(i); #ifdef Honor_FLT_ROUNDS if (mode > 1 && rounding != 1) leftright = 0; #endif if (ilim >= 0 && ilim <= Quick_max && try_quick) { /* Try to get by with floating-point arithmetic. */ i = 0; dval(d2) = dval(d); k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ if (k > 0) { ds = tens[k&0xf]; j = k >> 4; if (j & Bletch) { /* prevent overflows */ j &= Bletch - 1; dval(d) /= bigtens[n_bigtens-1]; ieps++; } for(; j; j >>= 1, i++) if (j & 1) { ieps++; ds *= bigtens[i]; } dval(d) /= ds; } else if (j1 = -k) { dval(d) *= tens[j1 & 0xf]; for(j = j1 >> 4; j; j >>= 1, i++) if (j & 1) { ieps++; dval(d) *= bigtens[i]; } } if (k_check && dval(d) < 1. && ilim > 0) { if (ilim1 <= 0) goto fast_failed; ilim = ilim1; k--; dval(d) *= 10.; ieps++; } dval(eps) = ieps*dval(d) + 7.; word0(eps) -= (P-1)*Exp_msk1; if (ilim == 0) { S = mhi = 0; dval(d) -= 5.; if (dval(d) > dval(eps)) goto one_digit; if (dval(d) < -dval(eps)) goto no_digits; goto fast_failed; } #ifndef No_leftright if (leftright) { /* Use Steele & White method of only * generating digits needed. */ dval(eps) = 0.5/tens[ilim-1] - dval(eps); for(i = 0;;) { L = dval(d); dval(d) -= L; *s++ = '0' + (int)L; if (dval(d) < dval(eps)) goto ret1; if (1. - dval(d) < dval(eps)) goto bump_up; if (++i >= ilim) break; dval(eps) *= 10.; dval(d) *= 10.; } } else { #endif /* Generate ilim digits, then fix them up. */ dval(eps) *= tens[ilim-1]; for(i = 1;; i++, dval(d) *= 10.) { L = (Long)(dval(d)); if (!(dval(d) -= L)) ilim = i; *s++ = '0' + (int)L; if (i == ilim) { if (dval(d) > 0.5 + dval(eps)) goto bump_up; else if (dval(d) < 0.5 - dval(eps)) { while(*--s == '0'); s++; goto ret1; } break; } } #ifndef No_leftright } #endif fast_failed: s = s0; dval(d) = dval(d2); k = k0; ilim = ilim0; } /* Do we have a "small" integer? */ if (be >= 0 && k <= Int_max) { /* Yes. */ ds = tens[k]; if (ndigits < 0 && ilim <= 0) { S = mhi = 0; if (ilim < 0 || dval(d) <= 5*ds) goto no_digits; goto one_digit; } for(i = 1; i <= k+1; i++, dval(d) *= 10.) { L = (Long)(dval(d) / ds); dval(d) -= L*ds; #ifdef Check_FLT_ROUNDS /* If FLT_ROUNDS == 2, L will usually be high by 1 */ if (dval(d) < 0) { L--; dval(d) += ds; } #endif *s++ = '0' + (int)L; if (!dval(d)) { #ifdef SET_INEXACT inexact = 0; #endif break; } if (i == ilim) { #ifdef Honor_FLT_ROUNDS if (mode > 1) switch(rounding) { case 0: goto ret1; case 2: goto bump_up; } #endif dval(d) += dval(d); if (dval(d) > ds || dval(d) == ds && L & 1) { bump_up: while(*--s == '9') if (s == s0) { k++; *s = '0'; break; } ++*s++; } break; } } goto ret1; } m2 = b2; m5 = b5; mhi = mlo = 0; if (leftright) { i = #ifndef Sudden_Underflow denorm ? be + (Bias + (P-1) - 1 + 1) : #endif #ifdef IBM 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); #else 1 + P - bbits; #endif b2 += i; s2 += i; mhi = i2b(1); } if (m2 > 0 && s2 > 0) { i = m2 < s2 ? m2 : s2; b2 -= i; m2 -= i; s2 -= i; } if (b5 > 0) { if (leftright) { if (m5 > 0) { mhi = pow5mult(mhi, m5); b1 = mult(mhi, b); Bfree(b); b = b1; } if (j = b5 - m5) b = pow5mult(b, j); } else b = pow5mult(b, b5); } S = i2b(1); if (s5 > 0) S = pow5mult(S, s5); /* Check for special case that d is a normalized power of 2. */ spec_case = 0; if ((mode < 2 || leftright) #ifdef Honor_FLT_ROUNDS && rounding == 1 #endif ) { if (!word1(d) && !(word0(d) & Bndry_mask) #ifndef Sudden_Underflow && word0(d) & (Exp_mask & ~Exp_msk1) #endif ) { /* The special case */ b2 += Log2P; s2 += Log2P; spec_case = 1; } } /* Arrange for convenient computation of quotients: * shift left if necessary so divisor has 4 leading 0 bits. * * Perhaps we should just compute leading 28 bits of S once * and for all and pass them and a shift to quorem, so it * can do shifts and ors to compute the numerator for q. */ #ifdef Pack_32 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) i = 32 - i; #else if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) i = 16 - i; #endif if (i > 4) { i -= 4; b2 += i; m2 += i; s2 += i; } else if (i < 4) { i += 28; b2 += i; m2 += i; s2 += i; } if (b2 > 0) b = lshift(b, b2); if (s2 > 0) S = lshift(S, s2); if (k_check) { if (cmp(b,S) < 0) { k--; b = multadd(b, 10, 0); /* we botched the k estimate */ if (leftright) mhi = multadd(mhi, 10, 0); ilim = ilim1; } } if (ilim <= 0 && (mode == 3 || mode == 5)) { if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { /* no digits, fcvt style */ no_digits: k = -1 - ndigits; goto ret; } one_digit: *s++ = '1'; k++; goto ret; } if (leftright) { if (m2 > 0) mhi = lshift(mhi, m2); /* Compute mlo -- check for special case * that d is a normalized power of 2. */ mlo = mhi; if (spec_case) { mhi = Balloc(mhi->k); Bcopy(mhi, mlo); mhi = lshift(mhi, Log2P); } for(i = 1;;i++) { dig = quorem(b,S) + '0'; /* Do we yet have the shortest decimal string * that will round to d? */ j = cmp(b, mlo); delta = diff(S, mhi); j1 = delta->sign ? 1 : cmp(b, delta); Bfree(delta); #ifndef ROUND_BIASED if (j1 == 0 && mode != 1 && !(word1(d) & 1) #ifdef Honor_FLT_ROUNDS && rounding >= 1 #endif ) { if (dig == '9') goto round_9_up; if (j > 0) dig++; #ifdef SET_INEXACT else if (!b->x[0] && b->wds <= 1) inexact = 0; #endif *s++ = dig; goto ret; } #endif if (j < 0 || j == 0 && mode != 1 #ifndef ROUND_BIASED && !(word1(d) & 1) #endif ) { if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto accept_dig; } #ifdef Honor_FLT_ROUNDS if (mode > 1) switch(rounding) { case 0: goto accept_dig; case 2: goto keep_dig; } #endif /*Honor_FLT_ROUNDS*/ if (j1 > 0) { b = lshift(b, 1); j1 = cmp(b, S); if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == '9') goto round_9_up; } accept_dig: *s++ = dig; goto ret; } if (j1 > 0) { #ifdef Honor_FLT_ROUNDS if (!rounding) goto accept_dig; #endif if (dig == '9') { /* possible if i == 1 */ round_9_up: *s++ = '9'; goto roundoff; } *s++ = dig + 1; goto ret; } #ifdef Honor_FLT_ROUNDS keep_dig: #endif *s++ = dig; if (i == ilim) break; b = multadd(b, 10, 0); if (mlo == mhi) mlo = mhi = multadd(mhi, 10, 0); else { mlo = multadd(mlo, 10, 0); mhi = multadd(mhi, 10, 0); } } } else for(i = 1;; i++) { *s++ = dig = quorem(b,S) + '0'; if (!b->x[0] && b->wds <= 1) { #ifdef SET_INEXACT inexact = 0; #endif goto ret; } if (i >= ilim) break; b = multadd(b, 10, 0); } /* Round off last digit */ #ifdef Honor_FLT_ROUNDS switch(rounding) { case 0: goto trimzeros; case 2: goto roundoff; } #endif b = lshift(b, 1); j = cmp(b, S); if (j > 0 || j == 0 && dig & 1) { roundoff: while(*--s == '9') if (s == s0) { k++; *s++ = '1'; goto ret; } ++*s++; } else { #ifdef Honor_FLT_ROUNDS trimzeros: #endif while(*--s == '0'); s++; } ret: Bfree(S); if (mhi) { if (mlo && mlo != mhi) Bfree(mlo); Bfree(mhi); } ret1: #ifdef SET_INEXACT if (inexact) { if (!oldinexact) { word0(d) = Exp_1 + (70 << Exp_shift); word1(d) = 0; dval(d) += 1.; } } else if (!oldinexact) clear_inexact(); #endif Bfree(b); *s = 0; *decpt = k + 1; if (rve) *rve = s; return s0; } #ifdef __cplusplus } #endif PR_IMPLEMENT(PRStatus) PR_dtoa(PRFloat64 d, PRIntn mode, PRIntn ndigits, PRIntn *decpt, PRIntn *sign, char **rve, char *buf, PRSize bufsize) { char *result; PRSize resultlen; PRStatus rv = PR_FAILURE; if (!_pr_initialized) _PR_ImplicitInitialization(); if (mode < 0 || mode > 3) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return rv; } result = dtoa(d, mode, ndigits, decpt, sign, rve); if (!result) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return rv; } resultlen = strlen(result)+1; if (bufsize < resultlen) { PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); } else { memcpy(buf, result, resultlen); if (rve) { *rve = buf + (*rve - result); } rv = PR_SUCCESS; } freedtoa(result); return rv; } /* ** conversion routines for floating point ** prcsn - number of digits of precision to generate floating ** point value. ** This should be reparameterized so that you can send in a ** prcn for the positive and negative ranges. For now, ** conform to the ECMA JavaScript spec which says numbers ** less than 1e-6 are in scientific notation. ** Also, the ECMA spec says that there should always be a ** '+' or '-' after the 'e' in scientific notation */ PR_IMPLEMENT(void) PR_cnvtf(char *buf, int bufsz, int prcsn, double dfval) { PRIntn decpt, sign, numdigits; char *num, *nump; char *bufp = buf; char *endnum; U fval; dval(fval) = dfval; /* If anything fails, we store an empty string in 'buf' */ num = (char*)PR_MALLOC(bufsz); if (num == NULL) { buf[0] = '\0'; return; } /* XXX Why use mode 1? */ if (PR_dtoa(dval(fval),1,prcsn,&decpt,&sign,&endnum,num,bufsz) == PR_FAILURE) { buf[0] = '\0'; goto done; } numdigits = endnum - num; nump = num; if (sign && !(word0(fval) == Sign_bit && word1(fval) == 0) && !((word0(fval) & Exp_mask) == Exp_mask && (word1(fval) || (word0(fval) & 0xfffff)))) { *bufp++ = '-'; } if (decpt == 9999) { while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */ goto done; } if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) { *bufp++ = *nump++; if (numdigits != 1) { *bufp++ = '.'; } while (*nump != '\0') { *bufp++ = *nump++; } *bufp++ = 'e'; PR_snprintf(bufp, bufsz - (bufp - buf), "%+d", decpt-1); } else if (decpt >= 0) { if (decpt == 0) { *bufp++ = '0'; } else { while (decpt--) { if (*nump != '\0') { *bufp++ = *nump++; } else { *bufp++ = '0'; } } } if (*nump != '\0') { *bufp++ = '.'; while (*nump != '\0') { *bufp++ = *nump++; } } *bufp++ = '\0'; } else if (decpt < 0) { *bufp++ = '0'; *bufp++ = '.'; while (decpt++) { *bufp++ = '0'; } while (*nump != '\0') { *bufp++ = *nump++; } *bufp++ = '\0'; } done: PR_DELETE(num); } nspr-4.11/nspr/pr/src/misc/prenv.c0000644000000000000000000000645712623070344015207 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "primpl.h" #include "prmem.h" #if defined(XP_UNIX) #if defined(DARWIN) #if defined(HAVE_CRT_EXTERNS_H) #include #endif /* HAVE_CRT_EXTERNS_H */ #else /* DARWIN */ PR_IMPORT_DATA(char **) environ; #endif /* DARWIN */ #endif /* XP_UNIX */ /* Lock used to lock the environment */ #if defined(_PR_NO_PREEMPT) #define _PR_NEW_LOCK_ENV() #define _PR_DELETE_LOCK_ENV() #define _PR_LOCK_ENV() #define _PR_UNLOCK_ENV() #elif defined(_PR_LOCAL_THREADS_ONLY) extern _PRCPU * _pr_primordialCPU; static PRIntn _is; #define _PR_NEW_LOCK_ENV() #define _PR_DELETE_LOCK_ENV() #define _PR_LOCK_ENV() if (_pr_primordialCPU) _PR_INTSOFF(_is); #define _PR_UNLOCK_ENV() if (_pr_primordialCPU) _PR_INTSON(_is); #else static PRLock *_pr_envLock = NULL; #define _PR_NEW_LOCK_ENV() {_pr_envLock = PR_NewLock();} #define _PR_DELETE_LOCK_ENV() \ { if (_pr_envLock) { PR_DestroyLock(_pr_envLock); _pr_envLock = NULL; } } #define _PR_LOCK_ENV() { if (_pr_envLock) PR_Lock(_pr_envLock); } #define _PR_UNLOCK_ENV() { if (_pr_envLock) PR_Unlock(_pr_envLock); } #endif /************************************************************************/ void _PR_InitEnv(void) { _PR_NEW_LOCK_ENV(); } void _PR_CleanupEnv(void) { _PR_DELETE_LOCK_ENV(); } PR_IMPLEMENT(char*) PR_GetEnv(const char *var) { char *ev; if (!_pr_initialized) _PR_ImplicitInitialization(); _PR_LOCK_ENV(); ev = _PR_MD_GET_ENV(var); _PR_UNLOCK_ENV(); return ev; } PR_IMPLEMENT(PRStatus) PR_SetEnv(const char *string) { PRIntn result; if (!_pr_initialized) _PR_ImplicitInitialization(); if (!strchr(string, '=')) return(PR_FAILURE); _PR_LOCK_ENV(); result = _PR_MD_PUT_ENV((char*)string); _PR_UNLOCK_ENV(); return result ? PR_FAILURE : PR_SUCCESS; } #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H)) PR_IMPLEMENT(char **) PR_DuplicateEnvironment(void) { char **the_environ, **result, **end, **src, **dst; _PR_LOCK_ENV(); #ifdef DARWIN the_environ = *(_NSGetEnviron()); #else the_environ = environ; #endif for (end = the_environ; *end != NULL; end++) /* empty loop body */; result = (char **)PR_Malloc(sizeof(char *) * (end - the_environ + 1)); if (result != NULL) { for (src = the_environ, dst = result; src != end; src++, dst++) { size_t len; len = strlen(*src) + 1; *dst = PR_Malloc(len); if (*dst == NULL) { /* Allocation failed. Must clean up the half-copied env. */ char **to_delete; for (to_delete = result; to_delete != dst; to_delete++) { PR_Free(*to_delete); } PR_Free(result); result = NULL; goto out; } memcpy(*dst, *src, len); } *dst = NULL; } out: _PR_UNLOCK_ENV(); return result; } #else /* This platform doesn't support raw access to the environ block. */ PR_IMPLEMENT(char **) PR_DuplicateEnvironment(void) { return NULL; } #endif nspr-4.11/nspr/pr/src/misc/prerr.c0000644000000000000000000001377212623070344015205 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * * prerr.c * This file is automatically generated; please do not edit it. */ #include "prerror.h" static const struct PRErrorMessage text[] = { {"PR_OUT_OF_MEMORY_ERROR", "Memory allocation attempt failed"}, {"PR_BAD_DESCRIPTOR_ERROR", "Invalid file descriptor"}, {"PR_WOULD_BLOCK_ERROR", "The operation would have blocked"}, {"PR_ACCESS_FAULT_ERROR", "Invalid memory address argument"}, {"PR_INVALID_METHOD_ERROR", "Invalid function for file type"}, {"PR_ILLEGAL_ACCESS_ERROR", "Invalid memory address argument"}, {"PR_UNKNOWN_ERROR", "Some unknown error has occurred"}, {"PR_PENDING_INTERRUPT_ERROR", "Operation interrupted by another thread"}, {"PR_NOT_IMPLEMENTED_ERROR", "function not implemented"}, {"PR_IO_ERROR", "I/O function error"}, {"PR_IO_TIMEOUT_ERROR", "I/O operation timed out"}, {"PR_IO_PENDING_ERROR", "I/O operation on busy file descriptor"}, {"PR_DIRECTORY_OPEN_ERROR", "The directory could not be opened"}, {"PR_INVALID_ARGUMENT_ERROR", "Invalid function argument"}, {"PR_ADDRESS_NOT_AVAILABLE_ERROR", "Network address not available (in use?)"}, {"PR_ADDRESS_NOT_SUPPORTED_ERROR", "Network address type not supported"}, {"PR_IS_CONNECTED_ERROR", "Already connected"}, {"PR_BAD_ADDRESS_ERROR", "Network address is invalid"}, {"PR_ADDRESS_IN_USE_ERROR", "Local Network address is in use"}, {"PR_CONNECT_REFUSED_ERROR", "Connection refused by peer"}, {"PR_NETWORK_UNREACHABLE_ERROR", "Network address is presently unreachable"}, {"PR_CONNECT_TIMEOUT_ERROR", "Connection attempt timed out"}, {"PR_NOT_CONNECTED_ERROR", "Network file descriptor is not connected"}, {"PR_LOAD_LIBRARY_ERROR", "Failure to load dynamic library"}, {"PR_UNLOAD_LIBRARY_ERROR", "Failure to unload dynamic library"}, {"PR_FIND_SYMBOL_ERROR", "Symbol not found in any of the loaded dynamic libraries"}, {"PR_INSUFFICIENT_RESOURCES_ERROR", "Insufficient system resources"}, {"PR_DIRECTORY_LOOKUP_ERROR", "A directory lookup on a network address has failed"}, {"PR_TPD_RANGE_ERROR", "Attempt to access a TPD key that is out of range"}, {"PR_PROC_DESC_TABLE_FULL_ERROR", "Process open FD table is full"}, {"PR_SYS_DESC_TABLE_FULL_ERROR", "System open FD table is full"}, {"PR_NOT_SOCKET_ERROR", "Network operation attempted on non-network file descriptor"}, {"PR_NOT_TCP_SOCKET_ERROR", "TCP-specific function attempted on a non-TCP file descriptor"}, {"PR_SOCKET_ADDRESS_IS_BOUND_ERROR", "TCP file descriptor is already bound"}, {"PR_NO_ACCESS_RIGHTS_ERROR", "Access Denied"}, {"PR_OPERATION_NOT_SUPPORTED_ERROR", "The requested operation is not supported by the platform"}, {"PR_PROTOCOL_NOT_SUPPORTED_ERROR", "The host operating system does not support the protocol requested"}, {"PR_REMOTE_FILE_ERROR", "Access to the remote file has been severed"}, {"PR_BUFFER_OVERFLOW_ERROR", "The value requested is too large to be stored in the data buffer provided"}, {"PR_CONNECT_RESET_ERROR", "TCP connection reset by peer"}, {"PR_RANGE_ERROR", "Unused"}, {"PR_DEADLOCK_ERROR", "The operation would have deadlocked"}, {"PR_FILE_IS_LOCKED_ERROR", "The file is already locked"}, {"PR_FILE_TOO_BIG_ERROR", "Write would result in file larger than the system allows"}, {"PR_NO_DEVICE_SPACE_ERROR", "The device for storing the file is full"}, {"PR_PIPE_ERROR", "Unused"}, {"PR_NO_SEEK_DEVICE_ERROR", "Unused"}, {"PR_IS_DIRECTORY_ERROR", "Cannot perform a normal file operation on a directory"}, {"PR_LOOP_ERROR", "Symbolic link loop"}, {"PR_NAME_TOO_LONG_ERROR", "File name is too long"}, {"PR_FILE_NOT_FOUND_ERROR", "File not found"}, {"PR_NOT_DIRECTORY_ERROR", "Cannot perform directory operation on a normal file"}, {"PR_READ_ONLY_FILESYSTEM_ERROR", "Cannot write to a read-only file system"}, {"PR_DIRECTORY_NOT_EMPTY_ERROR", "Cannot delete a directory that is not empty"}, {"PR_FILESYSTEM_MOUNTED_ERROR", "Cannot delete or rename a file object while the file system is busy"}, {"PR_NOT_SAME_DEVICE_ERROR", "Cannot rename a file to a file system on another device"}, {"PR_DIRECTORY_CORRUPTED_ERROR", "The directory object in the file system is corrupted"}, {"PR_FILE_EXISTS_ERROR", "Cannot create or rename a filename that already exists"}, {"PR_MAX_DIRECTORY_ENTRIES_ERROR", "Directory is full. No additional filenames may be added"}, {"PR_INVALID_DEVICE_STATE_ERROR", "The required device was in an invalid state"}, {"PR_DEVICE_IS_LOCKED_ERROR", "The device is locked"}, {"PR_NO_MORE_FILES_ERROR", "No more entries in the directory"}, {"PR_END_OF_FILE_ERROR", "Encountered end of file"}, {"PR_FILE_SEEK_ERROR", "Seek error"}, {"PR_FILE_IS_BUSY_ERROR", "The file is busy"}, {"PR_OPERATION_ABORTED_ERROR", "The I/O operation was aborted"}, {"PR_IN_PROGRESS_ERROR", "Operation is still in progress (probably a non-blocking connect)"}, {"PR_ALREADY_INITIATED_ERROR", "Operation has already been initiated (probably a non-blocking connect)"}, {"PR_GROUP_EMPTY_ERROR", "The wait group is empty"}, {"PR_INVALID_STATE_ERROR", "Object state improper for request"}, {"PR_NETWORK_DOWN_ERROR", "Network is down"}, {"PR_SOCKET_SHUTDOWN_ERROR", "Socket shutdown"}, {"PR_CONNECT_ABORTED_ERROR", "Connection aborted"}, {"PR_HOST_UNREACHABLE_ERROR", "Host is unreachable"}, {"PR_LIBRARY_NOT_LOADED_ERROR", "The library is not loaded"}, {"PR_CALL_ONCE_ERROR", "The one-time function was previously called and failed. Its error code is no longer available"}, {"PR_MAX_ERROR", "Placeholder for the end of the list"}, {0, 0} }; static const struct PRErrorTable et = { text, "prerr", -6000L, 77 }; void nspr_InitializePRErrorTable(void) { PR_ErrorInstallTable(&et); } nspr-4.11/nspr/pr/src/misc/prerr.et0000644000000000000000000001266712623070344015375 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. et nspr -6000 ec PR_OUT_OF_MEMORY_ERROR, "Memory allocation attempt failed" ec PR_BAD_DESCRIPTOR_ERROR, "Invalid file descriptor" ec PR_WOULD_BLOCK_ERROR, "The operation would have blocked" ec PR_ACCESS_FAULT_ERROR, "Invalid memory address argument" ec PR_INVALID_METHOD_ERROR, "Invalid function for file type" ec PR_ILLEGAL_ACCESS_ERROR, "Invalid memory address argument" ec PR_UNKNOWN_ERROR, "Some unknown error has occurred" ec PR_PENDING_INTERRUPT_ERROR,"Operation interrupted by another thread" ec PR_NOT_IMPLEMENTED_ERROR, "function not implemented" ec PR_IO_ERROR, "I/O function error" ec PR_IO_TIMEOUT_ERROR, "I/O operation timed out" ec PR_IO_PENDING_ERROR, "I/O operation on busy file descriptor" ec PR_DIRECTORY_OPEN_ERROR, "The directory could not be opened" ec PR_INVALID_ARGUMENT_ERROR, "Invalid function argument" ec PR_ADDRESS_NOT_AVAILABLE_ERROR, "Network address not available (in use?)" ec PR_ADDRESS_NOT_SUPPORTED_ERROR, "Network address type not supported" ec PR_IS_CONNECTED_ERROR, "Already connected" ec PR_BAD_ADDRESS_ERROR, "Network address is invalid" ec PR_ADDRESS_IN_USE_ERROR, "Local Network address is in use" ec PR_CONNECT_REFUSED_ERROR, "Connection refused by peer" ec PR_NETWORK_UNREACHABLE_ERROR, "Network address is presently unreachable" ec PR_CONNECT_TIMEOUT_ERROR, "Connection attempt timed out" ec PR_NOT_CONNECTED_ERROR, "Network file descriptor is not connected" ec PR_LOAD_LIBRARY_ERROR, "Failure to load dynamic library" ec PR_UNLOAD_LIBRARY_ERROR, "Failure to unload dynamic library" ec PR_FIND_SYMBOL_ERROR, "Symbol not found in any of the loaded dynamic libraries" ec PR_INSUFFICIENT_RESOURCES_ERROR, "Insufficient system resources" ec PR_DIRECTORY_LOOKUP_ERROR, "A directory lookup on a network address has failed" ec PR_TPD_RANGE_ERROR, "Attempt to access a TPD key that is out of range" ec PR_PROC_DESC_TABLE_FULL_ERROR, "Process open FD table is full" ec PR_SYS_DESC_TABLE_FULL_ERROR, "System open FD table is full" ec PR_NOT_SOCKET_ERROR, "Network operation attempted on non-network file descriptor" ec PR_NOT_TCP_SOCKET_ERROR, "TCP-specific function attempted on a non-TCP file descriptor" ec PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "TCP file descriptor is already bound" ec PR_NO_ACCESS_RIGHTS_ERROR, "Access Denied" ec PR_OPERATION_NOT_SUPPORTED_ERROR, "The requested operation is not supported by the platform" ec PR_PROTOCOL_NOT_SUPPORTED_ERROR, "The host operating system does not support the protocol requested" ec PR_REMOTE_FILE_ERROR, "Access to the remote file has been severed" ec PR_BUFFER_OVERFLOW_ERROR, "The value requested is too large to be stored in the data buffer provided" ec PR_CONNECT_RESET_ERROR, "TCP connection reset by peer" ec PR_RANGE_ERROR, "Unused" ec PR_DEADLOCK_ERROR, "The operation would have deadlocked" ec PR_FILE_IS_LOCKED_ERROR, "The file is already locked" ec PR_FILE_TOO_BIG_ERROR, "Write would result in file larger than the system allows" ec PR_NO_DEVICE_SPACE_ERROR, "The device for storing the file is full" ec PR_PIPE_ERROR, "Unused" ec PR_NO_SEEK_DEVICE_ERROR, "Unused" ec PR_IS_DIRECTORY_ERROR, "Cannot perform a normal file operation on a directory" ec PR_LOOP_ERROR, "Symbolic link loop" ec PR_NAME_TOO_LONG_ERROR, "File name is too long" ec PR_FILE_NOT_FOUND_ERROR, "File not found" ec PR_NOT_DIRECTORY_ERROR, "Cannot perform directory operation on a normal file" ec PR_READ_ONLY_FILESYSTEM_ERROR, "Cannot write to a read-only file system" ec PR_DIRECTORY_NOT_EMPTY_ERROR, "Cannot delete a directory that is not empty" ec PR_FILESYSTEM_MOUNTED_ERROR, "Cannot delete or rename a file object while the file system is busy" ec PR_NOT_SAME_DEVICE_ERROR, "Cannot rename a file to a file system on another device" ec PR_DIRECTORY_CORRUPTED_ERROR, "The directory object in the file system is corrupted" ec PR_FILE_EXISTS_ERROR, "Cannot create or rename a filename that already exists" ec PR_MAX_DIRECTORY_ENTRIES_ERROR, "Directory is full. No additional filenames may be added" ec PR_INVALID_DEVICE_STATE_ERROR, "The required device was in an invalid state" ec PR_DEVICE_IS_LOCKED_ERROR, "The device is locked" ec PR_NO_MORE_FILES_ERROR, "No more entries in the directory" ec PR_END_OF_FILE_ERROR, "Encountered end of file" ec PR_FILE_SEEK_ERROR, "Seek error" ec PR_FILE_IS_BUSY_ERROR, "The file is busy" ec PR_OPERATION_ABORTED_ERROR, "The I/O operation was aborted" ec PR_IN_PROGRESS_ERROR, "Operation is still in progress (probably a non-blocking connect)" ec PR_ALREADY_INITIATED_ERROR, "Operation has already been initiated (probably a non-blocking connect)" ec PR_GROUP_EMPTY_ERROR, "The wait group is empty" ec PR_INVALID_STATE_ERROR, "Object state improper for request" ec PR_NETWORK_DOWN_ERROR, "Network is down" ec PR_SOCKET_SHUTDOWN_ERROR, "Socket shutdown" ec PR_CONNECT_ABORTED_ERROR, "Connection aborted" ec PR_HOST_UNREACHABLE_ERROR, "Host is unreachable" ec PR_LIBRARY_NOT_LOADED_ERROR, "The library is not loaded" ec PR_CALL_ONCE_ERROR, "The one-time function was previously called and failed. Its error code is no longer available" ec PR_MAX_ERROR, "Placeholder for the end of the list" end nspr-4.11/nspr/pr/src/misc/prerr.properties0000644000000000000000000001145312623070344017151 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # prerr.properties # This file is automatically generated; please do not edit it. PR_OUT_OF_MEMORY_ERROR=Memory allocation attempt failed PR_BAD_DESCRIPTOR_ERROR=Invalid file descriptor PR_WOULD_BLOCK_ERROR=The operation would have blocked PR_ACCESS_FAULT_ERROR=Invalid memory address argument PR_INVALID_METHOD_ERROR=Invalid function for file type PR_ILLEGAL_ACCESS_ERROR=Invalid memory address argument PR_UNKNOWN_ERROR=Some unknown error has occurred PR_PENDING_INTERRUPT_ERROR=Operation interrupted by another thread PR_NOT_IMPLEMENTED_ERROR=function not implemented PR_IO_ERROR=I/O function error PR_IO_TIMEOUT_ERROR=I/O operation timed out PR_IO_PENDING_ERROR=I/O operation on busy file descriptor PR_DIRECTORY_OPEN_ERROR=The directory could not be opened PR_INVALID_ARGUMENT_ERROR=Invalid function argument PR_ADDRESS_NOT_AVAILABLE_ERROR=Network address not available (in use?) PR_ADDRESS_NOT_SUPPORTED_ERROR=Network address type not supported PR_IS_CONNECTED_ERROR=Already connected PR_BAD_ADDRESS_ERROR=Network address is invalid PR_ADDRESS_IN_USE_ERROR=Local Network address is in use PR_CONNECT_REFUSED_ERROR=Connection refused by peer PR_NETWORK_UNREACHABLE_ERROR=Network address is presently unreachable PR_CONNECT_TIMEOUT_ERROR=Connection attempt timed out PR_NOT_CONNECTED_ERROR=Network file descriptor is not connected PR_LOAD_LIBRARY_ERROR=Failure to load dynamic library PR_UNLOAD_LIBRARY_ERROR=Failure to unload dynamic library PR_FIND_SYMBOL_ERROR=Symbol not found in any of the loaded dynamic libraries PR_INSUFFICIENT_RESOURCES_ERROR=Insufficient system resources PR_DIRECTORY_LOOKUP_ERROR=A directory lookup on a network address has failed PR_TPD_RANGE_ERROR=Attempt to access a TPD key that is out of range PR_PROC_DESC_TABLE_FULL_ERROR=Process open FD table is full PR_SYS_DESC_TABLE_FULL_ERROR=System open FD table is full PR_NOT_SOCKET_ERROR=Network operation attempted on non-network file descriptor PR_NOT_TCP_SOCKET_ERROR=TCP-specific function attempted on a non-TCP file descriptor PR_SOCKET_ADDRESS_IS_BOUND_ERROR=TCP file descriptor is already bound PR_NO_ACCESS_RIGHTS_ERROR=Access Denied PR_OPERATION_NOT_SUPPORTED_ERROR=The requested operation is not supported by the platform PR_PROTOCOL_NOT_SUPPORTED_ERROR=The host operating system does not support the protocol requested PR_REMOTE_FILE_ERROR=Access to the remote file has been severed PR_BUFFER_OVERFLOW_ERROR=The value requested is too large to be stored in the data buffer provided PR_CONNECT_RESET_ERROR=TCP connection reset by peer PR_RANGE_ERROR=Unused PR_DEADLOCK_ERROR=The operation would have deadlocked PR_FILE_IS_LOCKED_ERROR=The file is already locked PR_FILE_TOO_BIG_ERROR=Write would result in file larger than the system allows PR_NO_DEVICE_SPACE_ERROR=The device for storing the file is full PR_PIPE_ERROR=Unused PR_NO_SEEK_DEVICE_ERROR=Unused PR_IS_DIRECTORY_ERROR=Cannot perform a normal file operation on a directory PR_LOOP_ERROR=Symbolic link loop PR_NAME_TOO_LONG_ERROR=File name is too long PR_FILE_NOT_FOUND_ERROR=File not found PR_NOT_DIRECTORY_ERROR=Cannot perform directory operation on a normal file PR_READ_ONLY_FILESYSTEM_ERROR=Cannot write to a read-only file system PR_DIRECTORY_NOT_EMPTY_ERROR=Cannot delete a directory that is not empty PR_FILESYSTEM_MOUNTED_ERROR=Cannot delete or rename a file object while the file system is busy PR_NOT_SAME_DEVICE_ERROR=Cannot rename a file to a file system on another device PR_DIRECTORY_CORRUPTED_ERROR=The directory object in the file system is corrupted PR_FILE_EXISTS_ERROR=Cannot create or rename a filename that already exists PR_MAX_DIRECTORY_ENTRIES_ERROR=Directory is full. No additional filenames may be added PR_INVALID_DEVICE_STATE_ERROR=The required device was in an invalid state PR_DEVICE_IS_LOCKED_ERROR=The device is locked PR_NO_MORE_FILES_ERROR=No more entries in the directory PR_END_OF_FILE_ERROR=Encountered end of file PR_FILE_SEEK_ERROR=Seek error PR_FILE_IS_BUSY_ERROR=The file is busy PR_OPERATION_ABORTED_ERROR=The I/O operation was aborted PR_IN_PROGRESS_ERROR=Operation is still in progress (probably a non-blocking connect) PR_ALREADY_INITIATED_ERROR=Operation has already been initiated (probably a non-blocking connect) PR_GROUP_EMPTY_ERROR=The wait group is empty PR_INVALID_STATE_ERROR=Object state improper for request PR_NETWORK_DOWN_ERROR=Network is down PR_SOCKET_SHUTDOWN_ERROR=Socket shutdown PR_CONNECT_ABORTED_ERROR=Connection aborted PR_HOST_UNREACHABLE_ERROR=Host is unreachable PR_LIBRARY_NOT_LOADED_ERROR=The library is not loaded PR_CALL_ONCE_ERROR=The one-time function was previously called and failed. Its error code is no longer available PR_MAX_ERROR=Placeholder for the end of the list nspr-4.11/nspr/pr/src/misc/prerror.c0000644000000000000000000000422412623070344015536 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include PR_IMPLEMENT(PRErrorCode) PR_GetError(void) { PRThread *thread = PR_GetCurrentThread(); return thread->errorCode; } PR_IMPLEMENT(PRInt32) PR_GetOSError(void) { PRThread *thread = PR_GetCurrentThread(); return thread->osErrorCode; } PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr) { PRThread *thread = PR_GetCurrentThread(); thread->errorCode = code; thread->osErrorCode = osErr; thread->errorStringLength = 0; } PR_IMPLEMENT(void) PR_SetErrorText(PRIntn textLength, const char *text) { PRThread *thread = PR_GetCurrentThread(); if (0 == textLength) { if (NULL != thread->errorString) PR_DELETE(thread->errorString); thread->errorStringSize = 0; } else { PRIntn size = textLength + 31; /* actual length to allocate. Plus a little extra */ if (thread->errorStringSize < textLength+1) /* do we have room? */ { if (NULL != thread->errorString) PR_DELETE(thread->errorString); thread->errorString = (char*)PR_MALLOC(size); if ( NULL == thread->errorString ) { thread->errorStringSize = 0; thread->errorStringLength = 0; return; } thread->errorStringSize = size; } memcpy(thread->errorString, text, textLength+1 ); } thread->errorStringLength = textLength; } PR_IMPLEMENT(PRInt32) PR_GetErrorTextLength(void) { PRThread *thread = PR_GetCurrentThread(); return thread->errorStringLength; } /* PR_GetErrorTextLength */ PR_IMPLEMENT(PRInt32) PR_GetErrorText(char *text) { PRThread *thread = PR_GetCurrentThread(); if (0 != thread->errorStringLength) memcpy(text, thread->errorString, thread->errorStringLength+1); return thread->errorStringLength; } /* PR_GetErrorText */ nspr-4.11/nspr/pr/src/misc/prerrortable.c0000644000000000000000000001270512623070344016551 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Copyright 1987, 1988 by the Student Information Processing Board of the Massachusetts Institute of Technology Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ #include #include #include #include "prmem.h" #include "prerror.h" #define ERRCODE_RANGE 8 /* # of bits to shift table number */ #define BITS_PER_CHAR 6 /* # bits to shift per character in name */ #ifdef NEED_SYS_ERRLIST extern char const * const sys_errlist[]; extern const int sys_nerr; #endif /* List of error tables */ struct PRErrorTableList { struct PRErrorTableList *next; const struct PRErrorTable *table; struct PRErrorCallbackTablePrivate *table_private; }; static struct PRErrorTableList * Table_List = (struct PRErrorTableList *) NULL; /* Supported languages */ static const char * default_languages[] = { "i-default", "en", 0 }; static const char * const * callback_languages = default_languages; /* Callback info */ static struct PRErrorCallbackPrivate *callback_private = 0; static PRErrorCallbackLookupFn *callback_lookup = 0; static PRErrorCallbackNewTableFn *callback_newtable = 0; static const char char_set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; static const char * error_table_name (PRErrorCode num) { static char buf[6]; /* only used if internal code problems exist */ long ch; int i; char *p; /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */ p = buf; num >>= ERRCODE_RANGE; /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */ num &= 077777777; /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */ for (i = 4; i >= 0; i--) { ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1); if (ch != 0) *p++ = char_set[ch-1]; } *p = '\0'; return(buf); } PR_IMPLEMENT(const char *) PR_ErrorToString(PRErrorCode code, PRLanguageCode language) { /* static buffer only used if code is using inconsistent error message * numbers, so just ignore the possible thread contention */ static char buffer[25]; const char *msg; int offset; PRErrorCode table_num; struct PRErrorTableList *et; int started = 0; char *cp; for (et = Table_List; et; et = et->next) { if (et->table->base <= code && et->table->base + et->table->n_msgs > code) { /* This is the right table */ if (callback_lookup) { msg = callback_lookup(code, language, et->table, callback_private, et->table_private); if (msg) return msg; } return(et->table->msgs[code - et->table->base].en_text); } } if (code >= 0 && code < 256) { return strerror(code); } offset = (int) (code & ((1<= 100) { *cp++ = (char)('0' + offset / 100); offset %= 100; started++; } if (started || offset >= 10) { *cp++ = (char)('0' + offset / 10); offset %= 10; } *cp++ = (char)('0' + offset); *cp = '\0'; return(buffer); } PR_IMPLEMENT(const char *) PR_ErrorToName(PRErrorCode code) { struct PRErrorTableList *et; for (et = Table_List; et; et = et->next) { if (et->table->base <= code && et->table->base + et->table->n_msgs > code) { /* This is the right table */ return(et->table->msgs[code - et->table->base].name); } } return 0; } PR_IMPLEMENT(const char * const *) PR_ErrorLanguages(void) { return callback_languages; } PR_IMPLEMENT(PRErrorCode) PR_ErrorInstallTable(const struct PRErrorTable *table) { struct PRErrorTableList * new_et; new_et = (struct PRErrorTableList *) PR_Malloc(sizeof(struct PRErrorTableList)); if (!new_et) return errno; /* oops */ new_et->table = table; if (callback_newtable) { new_et->table_private = callback_newtable(table, callback_private); } else { new_et->table_private = 0; } new_et->next = Table_List; Table_List = new_et; return 0; } PR_IMPLEMENT(void) PR_ErrorInstallCallback(const char * const * languages, PRErrorCallbackLookupFn *lookup, PRErrorCallbackNewTableFn *newtable, struct PRErrorCallbackPrivate *cb_private) { struct PRErrorTableList *et; assert(strcmp(languages[0], "i-default") == 0); assert(strcmp(languages[1], "en") == 0); callback_languages = languages; callback_lookup = lookup; callback_newtable = newtable; callback_private = cb_private; if (callback_newtable) { for (et = Table_List; et; et = et->next) { et->table_private = callback_newtable(et->table, callback_private); } } } nspr-4.11/nspr/pr/src/misc/prinit.c0000644000000000000000000005302112623070344015347 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include PRLogModuleInfo *_pr_clock_lm; PRLogModuleInfo *_pr_cmon_lm; PRLogModuleInfo *_pr_io_lm; PRLogModuleInfo *_pr_cvar_lm; PRLogModuleInfo *_pr_mon_lm; PRLogModuleInfo *_pr_linker_lm; PRLogModuleInfo *_pr_sched_lm; PRLogModuleInfo *_pr_thread_lm; PRLogModuleInfo *_pr_gc_lm; PRLogModuleInfo *_pr_shm_lm; PRLogModuleInfo *_pr_shma_lm; PRFileDesc *_pr_stdin; PRFileDesc *_pr_stdout; PRFileDesc *_pr_stderr; #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) PRCList _pr_active_local_threadQ = PR_INIT_STATIC_CLIST(&_pr_active_local_threadQ); PRCList _pr_active_global_threadQ = PR_INIT_STATIC_CLIST(&_pr_active_global_threadQ); _MDLock _pr_cpuLock; /* lock for the CPU Q */ PRCList _pr_cpuQ = PR_INIT_STATIC_CLIST(&_pr_cpuQ); PRUint32 _pr_utid; PRInt32 _pr_userActive; PRInt32 _pr_systemActive; PRUintn _pr_maxPTDs; #ifdef _PR_LOCAL_THREADS_ONLY struct _PRCPU *_pr_currentCPU; PRThread *_pr_currentThread; PRThread *_pr_lastThread; PRInt32 _pr_intsOff; #endif /* _PR_LOCAL_THREADS_ONLY */ /* Lock protecting all "termination" condition variables of all threads */ PRLock *_pr_terminationCVLock; #endif /* !defined(_PR_PTHREADS) */ PRLock *_pr_sleeplock; /* used in PR_Sleep(), classic and pthreads */ static void _PR_InitCallOnce(void); PRBool _pr_initialized = PR_FALSE; PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion) { /* ** This is the secret handshake algorithm. ** ** This release has a simple version compatibility ** check algorithm. This release is not backward ** compatible with previous major releases. It is ** not compatible with future major, minor, or ** patch releases. */ int vmajor = 0, vminor = 0, vpatch = 0; const char *ptr = importedVersion; while (isdigit(*ptr)) { vmajor = 10 * vmajor + *ptr - '0'; ptr++; } if (*ptr == '.') { ptr++; while (isdigit(*ptr)) { vminor = 10 * vminor + *ptr - '0'; ptr++; } if (*ptr == '.') { ptr++; while (isdigit(*ptr)) { vpatch = 10 * vpatch + *ptr - '0'; ptr++; } } } if (vmajor != PR_VMAJOR) { return PR_FALSE; } if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) { return PR_FALSE; } if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) { return PR_FALSE; } return PR_TRUE; } /* PR_VersionCheck */ PR_IMPLEMENT(const char*) PR_GetVersion(void) { return PR_VERSION; } PR_IMPLEMENT(PRBool) PR_Initialized(void) { return _pr_initialized; } PRInt32 _native_threads_only = 0; #ifdef WINNT static void _pr_SetNativeThreadsOnlyMode(void) { HMODULE mainExe; PRBool *globalp; char *envp; mainExe = GetModuleHandle(NULL); PR_ASSERT(NULL != mainExe); globalp = (PRBool *) GetProcAddress(mainExe, "nspr_native_threads_only"); if (globalp) { _native_threads_only = (*globalp != PR_FALSE); } else if (envp = getenv("NSPR_NATIVE_THREADS_ONLY")) { _native_threads_only = (atoi(envp) == 1); } } #endif static void _PR_InitStuff(void) { if (_pr_initialized) return; _pr_initialized = PR_TRUE; #ifdef _PR_ZONE_ALLOCATOR _PR_InitZones(); #endif #ifdef WINNT _pr_SetNativeThreadsOnlyMode(); #endif (void) PR_GetPageSize(); _pr_clock_lm = PR_NewLogModule("clock"); _pr_cmon_lm = PR_NewLogModule("cmon"); _pr_io_lm = PR_NewLogModule("io"); _pr_mon_lm = PR_NewLogModule("mon"); _pr_linker_lm = PR_NewLogModule("linker"); _pr_cvar_lm = PR_NewLogModule("cvar"); _pr_sched_lm = PR_NewLogModule("sched"); _pr_thread_lm = PR_NewLogModule("thread"); _pr_gc_lm = PR_NewLogModule("gc"); _pr_shm_lm = PR_NewLogModule("shm"); _pr_shma_lm = PR_NewLogModule("shma"); /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */ _PR_MD_EARLY_INIT(); _PR_InitLocks(); _PR_InitAtomic(); _PR_InitSegs(); _PR_InitStacks(); _PR_InitTPD(); _PR_InitEnv(); _PR_InitLayerCache(); _PR_InitClock(); _pr_sleeplock = PR_NewLock(); PR_ASSERT(NULL != _pr_sleeplock); _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); #ifdef WIN16 { PRInt32 top; /* artificial top of stack, win16 */ _pr_top_of_task_stack = (char *) ⊤ } #endif #ifndef _PR_GLOBAL_THREADS_ONLY _PR_InitCPUs(); #endif /* * XXX: call _PR_InitMem only on those platforms for which nspr implements * malloc, for now. */ #ifdef _PR_OVERRIDE_MALLOC _PR_InitMem(); #endif _PR_InitCMon(); _PR_InitIO(); _PR_InitNet(); _PR_InitTime(); _PR_InitLog(); _PR_InitLinker(); _PR_InitCallOnce(); _PR_InitDtoa(); _PR_InitMW(); _PR_InitRWLocks(); nspr_InitializePRErrorTable(); _PR_MD_FINAL_INIT(); } void _PR_ImplicitInitialization(void) { _PR_InitStuff(); /* Enable interrupts */ #if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY) _PR_MD_START_INTERRUPTS(); #endif } PR_IMPLEMENT(void) PR_DisableClockInterrupts(void) { #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) if (!_pr_initialized) { _PR_InitStuff(); } else { _PR_MD_DISABLE_CLOCK_INTERRUPTS(); } #endif } PR_IMPLEMENT(void) PR_EnableClockInterrupts(void) { #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) if (!_pr_initialized) { _PR_InitStuff(); } _PR_MD_ENABLE_CLOCK_INTERRUPTS(); #endif } PR_IMPLEMENT(void) PR_BlockClockInterrupts(void) { #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) _PR_MD_BLOCK_CLOCK_INTERRUPTS(); #endif } PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void) { #if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(); #endif } PR_IMPLEMENT(void) PR_Init( PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) { _PR_ImplicitInitialization(); } PR_IMPLEMENT(PRIntn) PR_Initialize( PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs) { PRIntn rv; _PR_ImplicitInitialization(); rv = prmain(argc, argv); PR_Cleanup(); return rv; } /* PR_Initialize */ /* *----------------------------------------------------------------------- * * _PR_CleanupBeforeExit -- * * Perform the cleanup work before exiting the process. * We first do the cleanup generic to all platforms. Then * we call _PR_MD_CLEANUP_BEFORE_EXIT(), where platform-dependent * cleanup is done. This function is used by PR_Cleanup(). * * See also: PR_Cleanup(). * *----------------------------------------------------------------------- */ #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) /* see ptthread.c */ #else static void _PR_CleanupBeforeExit(void) { /* Do not make any calls here other than to destroy resources. For example, do not make any calls that eventually may end up in PR_Lock. Because the thread is destroyed, can not access current thread any more. */ _PR_CleanupTPD(); if (_pr_terminationCVLock) /* * In light of the comment above, this looks real suspicious. * I'd go so far as to say it's just a problem waiting to happen. */ PR_DestroyLock(_pr_terminationCVLock); _PR_MD_CLEANUP_BEFORE_EXIT(); } #endif /* defined(_PR_PTHREADS) */ /* *---------------------------------------------------------------------- * * PR_Cleanup -- * * Perform a graceful shutdown of the NSPR runtime. PR_Cleanup() may * only be called from the primordial thread, typically at the * end of the main() function. It returns when it has completed * its platform-dependent duty and the process must not make any other * NSPR library calls prior to exiting from main(). * * PR_Cleanup() first blocks the primordial thread until all the * other user (non-system) threads, if any, have terminated. * Then it performs cleanup in preparation for exiting the process. * PR_Cleanup() does not exit the primordial thread (which would * in turn exit the process). * * PR_Cleanup() only responds when it is called by the primordial * thread. Calls by any other thread are silently ignored. * * See also: PR_ExitProcess() * *---------------------------------------------------------------------- */ #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) /* see ptthread.c */ #else PR_IMPLEMENT(PRStatus) PR_Cleanup() { PRThread *me = PR_GetCurrentThread(); PR_ASSERT((NULL != me) && (me->flags & _PR_PRIMORDIAL)); if ((NULL != me) && (me->flags & _PR_PRIMORDIAL)) { PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); /* * No more recycling of threads */ _pr_recycleThreads = 0; /* * Wait for all other user (non-system/daemon) threads * to terminate. */ PR_Lock(_pr_activeLock); while (_pr_userActive > _pr_primordialExitCount) { PR_WaitCondVar(_pr_primordialExitCVar, PR_INTERVAL_NO_TIMEOUT); } if (me->flags & _PR_SYSTEM) { _pr_systemActive--; } else { _pr_userActive--; } PR_Unlock(_pr_activeLock); #ifdef IRIX _PR_MD_PRE_CLEANUP(me); /* * The primordial thread must now be running on the primordial cpu */ PR_ASSERT((_PR_IS_NATIVE_THREAD(me)) || (me->cpu->id == 0)); #endif _PR_MD_EARLY_CLEANUP(); _PR_CleanupMW(); _PR_CleanupTime(); _PR_CleanupDtoa(); _PR_CleanupCallOnce(); _PR_ShutdownLinker(); _PR_CleanupNet(); _PR_CleanupIO(); /* Release the primordial thread's private data, etc. */ _PR_CleanupThread(me); _PR_MD_STOP_INTERRUPTS(); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: clean up before destroying thread")); _PR_LogCleanup(); /* * This part should look like the end of _PR_NativeRunThread * and _PR_UserRunThread. */ if (_PR_IS_NATIVE_THREAD(me)) { _PR_MD_EXIT_THREAD(me); _PR_NativeDestroyThread(me); } else { _PR_UserDestroyThread(me); PR_DELETE(me->stack); PR_DELETE(me); } /* * XXX: We are freeing the heap memory here so that Purify won't * complain, but we should also free other kinds of resources * that are allocated by the _PR_InitXXX() functions. * Ideally, for each _PR_InitXXX(), there should be a corresponding * _PR_XXXCleanup() that we can call here. */ #ifdef WINNT _PR_CleanupCPUs(); #endif _PR_CleanupThreads(); _PR_CleanupCMon(); PR_DestroyLock(_pr_sleeplock); _pr_sleeplock = NULL; _PR_CleanupLayerCache(); _PR_CleanupEnv(); _PR_CleanupStacks(); _PR_CleanupBeforeExit(); _pr_initialized = PR_FALSE; return PR_SUCCESS; } return PR_FAILURE; } #endif /* defined(_PR_PTHREADS) */ /* *------------------------------------------------------------------------ * PR_ProcessExit -- * * Cause an immediate, nongraceful, forced termination of the process. * It takes a PRIntn argument, which is the exit status code of the * process. * * See also: PR_Cleanup() * *------------------------------------------------------------------------ */ #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS) /* see ptthread.c */ #else PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status) { _PR_MD_EXIT(status); } #endif /* defined(_PR_PTHREADS) */ PR_IMPLEMENT(PRProcessAttr *) PR_NewProcessAttr(void) { PRProcessAttr *attr; attr = PR_NEWZAP(PRProcessAttr); if (!attr) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return attr; } PR_IMPLEMENT(void) PR_ResetProcessAttr(PRProcessAttr *attr) { PR_FREEIF(attr->currentDirectory); PR_FREEIF(attr->fdInheritBuffer); memset(attr, 0, sizeof(*attr)); } PR_IMPLEMENT(void) PR_DestroyProcessAttr(PRProcessAttr *attr) { PR_FREEIF(attr->currentDirectory); PR_FREEIF(attr->fdInheritBuffer); PR_DELETE(attr); } PR_IMPLEMENT(void) PR_ProcessAttrSetStdioRedirect( PRProcessAttr *attr, PRSpecialFD stdioFd, PRFileDesc *redirectFd) { switch (stdioFd) { case PR_StandardInput: attr->stdinFd = redirectFd; break; case PR_StandardOutput: attr->stdoutFd = redirectFd; break; case PR_StandardError: attr->stderrFd = redirectFd; break; default: PR_ASSERT(0); } } /* * OBSOLETE */ PR_IMPLEMENT(void) PR_SetStdioRedirect( PRProcessAttr *attr, PRSpecialFD stdioFd, PRFileDesc *redirectFd) { #if defined(DEBUG) static PRBool warn = PR_TRUE; if (warn) { warn = _PR_Obsolete("PR_SetStdioRedirect()", "PR_ProcessAttrSetStdioRedirect()"); } #endif PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd); } PR_IMPLEMENT(PRStatus) PR_ProcessAttrSetCurrentDirectory( PRProcessAttr *attr, const char *dir) { PR_FREEIF(attr->currentDirectory); attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1); if (!attr->currentDirectory) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return PR_FAILURE; } strcpy(attr->currentDirectory, dir); return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_ProcessAttrSetInheritableFD( PRProcessAttr *attr, PRFileDesc *fd, const char *name) { /* We malloc the fd inherit buffer in multiples of this number. */ #define FD_INHERIT_BUFFER_INCR 128 /* The length of "NSPR_INHERIT_FDS=" */ #define NSPR_INHERIT_FDS_STRLEN 17 /* The length of osfd (PROsfd) printed in hexadecimal with 0x prefix */ #ifdef _WIN64 #define OSFD_STRLEN 18 #else #define OSFD_STRLEN 10 #endif /* The length of fd type (PRDescType) printed in decimal */ #define FD_TYPE_STRLEN 1 PRSize newSize; int remainder; char *newBuffer; int nwritten; char *cur; int freeSize; if (fd->identity != PR_NSPR_IO_LAYER) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } if (fd->secret->inheritable == _PR_TRI_UNKNOWN) { _PR_MD_QUERY_FD_INHERITABLE(fd); } if (fd->secret->inheritable != _PR_TRI_TRUE) { PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0); return PR_FAILURE; } /* * We also need to account for the : separators and the * terminating null byte. */ if (NULL == attr->fdInheritBuffer) { /* The first time, we print "NSPR_INHERIT_FDS=::" */ newSize = NSPR_INHERIT_FDS_STRLEN + strlen(name) + FD_TYPE_STRLEN + OSFD_STRLEN + 2 + 1; } else { /* At other times, we print ":::" */ newSize = attr->fdInheritBufferUsed + strlen(name) + FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1; } if (newSize > attr->fdInheritBufferSize) { /* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */ remainder = newSize % FD_INHERIT_BUFFER_INCR; if (remainder != 0) { newSize += (FD_INHERIT_BUFFER_INCR - remainder); } if (NULL == attr->fdInheritBuffer) { newBuffer = (char *) PR_MALLOC(newSize); } else { newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize); } if (NULL == newBuffer) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return PR_FAILURE; } attr->fdInheritBuffer = newBuffer; attr->fdInheritBufferSize = newSize; } cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed; freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed; if (0 == attr->fdInheritBufferUsed) { nwritten = PR_snprintf(cur, freeSize, "NSPR_INHERIT_FDS=%s:%d:0x%" PR_PRIxOSFD, name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd); } else { nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%" PR_PRIxOSFD, name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd); } attr->fdInheritBufferUsed += nwritten; return PR_SUCCESS; } PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD( const char *name) { PRFileDesc *fd; const char *envVar; const char *ptr; int len = strlen(name); PROsfd osfd; int nColons; PRIntn fileType; envVar = PR_GetEnv("NSPR_INHERIT_FDS"); if (NULL == envVar || '\0' == envVar[0]) { PR_SetError(PR_UNKNOWN_ERROR, 0); return NULL; } ptr = envVar; while (1) { if ((ptr[len] == ':') && (strncmp(ptr, name, len) == 0)) { ptr += len + 1; if (PR_sscanf(ptr, "%d:0x%" PR_SCNxOSFD, &fileType, &osfd) != 2) { PR_SetError(PR_UNKNOWN_ERROR, 0); return NULL; } switch ((PRDescType)fileType) { case PR_DESC_FILE: fd = PR_ImportFile(osfd); break; case PR_DESC_PIPE: fd = PR_ImportPipe(osfd); break; case PR_DESC_SOCKET_TCP: fd = PR_ImportTCPSocket(osfd); break; case PR_DESC_SOCKET_UDP: fd = PR_ImportUDPSocket(osfd); break; default: PR_ASSERT(0); PR_SetError(PR_UNKNOWN_ERROR, 0); fd = NULL; break; } if (fd) { /* * An inherited FD is inheritable by default. * The child process needs to call PR_SetFDInheritable * to make it non-inheritable if so desired. */ fd->secret->inheritable = _PR_TRI_TRUE; } return fd; } /* Skip three colons */ nColons = 0; while (*ptr) { if (*ptr == ':') { if (++nColons == 3) { break; } } ptr++; } if (*ptr == '\0') { PR_SetError(PR_UNKNOWN_ERROR, 0); return NULL; } ptr++; } } PR_IMPLEMENT(PRProcess*) PR_CreateProcess( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { return _PR_MD_CREATE_PROCESS(path, argv, envp, attr); } /* PR_CreateProcess */ PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr) { PRProcess *process; PRStatus rv; process = PR_CreateProcess(path, argv, envp, attr); if (NULL == process) { return PR_FAILURE; } rv = PR_DetachProcess(process); PR_ASSERT(PR_SUCCESS == rv); if (rv == PR_FAILURE) { PR_DELETE(process); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process) { return _PR_MD_DETACH_PROCESS(process); } PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode) { return _PR_MD_WAIT_PROCESS(process, exitCode); } /* PR_WaitProcess */ PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process) { return _PR_MD_KILL_PROCESS(process); } /* ******************************************************************** * * Module initialization * ******************************************************************** */ static struct { PRLock *ml; PRCondVar *cv; } mod_init; static void _PR_InitCallOnce(void) { mod_init.ml = PR_NewLock(); PR_ASSERT(NULL != mod_init.ml); mod_init.cv = PR_NewCondVar(mod_init.ml); PR_ASSERT(NULL != mod_init.cv); } void _PR_CleanupCallOnce() { PR_DestroyLock(mod_init.ml); mod_init.ml = NULL; PR_DestroyCondVar(mod_init.cv); mod_init.cv = NULL; } PR_IMPLEMENT(PRStatus) PR_CallOnce( PRCallOnceType *once, PRCallOnceFN func) { if (!_pr_initialized) _PR_ImplicitInitialization(); if (!once->initialized) { if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) { once->status = (*func)(); PR_Lock(mod_init.ml); once->initialized = 1; PR_NotifyAllCondVar(mod_init.cv); PR_Unlock(mod_init.ml); } else { PR_Lock(mod_init.ml); while (!once->initialized) { PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(mod_init.ml); } } else { if (PR_SUCCESS != once->status) { PR_SetError(PR_CALL_ONCE_ERROR, 0); } } return once->status; } PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg( PRCallOnceType *once, PRCallOnceWithArgFN func, void *arg) { if (!_pr_initialized) _PR_ImplicitInitialization(); if (!once->initialized) { if (PR_ATOMIC_SET(&once->inProgress, 1) == 0) { once->status = (*func)(arg); PR_Lock(mod_init.ml); once->initialized = 1; PR_NotifyAllCondVar(mod_init.cv); PR_Unlock(mod_init.ml); } else { PR_Lock(mod_init.ml); while (!once->initialized) { PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(mod_init.ml); } } else { if (PR_SUCCESS != once->status) { PR_SetError(PR_CALL_ONCE_ERROR, 0); } } return once->status; } PRBool _PR_Obsolete(const char *obsolete, const char *preferred) { #if defined(DEBUG) PR_fprintf( PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n", obsolete, (NULL == preferred) ? "something else" : preferred); #endif return PR_FALSE; } /* _PR_Obsolete */ /* prinit.c */ nspr-4.11/nspr/pr/src/misc/prinrval.c0000644000000000000000000000642712623070344015707 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * file: prinrval.c * description: implementation for the kernel interval timing functions */ #include "primpl.h" /* *----------------------------------------------------------------------- * * _PR_InitClock -- * * *----------------------------------------------------------------------- */ void _PR_InitClock(void) { _PR_MD_INTERVAL_INIT(); #ifdef DEBUG { PRIntervalTime ticksPerSec = PR_TicksPerSecond(); PR_ASSERT(ticksPerSec >= PR_INTERVAL_MIN); PR_ASSERT(ticksPerSec <= PR_INTERVAL_MAX); } #endif /* DEBUG */ } PR_IMPLEMENT(PRIntervalTime) PR_IntervalNow(void) { if (!_pr_initialized) _PR_ImplicitInitialization(); return _PR_MD_GET_INTERVAL(); } /* PR_IntervalNow */ PR_EXTERN(PRUint32) PR_TicksPerSecond(void) { if (!_pr_initialized) _PR_ImplicitInitialization(); return _PR_MD_INTERVAL_PER_SEC(); } /* PR_TicksPerSecond */ PR_IMPLEMENT(PRIntervalTime) PR_SecondsToInterval(PRUint32 seconds) { return seconds * PR_TicksPerSecond(); } /* PR_SecondsToInterval */ PR_IMPLEMENT(PRIntervalTime) PR_MillisecondsToInterval(PRUint32 milli) { PRIntervalTime ticks; PRUint64 tock, tps, msecPerSec, rounding; LL_UI2L(tock, milli); LL_I2L(msecPerSec, PR_MSEC_PER_SEC); LL_I2L(rounding, (PR_MSEC_PER_SEC >> 1)); LL_I2L(tps, PR_TicksPerSecond()); LL_MUL(tock, tock, tps); LL_ADD(tock, tock, rounding); LL_DIV(tock, tock, msecPerSec); LL_L2UI(ticks, tock); return ticks; } /* PR_MillisecondsToInterval */ PR_IMPLEMENT(PRIntervalTime) PR_MicrosecondsToInterval(PRUint32 micro) { PRIntervalTime ticks; PRUint64 tock, tps, usecPerSec, rounding; LL_UI2L(tock, micro); LL_I2L(usecPerSec, PR_USEC_PER_SEC); LL_I2L(rounding, (PR_USEC_PER_SEC >> 1)); LL_I2L(tps, PR_TicksPerSecond()); LL_MUL(tock, tock, tps); LL_ADD(tock, tock, rounding); LL_DIV(tock, tock, usecPerSec); LL_L2UI(ticks, tock); return ticks; } /* PR_MicrosecondsToInterval */ PR_IMPLEMENT(PRUint32) PR_IntervalToSeconds(PRIntervalTime ticks) { return ticks / PR_TicksPerSecond(); } /* PR_IntervalToSeconds */ PR_IMPLEMENT(PRUint32) PR_IntervalToMilliseconds(PRIntervalTime ticks) { PRUint32 milli; PRUint64 tock, tps, msecPerSec, rounding; LL_UI2L(tock, ticks); LL_I2L(msecPerSec, PR_MSEC_PER_SEC); LL_I2L(tps, PR_TicksPerSecond()); LL_USHR(rounding, tps, 1); LL_MUL(tock, tock, msecPerSec); LL_ADD(tock, tock, rounding); LL_DIV(tock, tock, tps); LL_L2UI(milli, tock); return milli; } /* PR_IntervalToMilliseconds */ PR_IMPLEMENT(PRUint32) PR_IntervalToMicroseconds(PRIntervalTime ticks) { PRUint32 micro; PRUint64 tock, tps, usecPerSec, rounding; LL_UI2L(tock, ticks); LL_I2L(usecPerSec, PR_USEC_PER_SEC); LL_I2L(tps, PR_TicksPerSecond()); LL_USHR(rounding, tps, 1); LL_MUL(tock, tock, usecPerSec); LL_ADD(tock, tock, rounding); LL_DIV(tock, tock, tps); LL_L2UI(micro, tock); return micro; } /* PR_IntervalToMicroseconds */ /* prinrval.c */ nspr-4.11/nspr/pr/src/misc/pripc.c0000644000000000000000000000420512623070344015157 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pripc.c * * Description: functions for IPC support */ #include "primpl.h" #include /* * A POSIX IPC name must begin with a '/'. * A POSIX IPC name on Solaris cannot contain any '/' except * the required leading '/'. * A POSIX IPC name on HP-UX and OSF1 must be a valid pathname * in the file system. * * The ftok() function for System V IPC requires a valid pathname * in the file system. * * A Win32 IPC name cannot contain '\'. */ static void _pr_ConvertSemName(char *result) { #ifdef _PR_HAVE_POSIX_SEMAPHORES #if defined(SOLARIS) char *p; /* Convert '/' to '_' except for the leading '/' */ for (p = result+1; *p; p++) { if (*p == '/') { *p = '_'; } } return; #else return; #endif #elif defined(_PR_HAVE_SYSV_SEMAPHORES) return; #elif defined(WIN32) return; #endif } static void _pr_ConvertShmName(char *result) { #if defined(PR_HAVE_POSIX_NAMED_SHARED_MEMORY) #if defined(SOLARIS) char *p; /* Convert '/' to '_' except for the leading '/' */ for (p = result+1; *p; p++) { if (*p == '/') { *p = '_'; } } return; #else return; #endif #elif defined(PR_HAVE_SYSV_NAMED_SHARED_MEMORY) return; #elif defined(WIN32) return; #else return; #endif } PRStatus _PR_MakeNativeIPCName( const char *name, char *result, PRIntn size, _PRIPCType type) { if (strlen(name) >= (PRSize)size) { PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); return PR_FAILURE; } strcpy(result, name); switch (type) { case _PRIPCSem: _pr_ConvertSemName(result); break; case _PRIPCShm: _pr_ConvertShmName(result); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } return PR_SUCCESS; } nspr-4.11/nspr/pr/src/misc/pripcsem.c0000644000000000000000000000456212623070344015672 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pripcsem.c * * Description: implements the named semaphores API in prsemipc.h * for classic NSPR. If _PR_HAVE_NAMED_SEMAPHORES is not defined, * the named semaphore functions all fail with the error code * PR_NOT_IMPLEMENTED_ERROR. */ #include "primpl.h" #ifdef _PR_PTHREADS #error "This file should not be compiled for the pthreads version" #else #ifndef _PR_HAVE_NAMED_SEMAPHORES PRSem * _PR_MD_OPEN_SEMAPHORE( const char *osname, PRIntn flags, PRIntn mode, PRUintn value) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PRStatus _PR_MD_WAIT_SEMAPHORE(PRSem *sem) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRStatus _PR_MD_POST_SEMAPHORE(PRSem *sem) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRStatus _PR_MD_CLOSE_SEMAPHORE(PRSem *sem) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRStatus _PR_MD_DELETE_SEMAPHORE(const char *osname) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } #endif /* !_PR_HAVE_NAMED_SEMAPHORES */ PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value) { char osname[PR_IPC_NAME_SIZE]; if (!_pr_initialized) _PR_ImplicitInitialization(); if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return NULL; } return _PR_MD_OPEN_SEMAPHORE(osname, flags, mode, value); } PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem) { return _PR_MD_WAIT_SEMAPHORE(sem); } PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem) { return _PR_MD_POST_SEMAPHORE(sem); } PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem) { return _PR_MD_CLOSE_SEMAPHORE(sem); } PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name) { char osname[PR_IPC_NAME_SIZE]; if (!_pr_initialized) _PR_ImplicitInitialization(); if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return PR_FAILURE; } return _PR_MD_DELETE_SEMAPHORE(osname); } #endif /* _PR_PTHREADS */ nspr-4.11/nspr/pr/src/misc/prlog2.c0000644000000000000000000000135312623070344015250 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prbit.h" /* ** Compute the log of the least power of 2 greater than or equal to n */ PR_IMPLEMENT(PRIntn) PR_CeilingLog2(PRUint32 n) { PRIntn log2; PR_CEILING_LOG2(log2, n); return log2; } /* ** Compute the log of the greatest power of 2 less than or equal to n. ** This really just finds the highest set bit in the word. */ PR_IMPLEMENT(PRIntn) PR_FloorLog2(PRUint32 n) { PRIntn log2; PR_FLOOR_LOG2(log2, n); return log2; } nspr-4.11/nspr/pr/src/misc/prlong.c0000644000000000000000000001164712623070344015353 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prlong.h" static PRInt64 ll_zero = LL_INIT( 0x00000000,0x00000000 ); static PRInt64 ll_maxint = LL_INIT( 0x7fffffff, 0xffffffff ); static PRInt64 ll_minint = LL_INIT( 0x80000000, 0x00000000 ); static PRUint64 ll_maxuint = LL_INIT( 0xffffffff, 0xffffffff ); PR_IMPLEMENT(PRInt64) LL_Zero(void) { return ll_zero; } PR_IMPLEMENT(PRInt64) LL_MaxInt(void) { return ll_maxint; } PR_IMPLEMENT(PRInt64) LL_MinInt(void) { return ll_minint; } PR_IMPLEMENT(PRUint64) LL_MaxUint(void) { return ll_maxuint; } #ifndef HAVE_LONG_LONG /* ** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1. */ static void norm_udivmod32(PRUint32 *qp, PRUint32 *rp, PRUint64 a, PRUint32 b) { PRUint32 d1, d0, q1, q0; PRUint32 r1, r0, m; d1 = _hi16(b); d0 = _lo16(b); r1 = a.hi % d1; q1 = a.hi / d1; m = q1 * d0; r1 = (r1 << 16) | _hi16(a.lo); if (r1 < m) { q1--, r1 += b; if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */ && r1 < m) { q1--, r1 += b; } } r1 -= m; r0 = r1 % d1; q0 = r1 / d1; m = q0 * d0; r0 = (r0 << 16) | _lo16(a.lo); if (r0 < m) { q0--, r0 += b; if (r0 >= b && r0 < m) { q0--, r0 += b; } } *qp = (q1 << 16) | q0; *rp = r0 - m; } static PRUint32 CountLeadingZeros(PRUint32 a) { PRUint32 t; PRUint32 r = 32; if ((t = a >> 16) != 0) r -= 16, a = t; if ((t = a >> 8) != 0) r -= 8, a = t; if ((t = a >> 4) != 0) r -= 4, a = t; if ((t = a >> 2) != 0) r -= 2, a = t; if ((t = a >> 1) != 0) r -= 1, a = t; if (a & 1) r--; return r; } PR_IMPLEMENT(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b) { PRUint32 n0, n1, n2; PRUint32 q0, q1; PRUint32 rsh, lsh; n0 = a.lo; n1 = a.hi; if (b.hi == 0) { if (b.lo > n1) { /* (0 q0) = (n1 n0) / (0 D0) */ lsh = CountLeadingZeros(b.lo); if (lsh) { /* * Normalize, i.e. make the most significant bit of the * denominator be set. */ b.lo = b.lo << lsh; n1 = (n1 << lsh) | (n0 >> (32 - lsh)); n0 = n0 << lsh; } a.lo = n0, a.hi = n1; norm_udivmod32(&q0, &n0, a, b.lo); q1 = 0; /* remainder is in n0 >> lsh */ } else { /* (q1 q0) = (n1 n0) / (0 d0) */ if (b.lo == 0) /* user wants to divide by zero! */ b.lo = 1 / b.lo; /* so go ahead and crash */ lsh = CountLeadingZeros(b.lo); if (lsh == 0) { /* * From (n1 >= b.lo) * && (the most significant bit of b.lo is set), * conclude that * (the most significant bit of n1 is set) * && (the leading quotient digit q1 = 1). * * This special case is necessary, not an optimization * (Shifts counts of 32 are undefined). */ n1 -= b.lo; q1 = 1; } else { /* * Normalize. */ rsh = 32 - lsh; b.lo = b.lo << lsh; n2 = n1 >> rsh; n1 = (n1 << lsh) | (n0 >> rsh); n0 = n0 << lsh; a.lo = n1, a.hi = n2; norm_udivmod32(&q1, &n1, a, b.lo); } /* n1 != b.lo... */ a.lo = n0, a.hi = n1; norm_udivmod32(&q0, &n0, a, b.lo); /* remainder in n0 >> lsh */ } if (rp) { rp->lo = n0 >> lsh; rp->hi = 0; } } else { if (b.hi > n1) { /* (0 0) = (n1 n0) / (D1 d0) */ q0 = 0; q1 = 0; /* remainder in (n1 n0) */ if (rp) { rp->lo = n0; rp->hi = n1; } } else { /* (0 q0) = (n1 n0) / (d1 d0) */ lsh = CountLeadingZeros(b.hi); if (lsh == 0) { /* * From (n1 >= b.hi) * && (the most significant bit of b.hi is set), * conclude that * (the most significant bit of n1 is set) * && (the quotient digit q0 = 0 or 1). * * This special case is necessary, not an optimization. */ /* * The condition on the next line takes advantage of that * n1 >= b.hi (true due to control flow). */ if (n1 > b.hi || n0 >= b.lo) { q0 = 1; a.lo = n0, a.hi = n1; LL_SUB(a, a, b); } else { q0 = 0; } q1 = 0; if (rp) { rp->lo = n0; rp->hi = n1; } } else { PRInt64 m; /* * Normalize. */ rsh = 32 - lsh; b.hi = (b.hi << lsh) | (b.lo >> rsh); b.lo = b.lo << lsh; n2 = n1 >> rsh; n1 = (n1 << lsh) | (n0 >> rsh); n0 = n0 << lsh; a.lo = n1, a.hi = n2; norm_udivmod32(&q0, &n1, a, b.hi); LL_MUL32(m, q0, b.lo); if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) { q0--; LL_SUB(m, m, b); } q1 = 0; /* Remainder is ((n1 n0) - (m1 m0)) >> lsh */ if (rp) { a.lo = n0, a.hi = n1; LL_SUB(a, a, m); rp->lo = (a.hi << rsh) | (a.lo >> lsh); rp->hi = a.hi >> lsh; } } } } if (qp) { qp->lo = q0; qp->hi = q1; } } #endif /* !HAVE_LONG_LONG */ nspr-4.11/nspr/pr/src/misc/prnetdb.c0000644000000000000000000020646512623070344015514 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include /* * On Unix, the error code for gethostbyname() and gethostbyaddr() * is returned in the global variable h_errno, instead of the usual * errno. */ #if defined(XP_UNIX) #if defined(_PR_NEED_H_ERRNO) extern int h_errno; #endif #define _MD_GETHOST_ERRNO() h_errno #else #define _MD_GETHOST_ERRNO() _MD_ERRNO() #endif /* * The meaning of the macros related to gethostbyname, gethostbyaddr, * and gethostbyname2 is defined below. * - _PR_HAVE_THREADSAFE_GETHOST: the gethostbyXXX functions return * the result in thread specific storage. For example, AIX, HP-UX, * and OSF1. * - _PR_HAVE_GETHOST_R: have the gethostbyXXX_r functions. See next * two macros. * - _PR_HAVE_GETHOST_R_INT: the gethostbyXXX_r functions return an * int. For example, Linux glibc. * - _PR_HAVE_GETHOST_R_POINTER: the gethostbyXXX_r functions return * a struct hostent* pointer. For example, Solaris and IRIX. */ #if defined(_PR_NO_PREEMPT) || defined(_PR_HAVE_GETHOST_R) \ || defined(_PR_HAVE_THREADSAFE_GETHOST) #define _PR_NO_DNS_LOCK #endif #if defined(_PR_NO_DNS_LOCK) #define LOCK_DNS() #define UNLOCK_DNS() #else PRLock *_pr_dnsLock = NULL; #define LOCK_DNS() PR_Lock(_pr_dnsLock) #define UNLOCK_DNS() PR_Unlock(_pr_dnsLock) #endif /* defined(_PR_NO_DNS_LOCK) */ /* * Some platforms have the reentrant getprotobyname_r() and * getprotobynumber_r(). However, they come in three flavors. * Some return a pointer to struct protoent, others return * an int, and glibc's flavor takes five arguments. */ #if defined(XP_BEOS) && defined(BONE_VERSION) #include /* pick up define for inet_addr */ #include #define _PR_HAVE_GETPROTO_R #define _PR_HAVE_GETPROTO_R_POINTER #endif #if defined(SOLARIS) || (defined(BSDI) && defined(_REENTRANT)) \ || (defined(LINUX) && defined(_REENTRANT) \ && !(defined(__GLIBC__) && __GLIBC__ >= 2) \ && !defined(ANDROID)) #define _PR_HAVE_GETPROTO_R #define _PR_HAVE_GETPROTO_R_POINTER #endif #if defined(OSF1) \ || defined(AIX4_3_PLUS) || (defined(AIX) && defined(_THREAD_SAFE)) \ || (defined(HPUX10_10) && defined(_REENTRANT)) \ || (defined(HPUX10_20) && defined(_REENTRANT)) \ || defined(OPENBSD) #define _PR_HAVE_GETPROTO_R #define _PR_HAVE_GETPROTO_R_INT #endif #if __FreeBSD_version >= 602000 #define _PR_HAVE_GETPROTO_R #define _PR_HAVE_5_ARG_GETPROTO_R #endif /* BeOS has glibc but not the glibc-style getprotobyxxx_r functions. */ #if (defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(XP_BEOS)) #define _PR_HAVE_GETPROTO_R #define _PR_HAVE_5_ARG_GETPROTO_R #endif #if !defined(_PR_HAVE_GETPROTO_R) PRLock* _getproto_lock = NULL; #endif #if defined(_PR_INET6_PROBE) extern PRBool _pr_ipv6_is_present(void); #endif #define _PR_IN6_IS_ADDR_UNSPECIFIED(a) \ (((a)->pr_s6_addr32[0] == 0) && \ ((a)->pr_s6_addr32[1] == 0) && \ ((a)->pr_s6_addr32[2] == 0) && \ ((a)->pr_s6_addr32[3] == 0)) #define _PR_IN6_IS_ADDR_LOOPBACK(a) \ (((a)->pr_s6_addr32[0] == 0) && \ ((a)->pr_s6_addr32[1] == 0) && \ ((a)->pr_s6_addr32[2] == 0) && \ ((a)->pr_s6_addr[12] == 0) && \ ((a)->pr_s6_addr[13] == 0) && \ ((a)->pr_s6_addr[14] == 0) && \ ((a)->pr_s6_addr[15] == 0x1U)) const PRIPv6Addr _pr_in6addr_any = {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}}; const PRIPv6Addr _pr_in6addr_loopback = {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1U }}}; /* * The values at bytes 10 and 11 are compared using pointers to * 8-bit fields, and not 32-bit fields, to make the comparison work on * both big-endian and little-endian systems */ #define _PR_IN6_IS_ADDR_V4MAPPED(a) \ (((a)->pr_s6_addr32[0] == 0) && \ ((a)->pr_s6_addr32[1] == 0) && \ ((a)->pr_s6_addr[8] == 0) && \ ((a)->pr_s6_addr[9] == 0) && \ ((a)->pr_s6_addr[10] == 0xff) && \ ((a)->pr_s6_addr[11] == 0xff)) #define _PR_IN6_IS_ADDR_V4COMPAT(a) \ (((a)->pr_s6_addr32[0] == 0) && \ ((a)->pr_s6_addr32[1] == 0) && \ ((a)->pr_s6_addr32[2] == 0)) #define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->pr_s6_addr32[3]) #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) /* * The _pr_QueryNetIfs() function finds out if the system has * IPv4 or IPv6 source addresses configured and sets _pr_have_inet_if * and _pr_have_inet6_if accordingly. * * We have an implementation using SIOCGIFCONF ioctl and a * default implementation that simply sets _pr_have_inet_if * and _pr_have_inet6_if to true. A better implementation * would be to use the routing sockets (see Chapter 17 of * W. Richard Stevens' Unix Network Programming, Vol. 1, 2nd. Ed.) */ static PRLock *_pr_query_ifs_lock = NULL; static PRBool _pr_have_inet_if = PR_FALSE; static PRBool _pr_have_inet6_if = PR_FALSE; #undef DEBUG_QUERY_IFS #if defined(AIX) \ || (defined(DARWIN) && (!defined(HAVE_GETIFADDRS) \ || (defined(XP_MACOSX) && (!defined(MAC_OS_X_VERSION_10_2) || \ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_2)))) /* * Use SIOCGIFCONF ioctl on platforms that don't have routing * sockets. Warning: whether SIOCGIFCONF ioctl returns AF_INET6 * network interfaces is not portable. * * The _pr_QueryNetIfs() function is derived from the code in * src/lib/libc/net/getifaddrs.c in BSD Unix and the code in * Section 16.6 of W. Richard Stevens' Unix Network Programming, * Vol. 1, 2nd. Ed. */ #include #include #include #include #ifdef DEBUG_QUERY_IFS static void _pr_PrintIfreq(struct ifreq *ifr) { PRNetAddr addr; struct sockaddr *sa; const char* family; char addrstr[64]; sa = &ifr->ifr_addr; if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; family = "inet"; memcpy(&addr.inet.ip, &sin->sin_addr, sizeof(sin->sin_addr)); } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; family = "inet6"; memcpy(&addr.ipv6.ip, &sin6->sin6_addr, sizeof(sin6->sin6_addr)); } else { return; /* skip if not AF_INET or AF_INET6 */ } addr.raw.family = sa->sa_family; PR_NetAddrToString(&addr, addrstr, sizeof(addrstr)); printf("%s: %s %s\n", ifr->ifr_name, family, addrstr); } #endif static void _pr_QueryNetIfs(void) { int sock; int rv; struct ifconf ifc; struct ifreq *ifr; struct ifreq *lifr; PRUint32 len, lastlen; char *buf; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { return; } /* Issue SIOCGIFCONF request in a loop. */ lastlen = 0; len = 100 * sizeof(struct ifreq); /* initial buffer size guess */ for (;;) { buf = (char *)PR_Malloc(len); if (NULL == buf) { close(sock); return; } ifc.ifc_buf = buf; ifc.ifc_len = len; rv = ioctl(sock, SIOCGIFCONF, &ifc); if (rv < 0) { if (errno != EINVAL || lastlen != 0) { close(sock); PR_Free(buf); return; } } else { if (ifc.ifc_len == lastlen) break; /* success, len has not changed */ lastlen = ifc.ifc_len; } len += 10 * sizeof(struct ifreq); /* increment */ PR_Free(buf); } close(sock); ifr = ifc.ifc_req; lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len]; while (ifr < lifr) { struct sockaddr *sa; int sa_len; #ifdef DEBUG_QUERY_IFS _pr_PrintIfreq(ifr); #endif sa = &ifr->ifr_addr; if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { _pr_have_inet_if = PR_TRUE; } } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { _pr_have_inet6_if = PR_TRUE; } } #ifdef _PR_HAVE_SOCKADDR_LEN sa_len = PR_MAX(sa->sa_len, sizeof(struct sockaddr)); #else switch (sa->sa_family) { #ifdef AF_LINK case AF_LINK: sa_len = sizeof(struct sockaddr_dl); break; #endif case AF_INET6: sa_len = sizeof(struct sockaddr_in6); break; default: sa_len = sizeof(struct sockaddr); break; } #endif ifr = (struct ifreq *)(((char *)sa) + sa_len); } PR_Free(buf); } #elif (defined(DARWIN) && defined(HAVE_GETIFADDRS)) || defined(FREEBSD) \ || defined(NETBSD) || defined(OPENBSD) /* * Use the BSD getifaddrs function. */ #include #include #include #include #ifdef DEBUG_QUERY_IFS static void _pr_PrintIfaddrs(struct ifaddrs *ifa) { struct sockaddr *sa; const char* family; void *addrp; char addrstr[64]; sa = ifa->ifa_addr; if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)sa; family = "inet"; addrp = &sin->sin_addr; } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; family = "inet6"; addrp = &sin6->sin6_addr; } else { return; /* skip if not AF_INET or AF_INET6 */ } inet_ntop(sa->sa_family, addrp, addrstr, sizeof(addrstr)); printf("%s: %s %s\n", ifa->ifa_name, family, addrstr); } #endif static void _pr_QueryNetIfs(void) { struct ifaddrs *ifp; struct ifaddrs *ifa; if (getifaddrs(&ifp) == -1) { return; } for (ifa = ifp; ifa; ifa = ifa->ifa_next) { struct sockaddr *sa; #ifdef DEBUG_QUERY_IFS _pr_PrintIfaddrs(ifa); #endif sa = ifa->ifa_addr; if (sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *) sa; if (sin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { _pr_have_inet_if = 1; } } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; if (!IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { _pr_have_inet6_if = 1; } } } freeifaddrs(ifp); } #else /* default */ /* * Emulate the code in NSPR 4.2 or older. PR_GetIPNodeByName behaves * as if the system had both IPv4 and IPv6 source addresses configured. */ static void _pr_QueryNetIfs(void) { _pr_have_inet_if = PR_TRUE; _pr_have_inet6_if = PR_TRUE; } #endif #endif /* _PR_INET6 && _PR_HAVE_GETHOSTBYNAME2 */ void _PR_InitNet(void) { #if defined(XP_UNIX) #ifdef HAVE_NETCONFIG /* * This one-liner prevents the endless re-open's and re-read's of * /etc/netconfig on EACH and EVERY call to accept(), connect(), etc. */ (void)setnetconfig(); #endif #endif #if !defined(_PR_NO_DNS_LOCK) _pr_dnsLock = PR_NewLock(); #endif #if !defined(_PR_HAVE_GETPROTO_R) _getproto_lock = PR_NewLock(); #endif #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) _pr_query_ifs_lock = PR_NewLock(); #endif } void _PR_CleanupNet(void) { #if !defined(_PR_NO_DNS_LOCK) if (_pr_dnsLock) { PR_DestroyLock(_pr_dnsLock); _pr_dnsLock = NULL; } #endif #if !defined(_PR_HAVE_GETPROTO_R) if (_getproto_lock) { PR_DestroyLock(_getproto_lock); _getproto_lock = NULL; } #endif #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) if (_pr_query_ifs_lock) { PR_DestroyLock(_pr_query_ifs_lock); _pr_query_ifs_lock = NULL; } #endif } /* ** Allocate space from the buffer, aligning it to "align" before doing ** the allocation. "align" must be a power of 2. */ static char *Alloc(PRIntn amount, char **bufp, PRIntn *buflenp, PRIntn align) { char *buf = *bufp; PRIntn buflen = *buflenp; if (align && ((long)buf & (align - 1))) { PRIntn skip = align - ((ptrdiff_t)buf & (align - 1)); if (buflen < skip) { return 0; } buf += skip; buflen -= skip; } if (buflen < amount) { return 0; } *bufp = buf + amount; *buflenp = buflen - amount; return buf; } typedef enum _PRIPAddrConversion { _PRIPAddrNoConversion, _PRIPAddrIPv4Mapped, _PRIPAddrIPv4Compat } _PRIPAddrConversion; /* ** Convert an IPv4 address (v4) to an IPv4-mapped IPv6 address (v6). */ static void MakeIPv4MappedAddr(const char *v4, char *v6) { memset(v6, 0, 10); memset(v6 + 10, 0xff, 2); memcpy(v6 + 12, v4, 4); } /* ** Convert an IPv4 address (v4) to an IPv4-compatible IPv6 address (v6). */ static void MakeIPv4CompatAddr(const char *v4, char *v6) { memset(v6, 0, 12); memcpy(v6 + 12, v4, 4); } /* ** Copy a hostent, and all of the memory that it refers to into ** (hopefully) stacked buffers. */ static PRStatus CopyHostent( struct hostent *from, char **buf, PRIntn *bufsize, _PRIPAddrConversion conversion, PRHostEnt *to) { PRIntn len, na; char **ap; if (conversion != _PRIPAddrNoConversion && from->h_addrtype == AF_INET) { PR_ASSERT(from->h_length == 4); to->h_addrtype = PR_AF_INET6; to->h_length = 16; } else { #if defined(_PR_INET6) || defined(_PR_INET6_PROBE) if (AF_INET6 == from->h_addrtype) to->h_addrtype = PR_AF_INET6; else #endif to->h_addrtype = from->h_addrtype; to->h_length = from->h_length; } /* Copy the official name */ if (!from->h_name) return PR_FAILURE; len = strlen(from->h_name) + 1; to->h_name = Alloc(len, buf, bufsize, 0); if (!to->h_name) return PR_FAILURE; memcpy(to->h_name, from->h_name, len); /* Count the aliases, then allocate storage for the pointers */ if (!from->h_aliases) { na = 1; } else { for (na = 1, ap = from->h_aliases; *ap != 0; na++, ap++){;} /* nothing to execute */ } to->h_aliases = (char**)Alloc( na * sizeof(char*), buf, bufsize, sizeof(char**)); if (!to->h_aliases) return PR_FAILURE; /* Copy the aliases, one at a time */ if (!from->h_aliases) { to->h_aliases[0] = 0; } else { for (na = 0, ap = from->h_aliases; *ap != 0; na++, ap++) { len = strlen(*ap) + 1; to->h_aliases[na] = Alloc(len, buf, bufsize, 0); if (!to->h_aliases[na]) return PR_FAILURE; memcpy(to->h_aliases[na], *ap, len); } to->h_aliases[na] = 0; } /* Count the addresses, then allocate storage for the pointers */ for (na = 1, ap = from->h_addr_list; *ap != 0; na++, ap++){;} /* nothing to execute */ to->h_addr_list = (char**)Alloc( na * sizeof(char*), buf, bufsize, sizeof(char**)); if (!to->h_addr_list) return PR_FAILURE; /* Copy the addresses, one at a time */ for (na = 0, ap = from->h_addr_list; *ap != 0; na++, ap++) { to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0); if (!to->h_addr_list[na]) return PR_FAILURE; if (conversion != _PRIPAddrNoConversion && from->h_addrtype == AF_INET) { if (conversion == _PRIPAddrIPv4Mapped) { MakeIPv4MappedAddr(*ap, to->h_addr_list[na]); } else { PR_ASSERT(conversion == _PRIPAddrIPv4Compat); MakeIPv4CompatAddr(*ap, to->h_addr_list[na]); } } else { memcpy(to->h_addr_list[na], *ap, to->h_length); } } to->h_addr_list[na] = 0; return PR_SUCCESS; } #ifdef SYMBIAN /* Set p_aliases by hand because Symbian's getprotobyname() returns NULL. */ static void AssignAliases(struct protoent *Protoent, char** aliases) { if (NULL == Protoent->p_aliases) { if (0 == strcmp(Protoent->p_name, "ip")) aliases[0] = "IP"; else if (0 == strcmp(Protoent->p_name, "tcp")) aliases[0] = "TCP"; else if (0 == strcmp(Protoent->p_name, "udp")) aliases[0] = "UDP"; else aliases[0] = "UNKNOWN"; aliases[1] = NULL; Protoent->p_aliases = aliases; } } #endif #if !defined(_PR_HAVE_GETPROTO_R) /* ** Copy a protoent, and all of the memory that it refers to into ** (hopefully) stacked buffers. */ static PRStatus CopyProtoent( struct protoent *from, char *buf, PRIntn bufsize, PRProtoEnt *to) { PRIntn len, na; char **ap; /* Do the easy stuff */ to->p_num = from->p_proto; /* Copy the official name */ if (!from->p_name) return PR_FAILURE; len = strlen(from->p_name) + 1; to->p_name = Alloc(len, &buf, &bufsize, 0); if (!to->p_name) return PR_FAILURE; memcpy(to->p_name, from->p_name, len); /* Count the aliases, then allocate storage for the pointers */ for (na = 1, ap = from->p_aliases; *ap != 0; na++, ap++){;} /* nothing to execute */ to->p_aliases = (char**)Alloc( na * sizeof(char*), &buf, &bufsize, sizeof(char**)); if (!to->p_aliases) return PR_FAILURE; /* Copy the aliases, one at a time */ for (na = 0, ap = from->p_aliases; *ap != 0; na++, ap++) { len = strlen(*ap) + 1; to->p_aliases[na] = Alloc(len, &buf, &bufsize, 0); if (!to->p_aliases[na]) return PR_FAILURE; memcpy(to->p_aliases[na], *ap, len); } to->p_aliases[na] = 0; return PR_SUCCESS; } #endif /* !defined(_PR_HAVE_GETPROTO_R) */ /* * ################################################################# * NOTE: tmphe, tmpbuf, bufsize, h, and h_err are local variables * or arguments of PR_GetHostByName, PR_GetIPNodeByName, and * PR_GetHostByAddr. DO NOT CHANGE THE NAMES OF THESE LOCAL * VARIABLES OR ARGUMENTS. * ################################################################# */ #if defined(_PR_HAVE_GETHOST_R_INT) #define GETHOSTBYNAME(name) \ (gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h, &h_err), h) #define GETHOSTBYNAME2(name, af) \ (gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h, &h_err), h) #define GETHOSTBYADDR(addr, addrlen, af) \ (gethostbyaddr_r(addr, addrlen, af, \ &tmphe, tmpbuf, bufsize, &h, &h_err), h) #elif defined(_PR_HAVE_GETHOST_R_POINTER) #define GETHOSTBYNAME(name) \ gethostbyname_r(name, &tmphe, tmpbuf, bufsize, &h_err) #define GETHOSTBYNAME2(name, af) \ gethostbyname2_r(name, af, &tmphe, tmpbuf, bufsize, &h_err) #define GETHOSTBYADDR(addr, addrlen, af) \ gethostbyaddr_r(addr, addrlen, af, &tmphe, tmpbuf, bufsize, &h_err) #else #define GETHOSTBYNAME(name) gethostbyname(name) #define GETHOSTBYNAME2(name, af) gethostbyname2(name, af) #define GETHOSTBYADDR(addr, addrlen, af) gethostbyaddr(addr, addrlen, af) #endif /* definition of GETHOSTBYXXX */ PR_IMPLEMENT(PRStatus) PR_GetHostByName( const char *name, char *buf, PRIntn bufsize, PRHostEnt *hp) { struct hostent *h; PRStatus rv = PR_FAILURE; #if defined(_PR_HAVE_GETHOST_R) char localbuf[PR_NETDB_BUF_SIZE]; char *tmpbuf; struct hostent tmphe; int h_err; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); #if defined(_PR_HAVE_GETHOST_R) tmpbuf = localbuf; if (bufsize > sizeof(localbuf)) { tmpbuf = (char *)PR_Malloc(bufsize); if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return rv; } } #endif LOCK_DNS(); h = GETHOSTBYNAME(name); if (NULL == h) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); } else { _PRIPAddrConversion conversion = _PRIPAddrNoConversion; rv = CopyHostent(h, &buf, &bufsize, conversion, hp); if (PR_SUCCESS != rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } UNLOCK_DNS(); #if defined(_PR_HAVE_GETHOST_R) if (tmpbuf != localbuf) PR_Free(tmpbuf); #endif return rv; } #if !defined(_PR_INET6) && \ defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) typedef struct hostent * (*_pr_getipnodebyname_t)(const char *, int, int, int *); typedef struct hostent * (*_pr_getipnodebyaddr_t)(const void *, size_t, int, int *); typedef void (*_pr_freehostent_t)(struct hostent *); static void * _pr_getipnodebyname_fp; static void * _pr_getipnodebyaddr_fp; static void * _pr_freehostent_fp; /* * Look up the addresses of getipnodebyname, getipnodebyaddr, * and freehostent. */ PRStatus _pr_find_getipnodebyname(void) { PRLibrary *lib; PRStatus rv; #define GETIPNODEBYNAME "getipnodebyname" #define GETIPNODEBYADDR "getipnodebyaddr" #define FREEHOSTENT "freehostent" _pr_getipnodebyname_fp = PR_FindSymbolAndLibrary(GETIPNODEBYNAME, &lib); if (NULL != _pr_getipnodebyname_fp) { _pr_freehostent_fp = PR_FindSymbol(lib, FREEHOSTENT); if (NULL != _pr_freehostent_fp) { _pr_getipnodebyaddr_fp = PR_FindSymbol(lib, GETIPNODEBYADDR); if (NULL != _pr_getipnodebyaddr_fp) rv = PR_SUCCESS; else rv = PR_FAILURE; } else rv = PR_FAILURE; (void)PR_UnloadLibrary(lib); } else rv = PR_FAILURE; return rv; } #endif #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) /* ** Append the V4 addresses to the end of the list */ static PRStatus AppendV4AddrsToHostent( struct hostent *from, char **buf, PRIntn *bufsize, PRHostEnt *to) { PRIntn na, na_old; char **ap; char **new_addr_list; /* Count the addresses, then grow storage for the pointers */ for (na_old = 0, ap = to->h_addr_list; *ap != 0; na_old++, ap++) {;} /* nothing to execute */ for (na = na_old + 1, ap = from->h_addr_list; *ap != 0; na++, ap++) {;} /* nothing to execute */ new_addr_list = (char**)Alloc( na * sizeof(char*), buf, bufsize, sizeof(char**)); if (!new_addr_list) return PR_FAILURE; /* Copy the V6 addresses, one at a time */ for (na = 0, ap = to->h_addr_list; *ap != 0; na++, ap++) { new_addr_list[na] = to->h_addr_list[na]; } to->h_addr_list = new_addr_list; /* Copy the V4 addresses, one at a time */ for (ap = from->h_addr_list; *ap != 0; na++, ap++) { to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0); if (!to->h_addr_list[na]) return PR_FAILURE; MakeIPv4MappedAddr(*ap, to->h_addr_list[na]); } to->h_addr_list[na] = 0; return PR_SUCCESS; } #endif PR_IMPLEMENT(PRStatus) PR_GetIPNodeByName( const char *name, PRUint16 af, PRIntn flags, char *buf, PRIntn bufsize, PRHostEnt *hp) { struct hostent *h = 0; PRStatus rv = PR_FAILURE; #if defined(_PR_HAVE_GETHOST_R) char localbuf[PR_NETDB_BUF_SIZE]; char *tmpbuf; struct hostent tmphe; int h_err; #endif #if defined(_PR_HAVE_GETIPNODEBYNAME) PRUint16 md_af = af; int error_num; int tmp_flags = 0; #endif #if defined(_PR_HAVE_GETHOSTBYNAME2) PRBool did_af_inet = PR_FALSE; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); if (af != PR_AF_INET && af != PR_AF_INET6) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) PR_Lock(_pr_query_ifs_lock); /* * Keep querying the presence of IPv4 and IPv6 interfaces until * at least one is up. This allows us to detect the local * machine going from offline to online. */ if (!_pr_have_inet_if && !_pr_have_inet6_if) { _pr_QueryNetIfs(); #ifdef DEBUG_QUERY_IFS if (_pr_have_inet_if) printf("Have IPv4 source address\n"); if (_pr_have_inet6_if) printf("Have IPv6 source address\n"); #endif } PR_Unlock(_pr_query_ifs_lock); #endif #if defined(_PR_HAVE_GETIPNODEBYNAME) if (flags & PR_AI_V4MAPPED) tmp_flags |= AI_V4MAPPED; if (flags & PR_AI_ADDRCONFIG) tmp_flags |= AI_ADDRCONFIG; if (flags & PR_AI_ALL) tmp_flags |= AI_ALL; if (af == PR_AF_INET6) md_af = AF_INET6; else md_af = af; #endif #if defined(_PR_HAVE_GETHOST_R) tmpbuf = localbuf; if (bufsize > sizeof(localbuf)) { tmpbuf = (char *)PR_Malloc(bufsize); if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return rv; } } #endif /* Do not need to lock the DNS lock if getipnodebyname() is called */ #ifdef _PR_INET6 #ifdef _PR_HAVE_GETHOSTBYNAME2 LOCK_DNS(); if (af == PR_AF_INET6) { if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet6_if) { #ifdef _PR_INET6_PROBE if (_pr_ipv6_is_present()) #endif h = GETHOSTBYNAME2(name, AF_INET6); } if ((NULL == h) && (flags & PR_AI_V4MAPPED) && ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if)) { did_af_inet = PR_TRUE; h = GETHOSTBYNAME2(name, AF_INET); } } else { if ((flags & PR_AI_ADDRCONFIG) == 0 || _pr_have_inet_if) { did_af_inet = PR_TRUE; h = GETHOSTBYNAME2(name, af); } } #elif defined(_PR_HAVE_GETIPNODEBYNAME) h = getipnodebyname(name, md_af, tmp_flags, &error_num); #else #error "Unknown name-to-address translation function" #endif /* _PR_HAVE_GETHOSTBYNAME2 */ #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) if (_pr_ipv6_is_present()) { #ifdef PR_GETIPNODE_NOT_THREADSAFE LOCK_DNS(); #endif h = (*((_pr_getipnodebyname_t)_pr_getipnodebyname_fp))(name, md_af, tmp_flags, &error_num); } else { LOCK_DNS(); h = GETHOSTBYNAME(name); } #else /* _PR_INET6 */ LOCK_DNS(); h = GETHOSTBYNAME(name); #endif /* _PR_INET6 */ if (NULL == h) { #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) if (_pr_ipv6_is_present()) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #endif } else { _PRIPAddrConversion conversion = _PRIPAddrNoConversion; if (af == PR_AF_INET6) conversion = _PRIPAddrIPv4Mapped; rv = CopyHostent(h, &buf, &bufsize, conversion, hp); if (PR_SUCCESS != rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME) freehostent(h); #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) if (_pr_ipv6_is_present()) (*((_pr_freehostent_t)_pr_freehostent_fp))(h); #endif #if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2) if ((PR_SUCCESS == rv) && (flags & PR_AI_V4MAPPED) && ((flags & PR_AI_ALL) || ((flags & PR_AI_ADDRCONFIG) && _pr_have_inet_if)) && !did_af_inet && (h = GETHOSTBYNAME2(name, AF_INET)) != 0) { rv = AppendV4AddrsToHostent(h, &buf, &bufsize, hp); if (PR_SUCCESS != rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } #endif } /* Must match the convoluted logic above for LOCK_DNS() */ #ifdef _PR_INET6 #ifdef _PR_HAVE_GETHOSTBYNAME2 UNLOCK_DNS(); #endif /* _PR_HAVE_GETHOSTBYNAME2 */ #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYNAME) #ifdef PR_GETIPNODE_NOT_THREADSAFE UNLOCK_DNS(); #else if (!_pr_ipv6_is_present()) UNLOCK_DNS(); #endif #else /* _PR_INET6 */ UNLOCK_DNS(); #endif /* _PR_INET6 */ #if defined(_PR_HAVE_GETHOST_R) if (tmpbuf != localbuf) PR_Free(tmpbuf); #endif return rv; } PR_IMPLEMENT(PRStatus) PR_GetHostByAddr( const PRNetAddr *hostaddr, char *buf, PRIntn bufsize, PRHostEnt *hostentry) { struct hostent *h; PRStatus rv = PR_FAILURE; const void *addr; PRUint32 tmp_ip; int addrlen; PRInt32 af; #if defined(_PR_HAVE_GETHOST_R) char localbuf[PR_NETDB_BUF_SIZE]; char *tmpbuf; struct hostent tmphe; int h_err; #endif #if defined(_PR_HAVE_GETIPNODEBYADDR) int error_num; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); if (hostaddr->raw.family == PR_AF_INET6) { #if defined(_PR_INET6_PROBE) af = _pr_ipv6_is_present() ? AF_INET6 : AF_INET; #elif defined(_PR_INET6) af = AF_INET6; #else af = AF_INET; #endif #if defined(_PR_GHBA_DISALLOW_V4MAPPED) if (_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)) af = AF_INET; #endif } else { PR_ASSERT(hostaddr->raw.family == AF_INET); af = AF_INET; } if (hostaddr->raw.family == PR_AF_INET6) { #if defined(_PR_INET6) || defined(_PR_INET6_PROBE) if (af == AF_INET6) { addr = &hostaddr->ipv6.ip; addrlen = sizeof(hostaddr->ipv6.ip); } else #endif { PR_ASSERT(af == AF_INET); if (!_PR_IN6_IS_ADDR_V4MAPPED(&hostaddr->ipv6.ip)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return rv; } tmp_ip = _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *) &hostaddr->ipv6.ip); addr = &tmp_ip; addrlen = sizeof(tmp_ip); } } else { PR_ASSERT(hostaddr->raw.family == AF_INET); PR_ASSERT(af == AF_INET); addr = &hostaddr->inet.ip; addrlen = sizeof(hostaddr->inet.ip); } #if defined(_PR_HAVE_GETHOST_R) tmpbuf = localbuf; if (bufsize > sizeof(localbuf)) { tmpbuf = (char *)PR_Malloc(bufsize); if (NULL == tmpbuf) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return rv; } } #endif /* Do not need to lock the DNS lock if getipnodebyaddr() is called */ #if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6) h = getipnodebyaddr(addr, addrlen, af, &error_num); #elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE) if (_pr_ipv6_is_present()) { #ifdef PR_GETIPNODE_NOT_THREADSAFE LOCK_DNS(); #endif h = (*((_pr_getipnodebyaddr_t)_pr_getipnodebyaddr_fp))(addr, addrlen, af, &error_num); } else { LOCK_DNS(); h = GETHOSTBYADDR(addr, addrlen, af); } #else /* _PR_HAVE_GETIPNODEBYADDR */ LOCK_DNS(); h = GETHOSTBYADDR(addr, addrlen, af); #endif /* _PR_HAVE_GETIPNODEBYADDR */ if (NULL == h) { #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR) if (_pr_ipv6_is_present()) PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num); else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #else PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO()); #endif } else { _PRIPAddrConversion conversion = _PRIPAddrNoConversion; if (hostaddr->raw.family == PR_AF_INET6) { if (af == AF_INET) { if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr*) &hostaddr->ipv6.ip)) { conversion = _PRIPAddrIPv4Mapped; } else if (_PR_IN6_IS_ADDR_V4COMPAT((PRIPv6Addr *) &hostaddr->ipv6.ip)) { conversion = _PRIPAddrIPv4Compat; } } } rv = CopyHostent(h, &buf, &bufsize, conversion, hostentry); if (PR_SUCCESS != rv) { PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR) freehostent(h); #elif defined(_PR_INET6_PROBE) && defined(_PR_HAVE_GETIPNODEBYADDR) if (_pr_ipv6_is_present()) (*((_pr_freehostent_t)_pr_freehostent_fp))(h); #endif } /* Must match the convoluted logic above for LOCK_DNS() */ #if defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6) #elif defined(_PR_HAVE_GETIPNODEBYADDR) && defined(_PR_INET6_PROBE) #ifdef PR_GETIPNODE_NOT_THREADSAFE UNLOCK_DNS(); #else if (!_pr_ipv6_is_present()) UNLOCK_DNS(); #endif #else /* _PR_HAVE_GETIPNODEBYADDR */ UNLOCK_DNS(); #endif /* _PR_HAVE_GETIPNODEBYADDR */ #if defined(_PR_HAVE_GETHOST_R) if (tmpbuf != localbuf) PR_Free(tmpbuf); #endif return rv; } /******************************************************************************/ /* * Some systems define a reentrant version of getprotobyname(). Too bad * the signature isn't always the same. But hey, they tried. If there * is such a definition, use it. Otherwise, grab a lock and do it here. */ /******************************************************************************/ #if !defined(_PR_HAVE_GETPROTO_R) /* * This may seem like a silly thing to do, but the compiler SHOULD * complain if getprotobyname_r() is implemented on some system and * we're not using it. For sure these signatures are different than * any usable implementation. */ #if defined(ANDROID) /* Android's Bionic libc system includes prototypes for these in netdb.h, * but doesn't actually include implementations. It uses the 5-arg form, * so these functions end up not matching the prototype. So just rename * them if not found. */ #define getprotobyname_r _pr_getprotobyname_r #define getprotobynumber_r _pr_getprotobynumber_r #endif static struct protoent *getprotobyname_r(const char* name) { return getprotobyname(name); } /* getprotobyname_r */ static struct protoent *getprotobynumber_r(PRInt32 number) { return getprotobynumber(number); } /* getprotobynumber_r */ #endif /* !defined(_PR_HAVE_GETPROTO_R) */ PR_IMPLEMENT(PRStatus) PR_GetProtoByName( const char* name, char* buffer, PRInt32 buflen, PRProtoEnt* result) { PRStatus rv = PR_SUCCESS; #if defined(_PR_HAVE_GETPROTO_R) struct protoent* res = (struct protoent*)result; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); #if defined(_PR_HAVE_GETPROTO_R_INT) { /* ** The protoent_data has a pointer as the first field. ** That implies the buffer better be aligned, and char* ** doesn't promise much. */ PRUptrdiff aligned = (PRUptrdiff)buffer; if (0 != (aligned & (sizeof(struct protoent_data*) - 1))) { aligned += sizeof(struct protoent_data*) - 1; aligned &= ~(sizeof(struct protoent_data*) - 1); buflen -= (aligned - (PRUptrdiff)buffer); buffer = (char*)aligned; } } #endif /* defined(_PR_HAVE_GETPROTO_R_INT) */ if (PR_NETDB_BUF_SIZE > buflen) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #if defined(_PR_HAVE_GETPROTO_R_POINTER) if (NULL == getprotobyname_r(name, res, buffer, buflen)) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); return PR_FAILURE; } #elif defined(_PR_HAVE_GETPROTO_R_INT) /* ** The buffer needs to be zero'd, and it should be ** at least the size of a struct protoent_data. */ memset(buffer, 0, buflen); if (-1 == getprotobyname_r(name, res, (struct protoent_data*)buffer)) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); return PR_FAILURE; } #elif defined(_PR_HAVE_5_ARG_GETPROTO_R) /* The 5th argument for getprotobyname_r() cannot be NULL */ if (-1 == getprotobyname_r(name, res, buffer, buflen, &res)) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); return PR_FAILURE; } #else /* do it the hard way */ { struct protoent *staticBuf; PR_Lock(_getproto_lock); staticBuf = getprotobyname_r(name); if (NULL == staticBuf) { rv = PR_FAILURE; PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); } else { #if defined(SYMBIAN) char* aliases[2]; AssignAliases(staticBuf, aliases); #endif rv = CopyProtoent(staticBuf, buffer, buflen, result); if (PR_FAILURE == rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } PR_Unlock(_getproto_lock); } #endif /* all that */ return rv; } PR_IMPLEMENT(PRStatus) PR_GetProtoByNumber( PRInt32 number, char* buffer, PRInt32 buflen, PRProtoEnt* result) { PRStatus rv = PR_SUCCESS; #if defined(_PR_HAVE_GETPROTO_R) struct protoent* res = (struct protoent*)result; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); #if defined(_PR_HAVE_GETPROTO_R_INT) { /* ** The protoent_data has a pointer as the first field. ** That implies the buffer better be aligned, and char* ** doesn't promise much. */ PRUptrdiff aligned = (PRUptrdiff)buffer; if (0 != (aligned & (sizeof(struct protoent_data*) - 1))) { aligned += sizeof(struct protoent_data*) - 1; aligned &= ~(sizeof(struct protoent_data*) - 1); buflen -= (aligned - (PRUptrdiff)buffer); buffer = (char*)aligned; } } #endif /* defined(_PR_HAVE_GETPROTO_R_INT) */ if (PR_NETDB_BUF_SIZE > buflen) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #if defined(_PR_HAVE_GETPROTO_R_POINTER) if (NULL == getprotobynumber_r(number, res, buffer, buflen)) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); return PR_FAILURE; } #elif defined(_PR_HAVE_GETPROTO_R_INT) /* ** The buffer needs to be zero'd for these OS's. */ memset(buffer, 0, buflen); if (-1 == getprotobynumber_r(number, res, (struct protoent_data*)buffer)) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); return PR_FAILURE; } #elif defined(_PR_HAVE_5_ARG_GETPROTO_R) /* The 5th argument for getprotobynumber_r() cannot be NULL */ if (-1 == getprotobynumber_r(number, res, buffer, buflen, &res)) { PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); return PR_FAILURE; } #else /* do it the hard way */ { struct protoent *staticBuf; PR_Lock(_getproto_lock); staticBuf = getprotobynumber_r(number); if (NULL == staticBuf) { rv = PR_FAILURE; PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_ERRNO()); } else { #if defined(SYMBIAN) char* aliases[2]; AssignAliases(staticBuf, aliases); #endif rv = CopyProtoent(staticBuf, buffer, buflen, result); if (PR_FAILURE == rv) PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); } PR_Unlock(_getproto_lock); } #endif /* all that crap */ return rv; } PRUintn _PR_NetAddrSize(const PRNetAddr* addr) { PRUintn addrsize; /* * RFC 2553 added a new field (sin6_scope_id) to * struct sockaddr_in6. PRNetAddr's ipv6 member has a * scope_id field to match the new field. In order to * work with older implementations supporting RFC 2133, * we take the size of struct sockaddr_in6 instead of * addr->ipv6. */ if (AF_INET == addr->raw.family) addrsize = sizeof(addr->inet); else if (PR_AF_INET6 == addr->raw.family) #if defined(_PR_INET6) addrsize = sizeof(struct sockaddr_in6); #else addrsize = sizeof(addr->ipv6); #endif #if defined(XP_UNIX) || defined(XP_OS2) else if (AF_UNIX == addr->raw.family) addrsize = sizeof(addr->local); #endif else addrsize = 0; return addrsize; } /* _PR_NetAddrSize */ PR_IMPLEMENT(PRIntn) PR_EnumerateHostEnt( PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address) { void *addr = hostEnt->h_addr_list[enumIndex++]; memset(address, 0, sizeof(PRNetAddr)); if (NULL == addr) enumIndex = 0; else { address->raw.family = hostEnt->h_addrtype; if (PR_AF_INET6 == hostEnt->h_addrtype) { address->ipv6.port = htons(port); address->ipv6.flowinfo = 0; address->ipv6.scope_id = 0; memcpy(&address->ipv6.ip, addr, hostEnt->h_length); } else { PR_ASSERT(AF_INET == hostEnt->h_addrtype); address->inet.port = htons(port); memcpy(&address->inet.ip, addr, hostEnt->h_length); } } return enumIndex; } /* PR_EnumerateHostEnt */ PR_IMPLEMENT(PRStatus) PR_InitializeNetAddr( PRNetAddrValue val, PRUint16 port, PRNetAddr *addr) { PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->inet)); addr->inet.family = AF_INET; addr->inet.port = htons(port); switch (val) { case PR_IpAddrNull: break; /* don't overwrite the address */ case PR_IpAddrAny: addr->inet.ip = htonl(INADDR_ANY); break; case PR_IpAddrLoopback: addr->inet.ip = htonl(INADDR_LOOPBACK); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = PR_FAILURE; } return rv; } /* PR_InitializeNetAddr */ PR_IMPLEMENT(PRStatus) PR_SetNetAddr( PRNetAddrValue val, PRUint16 af, PRUint16 port, PRNetAddr *addr) { PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); if (af == PR_AF_INET6) { if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->ipv6)); addr->ipv6.family = af; addr->ipv6.port = htons(port); addr->ipv6.flowinfo = 0; addr->ipv6.scope_id = 0; switch (val) { case PR_IpAddrNull: break; /* don't overwrite the address */ case PR_IpAddrAny: addr->ipv6.ip = _pr_in6addr_any; break; case PR_IpAddrLoopback: addr->ipv6.ip = _pr_in6addr_loopback; break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = PR_FAILURE; } } else { if (val != PR_IpAddrNull) memset(addr, 0, sizeof(addr->inet)); addr->inet.family = af; addr->inet.port = htons(port); switch (val) { case PR_IpAddrNull: break; /* don't overwrite the address */ case PR_IpAddrAny: addr->inet.ip = htonl(INADDR_ANY); break; case PR_IpAddrLoopback: addr->inet.ip = htonl(INADDR_LOOPBACK); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); rv = PR_FAILURE; } } return rv; } /* PR_SetNetAddr */ PR_IMPLEMENT(PRBool) PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val) { if (addr->raw.family == PR_AF_INET6) { if (val == PR_IpAddrAny) { if (_PR_IN6_IS_ADDR_UNSPECIFIED((PRIPv6Addr *)&addr->ipv6.ip)) { return PR_TRUE; } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) == htonl(INADDR_ANY)) { return PR_TRUE; } } else if (val == PR_IpAddrLoopback) { if (_PR_IN6_IS_ADDR_LOOPBACK((PRIPv6Addr *)&addr->ipv6.ip)) { return PR_TRUE; } else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip) && _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip) == htonl(INADDR_LOOPBACK)) { return PR_TRUE; } } else if (val == PR_IpAddrV4Mapped && _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)) { return PR_TRUE; } } else { if (addr->raw.family == AF_INET) { if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)) { return PR_TRUE; } else if (val == PR_IpAddrLoopback && addr->inet.ip == htonl(INADDR_LOOPBACK)) { return PR_TRUE; } } } return PR_FALSE; } extern int pr_inet_aton(const char *cp, PRUint32 *addr); #define XX 127 static const unsigned char index_hex[256] = { XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,XX,XX, XX,XX,XX,XX, XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,10,11,12, 13,14,15,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, }; /* * StringToV6Addr() returns 1 if the conversion succeeds, * or 0 if the input is not a valid IPv6 address string. * (Same as inet_pton(AF_INET6, string, addr).) */ static int StringToV6Addr(const char *string, PRIPv6Addr *addr) { const unsigned char *s = (const unsigned char *)string; int section = 0; /* index of the current section (a 16-bit * piece of the address */ int double_colon = -1; /* index of the section after the first * 16-bit group of zeros represented by * the double colon */ unsigned int val; int len; /* Handle initial (double) colon */ if (*s == ':') { if (s[1] != ':') return 0; s += 2; addr->pr_s6_addr16[0] = 0; section = double_colon = 1; } while (*s) { if (section == 8) return 0; /* too long */ if (*s == ':') { if (double_colon != -1) return 0; /* two double colons */ addr->pr_s6_addr16[section++] = 0; double_colon = section; s++; continue; } for (len = val = 0; len < 4 && index_hex[*s] != XX; len++) { val = (val << 4) + index_hex[*s++]; } if (*s == '.') { if (len == 0) return 0; /* nothing between : and . */ break; } if (*s == ':') { s++; if (!*s) return 0; /* cannot end with single colon */ } else if (*s) { return 0; /* bad character */ } addr->pr_s6_addr16[section++] = htons((unsigned short)val); } if (*s == '.') { /* Have a trailing v4 format address */ if (section > 6) return 0; /* not enough room */ /* * The number before the '.' is decimal, but we parsed it * as hex. That means it is in BCD. Check it for validity * and convert it to binary. */ if (val > 0x0255 || (val & 0xf0) > 0x90 || (val & 0xf) > 9) return 0; val = (val >> 8) * 100 + ((val >> 4) & 0xf) * 10 + (val & 0xf); addr->pr_s6_addr[2 * section] = val; s++; val = index_hex[*s++]; if (val > 9) return 0; while (*s >= '0' && *s <= '9') { val = val * 10 + *s++ - '0'; if (val > 255) return 0; } if (*s != '.') return 0; /* must have exactly 4 decimal numbers */ addr->pr_s6_addr[2 * section + 1] = val; section++; s++; val = index_hex[*s++]; if (val > 9) return 0; while (*s >= '0' && *s <= '9') { val = val * 10 + *s++ - '0'; if (val > 255) return 0; } if (*s != '.') return 0; /* must have exactly 4 decimal numbers */ addr->pr_s6_addr[2 * section] = val; s++; val = index_hex[*s++]; if (val > 9) return 0; while (*s >= '0' && *s <= '9') { val = val * 10 + *s++ - '0'; if (val > 255) return 0; } if (*s) return 0; /* must have exactly 4 decimal numbers */ addr->pr_s6_addr[2 * section + 1] = val; section++; } if (double_colon != -1) { /* Stretch the double colon */ int tosection; int ncopy = section - double_colon; for (tosection = 7; ncopy--; tosection--) { addr->pr_s6_addr16[tosection] = addr->pr_s6_addr16[double_colon + ncopy]; } while (tosection >= double_colon) { addr->pr_s6_addr16[tosection--] = 0; } } else if (section != 8) { return 0; /* too short */ } return 1; } #undef XX #ifndef _PR_HAVE_INET_NTOP static const char *basis_hex = "0123456789abcdef"; /* * V6AddrToString() returns a pointer to the buffer containing * the text string if the conversion succeeds, and NULL otherwise. * (Same as inet_ntop(AF_INET6, addr, buf, size), except that errno * is not set on failure.) */ static const char *V6AddrToString( const PRIPv6Addr *addr, char *buf, PRUint32 size) { #define STUFF(c) do { \ if (!size--) return NULL; \ *buf++ = (c); \ } while (0) int double_colon = -1; /* index of the first 16-bit * group of zeros represented * by the double colon */ int double_colon_length = 1; /* use double colon only if * there are two or more 16-bit * groups of zeros */ int zero_length; int section; unsigned int val; const char *bufcopy = buf; /* Scan to find the placement of the double colon */ for (section = 0; section < 8; section++) { if (addr->pr_s6_addr16[section] == 0) { zero_length = 1; section++; while (section < 8 && addr->pr_s6_addr16[section] == 0) { zero_length++; section++; } /* Select the longest sequence of zeros */ if (zero_length > double_colon_length) { double_colon = section - zero_length; double_colon_length = zero_length; } } } /* Now start converting to a string */ section = 0; if (double_colon == 0) { if (double_colon_length == 6 || (double_colon_length == 5 && addr->pr_s6_addr16[5] == 0xffff)) { /* ipv4 format address */ STUFF(':'); STUFF(':'); if (double_colon_length == 5) { STUFF('f'); STUFF('f'); STUFF('f'); STUFF('f'); STUFF(':'); } if (addr->pr_s6_addr[12] > 99) STUFF(addr->pr_s6_addr[12]/100 + '0'); if (addr->pr_s6_addr[12] > 9) STUFF((addr->pr_s6_addr[12]%100)/10 + '0'); STUFF(addr->pr_s6_addr[12]%10 + '0'); STUFF('.'); if (addr->pr_s6_addr[13] > 99) STUFF(addr->pr_s6_addr[13]/100 + '0'); if (addr->pr_s6_addr[13] > 9) STUFF((addr->pr_s6_addr[13]%100)/10 + '0'); STUFF(addr->pr_s6_addr[13]%10 + '0'); STUFF('.'); if (addr->pr_s6_addr[14] > 99) STUFF(addr->pr_s6_addr[14]/100 + '0'); if (addr->pr_s6_addr[14] > 9) STUFF((addr->pr_s6_addr[14]%100)/10 + '0'); STUFF(addr->pr_s6_addr[14]%10 + '0'); STUFF('.'); if (addr->pr_s6_addr[15] > 99) STUFF(addr->pr_s6_addr[15]/100 + '0'); if (addr->pr_s6_addr[15] > 9) STUFF((addr->pr_s6_addr[15]%100)/10 + '0'); STUFF(addr->pr_s6_addr[15]%10 + '0'); STUFF('\0'); return bufcopy; } } while (section < 8) { if (section == double_colon) { STUFF(':'); STUFF(':'); section += double_colon_length; continue; } val = ntohs(addr->pr_s6_addr16[section]); if (val > 0xfff) { STUFF(basis_hex[val >> 12]); } if (val > 0xff) { STUFF(basis_hex[(val >> 8) & 0xf]); } if (val > 0xf) { STUFF(basis_hex[(val >> 4) & 0xf]); } STUFF(basis_hex[val & 0xf]); section++; if (section < 8 && section != double_colon) STUFF(':'); } STUFF('\0'); return bufcopy; #undef STUFF } #endif /* !_PR_HAVE_INET_NTOP */ /* * Convert an IPv4 addr to an (IPv4-mapped) IPv6 addr */ PR_IMPLEMENT(void) PR_ConvertIPv4AddrToIPv6(PRUint32 v4addr, PRIPv6Addr *v6addr) { PRUint8 *dstp; dstp = v6addr->pr_s6_addr; memset(dstp, 0, 10); memset(dstp + 10, 0xff, 2); memcpy(dstp + 12,(char *) &v4addr, 4); } PR_IMPLEMENT(PRUint16) PR_ntohs(PRUint16 n) { return ntohs(n); } PR_IMPLEMENT(PRUint32) PR_ntohl(PRUint32 n) { return ntohl(n); } PR_IMPLEMENT(PRUint16) PR_htons(PRUint16 n) { return htons(n); } PR_IMPLEMENT(PRUint32) PR_htonl(PRUint32 n) { return htonl(n); } PR_IMPLEMENT(PRUint64) PR_ntohll(PRUint64 n) { #ifdef IS_BIG_ENDIAN return n; #else PRUint64 tmp; PRUint32 hi, lo; LL_L2UI(lo, n); LL_SHR(tmp, n, 32); LL_L2UI(hi, tmp); hi = PR_ntohl(hi); lo = PR_ntohl(lo); LL_UI2L(n, lo); LL_SHL(n, n, 32); LL_UI2L(tmp, hi); LL_ADD(n, n, tmp); return n; #endif } /* ntohll */ PR_IMPLEMENT(PRUint64) PR_htonll(PRUint64 n) { #ifdef IS_BIG_ENDIAN return n; #else PRUint64 tmp; PRUint32 hi, lo; LL_L2UI(lo, n); LL_SHR(tmp, n, 32); LL_L2UI(hi, tmp); hi = htonl(hi); lo = htonl(lo); LL_UI2L(n, lo); LL_SHL(n, n, 32); LL_UI2L(tmp, hi); LL_ADD(n, n, tmp); return n; #endif } /* htonll */ /* * Implementation of PR_GetAddrInfoByName and friends * * Compile-time options: * * _PR_HAVE_GETADDRINFO Define this macro if the target system provides * getaddrinfo. With this defined, NSPR will require * getaddrinfo at run time. If this if not defined, * then NSPR will attempt to dynamically resolve * getaddrinfo, falling back to PR_GetHostByName if * getaddrinfo does not exist on the target system. * * Since getaddrinfo is a relatively new system call on many systems, * we are forced to dynamically resolve it at run time in most cases. * The exception includes any system (such as Mac OS X) that is known to * provide getaddrinfo in all versions that NSPR cares to support. */ #if defined(_PR_HAVE_GETADDRINFO) #if defined(_PR_INET6) typedef struct addrinfo PRADDRINFO; #define GETADDRINFO getaddrinfo #define FREEADDRINFO freeaddrinfo #define GETNAMEINFO getnameinfo #elif defined(_PR_INET6_PROBE) typedef struct addrinfo PRADDRINFO; /* getaddrinfo/freeaddrinfo/getnameinfo prototypes */ #if defined(WIN32) #define FUNC_MODIFIER __stdcall #else #define FUNC_MODIFIER #endif typedef int (FUNC_MODIFIER * FN_GETADDRINFO) (const char *nodename, const char *servname, const PRADDRINFO *hints, PRADDRINFO **res); typedef int (FUNC_MODIFIER * FN_FREEADDRINFO) (PRADDRINFO *ai); typedef int (FUNC_MODIFIER * FN_GETNAMEINFO) (const struct sockaddr *addr, int addrlen, char *host, int hostlen, char *serv, int servlen, int flags); /* global state */ static FN_GETADDRINFO _pr_getaddrinfo = NULL; static FN_FREEADDRINFO _pr_freeaddrinfo = NULL; static FN_GETNAMEINFO _pr_getnameinfo = NULL; #define GETADDRINFO_SYMBOL "getaddrinfo" #define FREEADDRINFO_SYMBOL "freeaddrinfo" #define GETNAMEINFO_SYMBOL "getnameinfo" PRStatus _pr_find_getaddrinfo(void) { PRLibrary *lib; #ifdef WIN32 /* * On windows, we need to search ws2_32.dll or wship6.dll * (Microsoft IPv6 Technology Preview for Windows 2000) for * getaddrinfo and freeaddrinfo. These libraries might not * be loaded yet. */ const char *libname[] = { "ws2_32.dll", "wship6.dll" }; int i; for (i = 0; i < sizeof(libname)/sizeof(libname[0]); i++) { lib = PR_LoadLibrary(libname[i]); if (!lib) { continue; } _pr_getaddrinfo = (FN_GETADDRINFO) PR_FindFunctionSymbol(lib, GETADDRINFO_SYMBOL); if (!_pr_getaddrinfo) { PR_UnloadLibrary(lib); continue; } _pr_freeaddrinfo = (FN_FREEADDRINFO) PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL); _pr_getnameinfo = (FN_GETNAMEINFO) PR_FindFunctionSymbol(lib, GETNAMEINFO_SYMBOL); if (!_pr_freeaddrinfo || !_pr_getnameinfo) { PR_UnloadLibrary(lib); continue; } /* Keep the library loaded. */ return PR_SUCCESS; } return PR_FAILURE; #else /* * Resolve getaddrinfo by searching all loaded libraries. Then * search library containing getaddrinfo for freeaddrinfo. */ _pr_getaddrinfo = (FN_GETADDRINFO) PR_FindFunctionSymbolAndLibrary(GETADDRINFO_SYMBOL, &lib); if (!_pr_getaddrinfo) { return PR_FAILURE; } _pr_freeaddrinfo = (FN_FREEADDRINFO) PR_FindFunctionSymbol(lib, FREEADDRINFO_SYMBOL); _pr_getnameinfo = (FN_GETNAMEINFO) PR_FindFunctionSymbol(lib, GETNAMEINFO_SYMBOL); PR_UnloadLibrary(lib); if (!_pr_freeaddrinfo || !_pr_getnameinfo) { return PR_FAILURE; } return PR_SUCCESS; #endif } #define GETADDRINFO (*_pr_getaddrinfo) #define FREEADDRINFO (*_pr_freeaddrinfo) #define GETNAMEINFO (*_pr_getnameinfo) #endif /* _PR_INET6 */ #endif /* _PR_HAVE_GETADDRINFO */ #if !defined(_PR_HAVE_GETADDRINFO) || defined(_PR_INET6_PROBE) /* * If getaddrinfo does not exist, then we will fall back on * PR_GetHostByName, which requires that we allocate a buffer for the * PRHostEnt data structure and its members. */ typedef struct PRAddrInfoFB { char buf[PR_NETDB_BUF_SIZE]; PRHostEnt hostent; PRBool has_cname; } PRAddrInfoFB; static PRAddrInfo * pr_GetAddrInfoByNameFB(const char *hostname, PRUint16 af, PRIntn flags) { PRStatus rv; PRAddrInfoFB *ai; /* fallback on PR_GetHostByName */ ai = PR_NEW(PRAddrInfoFB); if (!ai) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } rv = PR_GetHostByName(hostname, ai->buf, sizeof ai->buf, &ai->hostent); if (rv == PR_FAILURE) { PR_Free(ai); return NULL; } ai->has_cname = !(flags & PR_AI_NOCANONNAME); return (PRAddrInfo *) ai; } #endif /* !_PR_HAVE_GETADDRINFO || _PR_INET6_PROBE */ PR_IMPLEMENT(PRAddrInfo *) PR_GetAddrInfoByName(const char *hostname, PRUint16 af, PRIntn flags) { /* restrict input to supported values */ if ((af != PR_AF_INET && af != PR_AF_UNSPEC) || (flags & ~ PR_AI_NOCANONNAME) != PR_AI_ADDRCONFIG) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } if (!_pr_initialized) _PR_ImplicitInitialization(); #if !defined(_PR_HAVE_GETADDRINFO) return pr_GetAddrInfoByNameFB(hostname, af, flags); #else #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) { return pr_GetAddrInfoByNameFB(hostname, af, flags); } #endif { PRADDRINFO *res, hints; int rv; /* * we assume a RFC 2553 compliant getaddrinfo. this may at some * point need to be customized as platforms begin to adopt the * RFC 3493. */ memset(&hints, 0, sizeof(hints)); if (!(flags & PR_AI_NOCANONNAME)) hints.ai_flags |= AI_CANONNAME; #ifdef AI_ADDRCONFIG /* * Propagate AI_ADDRCONFIG to the GETADDRINFO call if PR_AI_ADDRCONFIG * is set. * * Need a workaround for loopback host addresses: * The problem is that in glibc and Windows, AI_ADDRCONFIG applies the * existence of an outgoing network interface to IP addresses of the * loopback interface, due to a strict interpretation of the * specification. For example, if a computer does not have any * outgoing IPv6 network interface, but its loopback network interface * supports IPv6, a getaddrinfo call on "localhost" with AI_ADDRCONFIG * won't return the IPv6 loopback address "::1", because getaddrinfo * thinks the computer cannot connect to any IPv6 destination, * ignoring the remote vs. local/loopback distinction. */ if ((flags & PR_AI_ADDRCONFIG) && strcmp(hostname, "localhost") != 0 && strcmp(hostname, "localhost.localdomain") != 0 && strcmp(hostname, "localhost6") != 0 && strcmp(hostname, "localhost6.localdomain6") != 0) { hints.ai_flags |= AI_ADDRCONFIG; } #endif hints.ai_family = (af == PR_AF_INET) ? AF_INET : AF_UNSPEC; /* * it is important to select a socket type in the hints, otherwise we * will get back repetitive entries: one for each socket type. since * we do not expose ai_socktype through our API, it is okay to do this * here. the application may still choose to create a socket of some * other type. */ hints.ai_socktype = SOCK_STREAM; rv = GETADDRINFO(hostname, NULL, &hints, &res); #ifdef AI_ADDRCONFIG if (rv == EAI_BADFLAGS && (hints.ai_flags & AI_ADDRCONFIG)) { hints.ai_flags &= ~AI_ADDRCONFIG; rv = GETADDRINFO(hostname, NULL, &hints, &res); } #endif if (rv == 0) return (PRAddrInfo *) res; PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, rv); } return NULL; #endif } PR_IMPLEMENT(void) PR_FreeAddrInfo(PRAddrInfo *ai) { #if defined(_PR_HAVE_GETADDRINFO) #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) PR_Free((PRAddrInfoFB *) ai); else #endif FREEADDRINFO((PRADDRINFO *) ai); #else PR_Free((PRAddrInfoFB *) ai); #endif } PR_IMPLEMENT(void *) PR_EnumerateAddrInfo(void *iterPtr, const PRAddrInfo *base, PRUint16 port, PRNetAddr *result) { #if defined(_PR_HAVE_GETADDRINFO) PRADDRINFO *ai; #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) { /* using PRAddrInfoFB */ PRIntn iter = (PRIntn)(PRPtrdiff) iterPtr; iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result); if (iter < 0) iter = 0; return (void *)(PRPtrdiff) iter; } #endif if (iterPtr) ai = ((PRADDRINFO *) iterPtr)->ai_next; else ai = (PRADDRINFO *) base; while (ai && ai->ai_addrlen > sizeof(PRNetAddr)) ai = ai->ai_next; if (ai) { /* copy sockaddr to PRNetAddr */ memcpy(result, ai->ai_addr, ai->ai_addrlen); result->raw.family = ai->ai_addr->sa_family; #ifdef _PR_INET6 if (AF_INET6 == result->raw.family) result->raw.family = PR_AF_INET6; #endif if (ai->ai_addrlen < sizeof(PRNetAddr)) memset(((char*)result)+ai->ai_addrlen, 0, sizeof(PRNetAddr) - ai->ai_addrlen); if (result->raw.family == PR_AF_INET) result->inet.port = htons(port); else result->ipv6.port = htons(port); } return ai; #else /* using PRAddrInfoFB */ PRIntn iter = (PRIntn) iterPtr; iter = PR_EnumerateHostEnt(iter, &((PRAddrInfoFB *) base)->hostent, port, result); if (iter < 0) iter = 0; return (void *) iter; #endif } PR_IMPLEMENT(const char *) PR_GetCanonNameFromAddrInfo(const PRAddrInfo *ai) { #if defined(_PR_HAVE_GETADDRINFO) #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) { const PRAddrInfoFB *fb = (const PRAddrInfoFB *) ai; return fb->has_cname ? fb->hostent.h_name : NULL; } #endif return ((const PRADDRINFO *) ai)->ai_canonname; #else const PRAddrInfoFB *fb = (const PRAddrInfoFB *) ai; return fb->has_cname ? fb->hostent.h_name : NULL; #endif } #if defined(_PR_HAVE_GETADDRINFO) static PRStatus pr_StringToNetAddrGAI(const char *string, PRNetAddr *addr) { PRADDRINFO *res, hints; int rv; /* 0 for success, or the error code EAI_xxx */ PRNetAddr laddr; PRStatus status = PR_SUCCESS; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; rv = GETADDRINFO(string, NULL, &hints, &res); if (rv != 0) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, rv); return PR_FAILURE; } /* pick up the first addr */ memcpy(&laddr, res->ai_addr, res->ai_addrlen); if (AF_INET6 == res->ai_addr->sa_family) { addr->ipv6.family = PR_AF_INET6; addr->ipv6.ip = laddr.ipv6.ip; addr->ipv6.scope_id = laddr.ipv6.scope_id; } else if (AF_INET == res->ai_addr->sa_family) { addr->inet.family = PR_AF_INET; addr->inet.ip = laddr.inet.ip; } else { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); status = PR_FAILURE; } FREEADDRINFO(res); return status; } #endif /* _PR_HAVE_GETADDRINFO */ static PRStatus pr_StringToNetAddrFB(const char *string, PRNetAddr *addr) { PRIntn rv; rv = pr_inet_aton(string, &addr->inet.ip); if (1 == rv) { addr->raw.family = AF_INET; return PR_SUCCESS; } PR_ASSERT(0 == rv); /* clean up after the failed call */ memset(&addr->inet.ip, 0, sizeof(addr->inet.ip)); rv = StringToV6Addr(string, &addr->ipv6.ip); if (1 == rv) { addr->raw.family = PR_AF_INET6; return PR_SUCCESS; } PR_ASSERT(0 == rv); PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) PR_StringToNetAddr(const char *string, PRNetAddr *addr) { if (!_pr_initialized) _PR_ImplicitInitialization(); if (!addr || !string || !*string) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } #if !defined(_PR_HAVE_GETADDRINFO) return pr_StringToNetAddrFB(string, addr); #else /* * getaddrinfo with AI_NUMERICHOST is much slower than pr_inet_aton on some * platforms, such as Mac OS X (bug 404399), Linux glibc 2.10 (bug 344809), * and most likely others. So we only use it to convert literal IP addresses * that contain IPv6 scope IDs, which pr_inet_aton cannot convert. */ if (!strchr(string, '%')) return pr_StringToNetAddrFB(string, addr); #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) return pr_StringToNetAddrFB(string, addr); #endif return pr_StringToNetAddrGAI(string, addr); #endif } #if defined(_PR_HAVE_GETADDRINFO) static PRStatus pr_NetAddrToStringGNI( const PRNetAddr *addr, char *string, PRUint32 size) { int addrlen; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) PRUint16 md_af = addr->raw.family; PRNetAddr addrcopy; #endif int rv; /* 0 for success, or the error code EAI_xxx */ #ifdef _PR_INET6 if (addr->raw.family == PR_AF_INET6) { md_af = AF_INET6; #ifndef _PR_HAVE_SOCKADDR_LEN addrcopy = *addr; addrcopy.raw.family = md_af; addrp = &addrcopy; #endif } #endif addrlen = PR_NETADDR_SIZE(addr); #ifdef _PR_HAVE_SOCKADDR_LEN addrcopy = *addr; ((struct sockaddr*)&addrcopy)->sa_len = addrlen; ((struct sockaddr*)&addrcopy)->sa_family = md_af; addrp = &addrcopy; #endif rv = GETNAMEINFO((const struct sockaddr *)addrp, addrlen, string, size, NULL, 0, NI_NUMERICHOST); if (rv != 0) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, rv); return PR_FAILURE; } return PR_SUCCESS; } #endif /* _PR_HAVE_GETADDRINFO */ #if !defined(_PR_HAVE_GETADDRINFO) || defined(_PR_INET6_PROBE) static PRStatus pr_NetAddrToStringFB( const PRNetAddr *addr, char *string, PRUint32 size) { if (PR_AF_INET6 == addr->raw.family) { #if defined(_PR_HAVE_INET_NTOP) if (NULL == inet_ntop(AF_INET6, &addr->ipv6.ip, string, size)) #else if (NULL == V6AddrToString(&addr->ipv6.ip, string, size)) #endif { /* the size of the result buffer is inadequate */ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); return PR_FAILURE; } } else { if (size < 16) goto failed; if (AF_INET != addr->raw.family) goto failed; else { unsigned char *byte = (unsigned char*)&addr->inet.ip; PR_snprintf(string, size, "%u.%u.%u.%u", byte[0], byte[1], byte[2], byte[3]); } } return PR_SUCCESS; failed: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } /* pr_NetAddrToStringFB */ #endif /* !_PR_HAVE_GETADDRINFO || _PR_INET6_PROBE */ PR_IMPLEMENT(PRStatus) PR_NetAddrToString( const PRNetAddr *addr, char *string, PRUint32 size) { if (!_pr_initialized) _PR_ImplicitInitialization(); #if !defined(_PR_HAVE_GETADDRINFO) return pr_NetAddrToStringFB(addr, string, size); #else #if defined(_PR_INET6_PROBE) if (!_pr_ipv6_is_present()) return pr_NetAddrToStringFB(addr, string, size); #endif return pr_NetAddrToStringGNI(addr, string, size); #endif } /* PR_NetAddrToString */ nspr-4.11/nspr/pr/src/misc/prolock.c0000644000000000000000000000262212623070344015514 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prolock.c -- NSPR Ordered Lock ** ** Implement the API defined in prolock.h ** */ #include "prolock.h" #include "prlog.h" #include "prerror.h" PR_IMPLEMENT(PROrderedLock *) PR_CreateOrderedLock( PRInt32 order, const char *name ) { PR_NOT_REACHED("Not implemented"); /* Not implemented yet */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } /* end PR_CreateOrderedLock() */ PR_IMPLEMENT(void) PR_DestroyOrderedLock( PROrderedLock *lock ) { PR_NOT_REACHED("Not implemented"); /* Not implemented yet */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); } /* end PR_DestroyOrderedLock() */ PR_IMPLEMENT(void) PR_LockOrderedLock( PROrderedLock *lock ) { PR_NOT_REACHED("Not implemented"); /* Not implemented yet */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); } /* end PR_LockOrderedLock() */ PR_IMPLEMENT(PRStatus) PR_UnlockOrderedLock( PROrderedLock *lock ) { PR_NOT_REACHED("Not implemented"); /* Not implemented yet */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } /* end PR_UnlockOrderedLock() */ nspr-4.11/nspr/pr/src/misc/prrng.c0000644000000000000000000000232712623070344015175 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /* * We were not including in optimized builds. On AIX this * caused libnspr4.so to export memcpy and some binaries linked with * libnspr4.so resolved their memcpy references with libnspr4.so. To * be backward compatible with old libnspr4.so binaries, we do not * include in optimized builds for AIX. (bug 200561) */ #if !(defined(AIX) && !defined(DEBUG)) #include #endif PRSize _pr_CopyLowBits( void *dst, PRSize dstlen, void *src, PRSize srclen ) { if (srclen <= dstlen) { memcpy(dst, src, srclen); return srclen; } #if defined IS_BIG_ENDIAN memcpy(dst, (char*)src + (srclen - dstlen), dstlen); #else memcpy(dst, src, dstlen); #endif return dstlen; } PR_IMPLEMENT(PRSize) PR_GetRandomNoise( void *buf, PRSize size ) { return( _PR_MD_GET_RANDOM_NOISE( buf, size )); } /* end PR_GetRandomNoise() */ /* end prrng.c */ nspr-4.11/nspr/pr/src/misc/prsystem.c0000644000000000000000000002311212623070344015726 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include "prsystem.h" #include "prprf.h" #include "prlong.h" #if defined(BEOS) #include #endif #if defined(OS2) #define INCL_DOS #define INCL_DOSMISC #include /* define the required constant if it is not already defined in the headers */ #ifndef QSV_NUMPROCESSORS #define QSV_NUMPROCESSORS 26 #endif #endif /* BSD-derived systems use sysctl() to get the number of processors */ #if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \ || defined(OPENBSD) || defined(DRAGONFLY) || defined(DARWIN) #define _PR_HAVE_SYSCTL #include #include #endif #if defined(DARWIN) #include #include #include #endif #if defined(HPUX) #include #include #endif #if defined(XP_UNIX) #include #include #endif #if defined(LINUX) #include #include #define MAX_LINE 512 #endif #if defined(AIX) #include #include #endif PR_IMPLEMENT(char) PR_GetDirectorySeparator(void) { return PR_DIRECTORY_SEPARATOR; } /* PR_GetDirectorySeparator */ /* ** OBSOLETE -- the function name is misspelled. */ PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) { #if defined(DEBUG) static PRBool warn = PR_TRUE; if (warn) { warn = _PR_Obsolete("PR_GetDirectorySepartor()", "PR_GetDirectorySeparator()"); } #endif return PR_GetDirectorySeparator(); } /* PR_GetDirectorySepartor */ PR_IMPLEMENT(char) PR_GetPathSeparator(void) { return PR_PATH_SEPARATOR; } /* PR_GetPathSeparator */ PR_IMPLEMENT(PRStatus) PR_GetSystemInfo(PRSysInfo cmd, char *buf, PRUint32 buflen) { PRUintn len = 0; if (!_pr_initialized) _PR_ImplicitInitialization(); switch(cmd) { case PR_SI_HOSTNAME: case PR_SI_HOSTNAME_UNTRUNCATED: if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) return PR_FAILURE; if (cmd == PR_SI_HOSTNAME_UNTRUNCATED) break; /* * On some platforms a system does not have a hostname and * its IP address is returned instead. The following code * should be skipped on those platforms. */ #ifndef _PR_GET_HOST_ADDR_AS_NAME /* Return the unqualified hostname */ while (buf[len] && (len < buflen)) { if (buf[len] == '.') { buf[len] = '\0'; break; } len += 1; } #endif break; case PR_SI_SYSNAME: /* Return the operating system name */ #if defined(XP_UNIX) || defined(WIN32) if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) return PR_FAILURE; #else (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME); #endif break; case PR_SI_RELEASE: /* Return the version of the operating system */ #if defined(XP_UNIX) || defined(WIN32) if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) return PR_FAILURE; #endif #if defined(XP_OS2) { ULONG os2ver[2] = {0}; DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_REVISION, &os2ver, sizeof(os2ver)); /* Formatting for normal usage (2.11, 3.0, 4.0, 4.5); officially, Warp 4 is version 2.40.00, WSeB 2.45.00 */ if (os2ver[0] < 30) (void)PR_snprintf(buf, buflen, "%s%lu", "2.", os2ver[0]); else if (os2ver[0] < 45) (void)PR_snprintf(buf, buflen, "%lu%s%lu", os2ver[0]/10, ".", os2ver[1]); else (void)PR_snprintf(buf, buflen, "%.1f", os2ver[0]/10.0); } #endif /* OS2 */ break; case PR_SI_ARCHITECTURE: /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/ (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE); break; default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } return PR_SUCCESS; } /* ** PR_GetNumberOfProcessors() ** ** Implementation notes: ** Every platform does it a bit different. ** numCpus is the returned value. ** for each platform's "if defined" section ** declare your local variable ** do your thing, assign to numCpus ** order of the if defined()s may be important, ** especially for unix variants. Do platform ** specific implementations before XP_UNIX. ** */ PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors( void ) { PRInt32 numCpus; #if defined(WIN32) SYSTEM_INFO info; GetSystemInfo( &info ); numCpus = info.dwNumberOfProcessors; #elif defined(BEOS) system_info sysInfo; get_system_info(&sysInfo); numCpus = sysInfo.cpu_count; #elif defined(OS2) DosQuerySysInfo( QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &numCpus, sizeof(numCpus)); #elif defined(_PR_HAVE_SYSCTL) int mib[2]; int rc; size_t len = sizeof(numCpus); mib[0] = CTL_HW; mib[1] = HW_NCPU; rc = sysctl( mib, 2, &numCpus, &len, NULL, 0 ); if ( -1 == rc ) { numCpus = -1; /* set to -1 for return value on error */ _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() ); } #elif defined(HPUX) numCpus = mpctl( MPC_GETNUMSPUS, 0, 0 ); if ( numCpus < 1 ) { numCpus = -1; /* set to -1 for return value on error */ _PR_MD_MAP_DEFAULT_ERROR( _MD_ERRNO() ); } #elif defined(IRIX) numCpus = sysconf( _SC_NPROC_ONLN ); #elif defined(RISCOS) || defined(SYMBIAN) numCpus = 1; #elif defined(LINUX) /* for the benefit of devices with advanced power-saving, that actually hotplug their cpus in heavy load, try to figure out the real number of CPUs */ char buf[MAX_LINE]; FILE *fin; const char *cpu_present = "/sys/devices/system/cpu/present"; size_t strsize; numCpus = 0; fin = fopen(cpu_present, "r"); if (fin != NULL) { if (fgets(buf, MAX_LINE, fin) != NULL) { /* check that the format is what we expect */ if (buf[0] == '0') { strsize = strlen(buf); if (strsize == 1) { /* single core */ numCpus = 1; } else if (strsize >= 3 && strsize <= 5) { /* should be of the form 0-999 */ /* parse the part after the 0-, note count is 0-based */ if (buf[1] == '-' && isdigit(buf[2])) { numCpus = 1 + atoi(buf + 2); } } } } fclose(fin); } /* if that fails, fall back to more standard methods */ if (!numCpus) { numCpus = sysconf( _SC_NPROCESSORS_CONF ); } #elif defined(XP_UNIX) numCpus = sysconf( _SC_NPROCESSORS_CONF ); #else #error "An implementation is required" #endif return(numCpus); } /* end PR_GetNumberOfProcessors() */ /* ** PR_GetPhysicalMemorySize() ** ** Implementation notes: ** Every platform does it a bit different. ** bytes is the returned value. ** for each platform's "if defined" section ** declare your local variable ** do your thing, assign to bytes. ** */ PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void) { PRUint64 bytes = 0; #if defined(LINUX) || defined(SOLARIS) long pageSize = sysconf(_SC_PAGESIZE); long pageCount = sysconf(_SC_PHYS_PAGES); if (pageSize >= 0 && pageCount >= 0) bytes = (PRUint64) pageSize * pageCount; #elif defined(NETBSD) || defined(OPENBSD) \ || defined(FREEBSD) || defined(DRAGONFLY) int mib[2]; int rc; #ifdef HW_PHYSMEM64 uint64_t memSize; #else unsigned long memSize; #endif size_t len = sizeof(memSize); mib[0] = CTL_HW; #ifdef HW_PHYSMEM64 mib[1] = HW_PHYSMEM64; #else mib[1] = HW_PHYSMEM; #endif rc = sysctl(mib, 2, &memSize, &len, NULL, 0); if (-1 != rc) { bytes = memSize; } #elif defined(HPUX) struct pst_static info; int result = pstat_getstatic(&info, sizeof(info), 1, 0); if (result == 1) bytes = (PRUint64) info.physical_memory * info.page_size; #elif defined(DARWIN) mach_port_t mach_host = mach_host_self(); struct host_basic_info hInfo; mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; int result = host_info(mach_host, HOST_BASIC_INFO, (host_info_t) &hInfo, &count); mach_port_deallocate(mach_task_self(), mach_host); if (result == KERN_SUCCESS) bytes = hInfo.max_mem; #elif defined(WIN32) MEMORYSTATUSEX memStat; memStat.dwLength = sizeof(memStat); if (GlobalMemoryStatusEx(&memStat)) bytes = memStat.ullTotalPhys; #elif defined(OS2) ULONG ulPhysMem; DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, &ulPhysMem, sizeof(ulPhysMem)); bytes = ulPhysMem; #elif defined(AIX) if (odm_initialize() == 0) { int how_many; struct CuAt *obj = getattr("sys0", "realmem", 0, &how_many); if (obj != NULL) { bytes = (PRUint64) atoi(obj->value) * 1024; free(obj); } odm_terminate(); } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); #endif return bytes; } /* end PR_GetPhysicalMemorySize() */ nspr-4.11/nspr/pr/src/misc/prthinfo.c0000644000000000000000000001362512623070344015701 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prlog.h" #include "prthread.h" #include "private/pprthred.h" #include "primpl.h" PR_IMPLEMENT(PRWord *) PR_GetGCRegisters(PRThread *t, int isCurrent, int *np) { return _MD_HomeGCRegisters(t, isCurrent, np); } PR_IMPLEMENT(PRStatus) PR_ThreadScanStackPointers(PRThread* t, PRScanStackFun scanFun, void* scanClosure) { PRThread* current = PR_GetCurrentThread(); PRWord *sp, *esp, *p0; int n; void **ptd; PRStatus status; PRUint32 index; int stack_end; /* ** Store the thread's registers in the thread structure so the GC ** can scan them. Then scan them. */ p0 = _MD_HomeGCRegisters(t, t == current, &n); status = scanFun(t, (void**)p0, n, scanClosure); if (status != PR_SUCCESS) return status; /* Scan the C stack for pointers into the GC heap */ #if defined(XP_PC) && defined(WIN16) /* ** Under WIN16, the stack of the current thread is always mapped into ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan ** the "task stack". Otherwise, scan the "cached stack" of the inactive ** thread... */ if (t == current) { sp = (PRWord*) &stack_end; esp = (PRWord*) _pr_top_of_task_stack; PR_ASSERT(sp <= esp); } else { sp = (PRWord*) PR_GetSP(t); esp = (PRWord*) t->stack->stackTop; PR_ASSERT((t->stack->stackSize == 0) || ((sp > (PRWord*)t->stack->stackBottom) && (sp <= (PRWord*)t->stack->stackTop))); } #else /* ! WIN16 */ #ifdef HAVE_STACK_GROWING_UP if (t == current) { esp = (PRWord*) &stack_end; } else { esp = (PRWord*) PR_GetSP(t); } sp = (PRWord*) t->stack->stackTop; if (t->stack->stackSize) { PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && (esp < (PRWord*)t->stack->stackBottom)); } #else /* ! HAVE_STACK_GROWING_UP */ if (t == current) { sp = (PRWord*) &stack_end; } else { sp = (PRWord*) PR_GetSP(t); } esp = (PRWord*) t->stack->stackTop; if (t->stack->stackSize) { PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && (sp < (PRWord*)t->stack->stackTop)); } #endif /* ! HAVE_STACK_GROWING_UP */ #endif /* ! WIN16 */ #if defined(WIN16) { prword_t scan; prword_t limit; scan = (prword_t) sp; limit = (prword_t) esp; while (scan < limit) { prword_t *test; test = *((prword_t **)scan); status = scanFun(t, (void**)&test, 1, scanClosure); if (status != PR_SUCCESS) return status; scan += sizeof(char); } } #else if (sp < esp) { status = scanFun(t, (void**)sp, esp - sp, scanClosure); if (status != PR_SUCCESS) return status; } #endif /* ** Mark all of the per-thread-data items attached to this thread ** ** The execution environment better be accounted for otherwise it ** will be collected */ status = scanFun(t, (void**)&t->environment, 1, scanClosure); if (status != PR_SUCCESS) return status; /* if thread is not allocated on stack, this is redundant. */ ptd = t->privateData; for (index = 0; index < t->tpdLength; index++, ptd++) { status = scanFun(t, (void**)ptd, 1, scanClosure); if (status != PR_SUCCESS) return status; } return PR_SUCCESS; } /* transducer for PR_EnumerateThreads */ typedef struct PRScanStackData { PRScanStackFun scanFun; void* scanClosure; } PRScanStackData; static PRStatus PR_CALLBACK pr_ScanStack(PRThread* t, int i, void* arg) { PRScanStackData* data = (PRScanStackData*)arg; return PR_ThreadScanStackPointers(t, data->scanFun, data->scanClosure); } PR_IMPLEMENT(PRStatus) PR_ScanStackPointers(PRScanStackFun scanFun, void* scanClosure) { PRScanStackData data; data.scanFun = scanFun; data.scanClosure = scanClosure; return PR_EnumerateThreads(pr_ScanStack, &data); } PR_IMPLEMENT(PRUword) PR_GetStackSpaceLeft(PRThread* t) { PRThread *current = PR_GetCurrentThread(); PRWord *sp, *esp; int stack_end; #if defined(WIN16) /* ** Under WIN16, the stack of the current thread is always mapped into ** the "task stack" (at SS:xxxx). So, if t is the current thread, scan ** the "task stack". Otherwise, scan the "cached stack" of the inactive ** thread... */ if (t == current) { sp = (PRWord*) &stack_end; esp = (PRWord*) _pr_top_of_task_stack; PR_ASSERT(sp <= esp); } else { sp = (PRWord*) PR_GetSP(t); esp = (PRWord*) t->stack->stackTop; PR_ASSERT((t->stack->stackSize == 0) || ((sp > (PRWord*)t->stack->stackBottom) && (sp <= (PRWord*)t->stack->stackTop))); } #else /* ! WIN16 */ #ifdef HAVE_STACK_GROWING_UP if (t == current) { esp = (PRWord*) &stack_end; } else { esp = (PRWord*) PR_GetSP(t); } sp = (PRWord*) t->stack->stackTop; if (t->stack->stackSize) { PR_ASSERT((esp > (PRWord*)t->stack->stackTop) && (esp < (PRWord*)t->stack->stackBottom)); } #else /* ! HAVE_STACK_GROWING_UP */ if (t == current) { sp = (PRWord*) &stack_end; } else { sp = (PRWord*) PR_GetSP(t); } esp = (PRWord*) t->stack->stackTop; if (t->stack->stackSize) { PR_ASSERT((sp > (PRWord*)t->stack->stackBottom) && (sp < (PRWord*)t->stack->stackTop)); } #endif /* ! HAVE_STACK_GROWING_UP */ #endif /* ! WIN16 */ return (PRUword)t->stack->stackSize - ((PRWord)esp - (PRWord)sp); } nspr-4.11/nspr/pr/src/misc/prtime.c0000644000000000000000000021555212623070344015353 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * prtime.c -- * * NSPR date and time functions * */ #include "prinit.h" #include "prtime.h" #include "prlock.h" #include "prprf.h" #include "prlog.h" #include #include #include /* for EINVAL */ #include /* * The COUNT_LEAPS macro counts the number of leap years passed by * till the start of the given year Y. At the start of the year 4 * A.D. the number of leap years passed by is 0, while at the start of * the year 5 A.D. this count is 1. The number of years divisible by * 100 but not divisible by 400 (the non-leap years) is deducted from * the count to get the correct number of leap years. * * The COUNT_DAYS macro counts the number of days since 01/01/01 till the * start of the given year Y. The number of days at the start of the year * 1 is 0 while the number of days at the start of the year 2 is 365 * (which is ((2)-1) * 365) and so on. The reference point is 01/01/01 * midnight 00:00:00. */ #define COUNT_LEAPS(Y) ( ((Y)-1)/4 - ((Y)-1)/100 + ((Y)-1)/400 ) #define COUNT_DAYS(Y) ( ((Y)-1)*365 + COUNT_LEAPS(Y) ) #define DAYS_BETWEEN_YEARS(A, B) (COUNT_DAYS(B) - COUNT_DAYS(A)) /* * Static variables used by functions in this file */ /* * The following array contains the day of year for the last day of * each month, where index 1 is January, and day 0 is January 1. */ static const int lastDayOfMonth[2][13] = { {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365} }; /* * The number of days in a month */ static const PRInt8 nDays[2][12] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; /* * Declarations for internal functions defined later in this file. */ static void ComputeGMT(PRTime time, PRExplodedTime *gmt); static int IsLeapYear(PRInt16 year); static void ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset); /* *------------------------------------------------------------------------ * * ComputeGMT -- * * Caveats: * - we ignore leap seconds * *------------------------------------------------------------------------ */ static void ComputeGMT(PRTime time, PRExplodedTime *gmt) { PRInt32 tmp, rem; PRInt32 numDays; PRInt64 numDays64, rem64; int isLeap; PRInt64 sec; PRInt64 usec; PRInt64 usecPerSec; PRInt64 secPerDay; /* * We first do the usec, sec, min, hour thing so that we do not * have to do LL arithmetic. */ LL_I2L(usecPerSec, 1000000L); LL_DIV(sec, time, usecPerSec); LL_MOD(usec, time, usecPerSec); LL_L2I(gmt->tm_usec, usec); /* Correct for weird mod semantics so the remainder is always positive */ if (gmt->tm_usec < 0) { PRInt64 one; LL_I2L(one, 1L); LL_SUB(sec, sec, one); gmt->tm_usec += 1000000L; } LL_I2L(secPerDay, 86400L); LL_DIV(numDays64, sec, secPerDay); LL_MOD(rem64, sec, secPerDay); /* We are sure both of these numbers can fit into PRInt32 */ LL_L2I(numDays, numDays64); LL_L2I(rem, rem64); if (rem < 0) { numDays--; rem += 86400L; } /* Compute day of week. Epoch started on a Thursday. */ gmt->tm_wday = (numDays + 4) % 7; if (gmt->tm_wday < 0) { gmt->tm_wday += 7; } /* Compute the time of day. */ gmt->tm_hour = rem / 3600; rem %= 3600; gmt->tm_min = rem / 60; gmt->tm_sec = rem % 60; /* * Compute the year by finding the 400 year period, then working * down from there. * * Since numDays is originally the number of days since January 1, 1970, * we must change it to be the number of days from January 1, 0001. */ numDays += 719162; /* 719162 = days from year 1 up to 1970 */ tmp = numDays / 146097; /* 146097 = days in 400 years */ rem = numDays % 146097; gmt->tm_year = tmp * 400 + 1; /* Compute the 100 year period. */ tmp = rem / 36524; /* 36524 = days in 100 years */ rem %= 36524; if (tmp == 4) { /* the 400th year is a leap year */ tmp = 3; rem = 36524; } gmt->tm_year += tmp * 100; /* Compute the 4 year period. */ tmp = rem / 1461; /* 1461 = days in 4 years */ rem %= 1461; gmt->tm_year += tmp * 4; /* Compute which year in the 4. */ tmp = rem / 365; rem %= 365; if (tmp == 4) { /* the 4th year is a leap year */ tmp = 3; rem = 365; } gmt->tm_year += tmp; gmt->tm_yday = rem; isLeap = IsLeapYear(gmt->tm_year); /* Compute the month and day of month. */ for (tmp = 1; lastDayOfMonth[isLeap][tmp] < gmt->tm_yday; tmp++) { } gmt->tm_month = --tmp; gmt->tm_mday = gmt->tm_yday - lastDayOfMonth[isLeap][tmp]; gmt->tm_params.tp_gmt_offset = 0; gmt->tm_params.tp_dst_offset = 0; } /* *------------------------------------------------------------------------ * * PR_ExplodeTime -- * * Cf. struct tm *gmtime(const time_t *tp) and * struct tm *localtime(const time_t *tp) * *------------------------------------------------------------------------ */ PR_IMPLEMENT(void) PR_ExplodeTime( PRTime usecs, PRTimeParamFn params, PRExplodedTime *exploded) { ComputeGMT(usecs, exploded); exploded->tm_params = params(exploded); ApplySecOffset(exploded, exploded->tm_params.tp_gmt_offset + exploded->tm_params.tp_dst_offset); } /* *------------------------------------------------------------------------ * * PR_ImplodeTime -- * * Cf. time_t mktime(struct tm *tp) * Note that 1 year has < 2^25 seconds. So an PRInt32 is large enough. * *------------------------------------------------------------------------ */ PR_IMPLEMENT(PRTime) PR_ImplodeTime(const PRExplodedTime *exploded) { PRExplodedTime copy; PRTime retVal; PRInt64 secPerDay, usecPerSec; PRInt64 temp; PRInt64 numSecs64; PRInt32 numDays; PRInt32 numSecs; /* Normalize first. Do this on our copy */ copy = *exploded; PR_NormalizeTime(©, PR_GMTParameters); numDays = DAYS_BETWEEN_YEARS(1970, copy.tm_year); numSecs = copy.tm_yday * 86400 + copy.tm_hour * 3600 + copy.tm_min * 60 + copy.tm_sec; LL_I2L(temp, numDays); LL_I2L(secPerDay, 86400); LL_MUL(temp, temp, secPerDay); LL_I2L(numSecs64, numSecs); LL_ADD(numSecs64, numSecs64, temp); /* apply the GMT and DST offsets */ LL_I2L(temp, copy.tm_params.tp_gmt_offset); LL_SUB(numSecs64, numSecs64, temp); LL_I2L(temp, copy.tm_params.tp_dst_offset); LL_SUB(numSecs64, numSecs64, temp); LL_I2L(usecPerSec, 1000000L); LL_MUL(temp, numSecs64, usecPerSec); LL_I2L(retVal, copy.tm_usec); LL_ADD(retVal, retVal, temp); return retVal; } /* *------------------------------------------------------------------------- * * IsLeapYear -- * * Returns 1 if the year is a leap year, 0 otherwise. * *------------------------------------------------------------------------- */ static int IsLeapYear(PRInt16 year) { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) return 1; else return 0; } /* * 'secOffset' should be less than 86400 (i.e., a day). * 'time' should point to a normalized PRExplodedTime. */ static void ApplySecOffset(PRExplodedTime *time, PRInt32 secOffset) { time->tm_sec += secOffset; /* Note that in this implementation we do not count leap seconds */ if (time->tm_sec < 0 || time->tm_sec >= 60) { time->tm_min += time->tm_sec / 60; time->tm_sec %= 60; if (time->tm_sec < 0) { time->tm_sec += 60; time->tm_min--; } } if (time->tm_min < 0 || time->tm_min >= 60) { time->tm_hour += time->tm_min / 60; time->tm_min %= 60; if (time->tm_min < 0) { time->tm_min += 60; time->tm_hour--; } } if (time->tm_hour < 0) { /* Decrement mday, yday, and wday */ time->tm_hour += 24; time->tm_mday--; time->tm_yday--; if (time->tm_mday < 1) { time->tm_month--; if (time->tm_month < 0) { time->tm_month = 11; time->tm_year--; if (IsLeapYear(time->tm_year)) time->tm_yday = 365; else time->tm_yday = 364; } time->tm_mday = nDays[IsLeapYear(time->tm_year)][time->tm_month]; } time->tm_wday--; if (time->tm_wday < 0) time->tm_wday = 6; } else if (time->tm_hour > 23) { /* Increment mday, yday, and wday */ time->tm_hour -= 24; time->tm_mday++; time->tm_yday++; if (time->tm_mday > nDays[IsLeapYear(time->tm_year)][time->tm_month]) { time->tm_mday = 1; time->tm_month++; if (time->tm_month > 11) { time->tm_month = 0; time->tm_year++; time->tm_yday = 0; } } time->tm_wday++; if (time->tm_wday > 6) time->tm_wday = 0; } } PR_IMPLEMENT(void) PR_NormalizeTime(PRExplodedTime *time, PRTimeParamFn params) { int daysInMonth; PRInt32 numDays; /* Get back to GMT */ time->tm_sec -= time->tm_params.tp_gmt_offset + time->tm_params.tp_dst_offset; time->tm_params.tp_gmt_offset = 0; time->tm_params.tp_dst_offset = 0; /* Now normalize GMT */ if (time->tm_usec < 0 || time->tm_usec >= 1000000) { time->tm_sec += time->tm_usec / 1000000; time->tm_usec %= 1000000; if (time->tm_usec < 0) { time->tm_usec += 1000000; time->tm_sec--; } } /* Note that we do not count leap seconds in this implementation */ if (time->tm_sec < 0 || time->tm_sec >= 60) { time->tm_min += time->tm_sec / 60; time->tm_sec %= 60; if (time->tm_sec < 0) { time->tm_sec += 60; time->tm_min--; } } if (time->tm_min < 0 || time->tm_min >= 60) { time->tm_hour += time->tm_min / 60; time->tm_min %= 60; if (time->tm_min < 0) { time->tm_min += 60; time->tm_hour--; } } if (time->tm_hour < 0 || time->tm_hour >= 24) { time->tm_mday += time->tm_hour / 24; time->tm_hour %= 24; if (time->tm_hour < 0) { time->tm_hour += 24; time->tm_mday--; } } /* Normalize month and year before mday */ if (time->tm_month < 0 || time->tm_month >= 12) { time->tm_year += time->tm_month / 12; time->tm_month %= 12; if (time->tm_month < 0) { time->tm_month += 12; time->tm_year--; } } /* Now that month and year are in proper range, normalize mday */ if (time->tm_mday < 1) { /* mday too small */ do { /* the previous month */ time->tm_month--; if (time->tm_month < 0) { time->tm_month = 11; time->tm_year--; } time->tm_mday += nDays[IsLeapYear(time->tm_year)][time->tm_month]; } while (time->tm_mday < 1); } else { daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; while (time->tm_mday > daysInMonth) { /* mday too large */ time->tm_mday -= daysInMonth; time->tm_month++; if (time->tm_month > 11) { time->tm_month = 0; time->tm_year++; } daysInMonth = nDays[IsLeapYear(time->tm_year)][time->tm_month]; } } /* Recompute yday and wday */ time->tm_yday = time->tm_mday + lastDayOfMonth[IsLeapYear(time->tm_year)][time->tm_month]; numDays = DAYS_BETWEEN_YEARS(1970, time->tm_year) + time->tm_yday; time->tm_wday = (numDays + 4) % 7; if (time->tm_wday < 0) { time->tm_wday += 7; } /* Recompute time parameters */ time->tm_params = params(time); ApplySecOffset(time, time->tm_params.tp_gmt_offset + time->tm_params.tp_dst_offset); } /* *------------------------------------------------------------------------- * * PR_LocalTimeParameters -- * * returns the time parameters for the local time zone * * The following uses localtime() from the standard C library. * (time.h) This is our fallback implementation. Unix, PC, and BeOS * use this version. A platform may have its own machine-dependent * implementation of this function. * *------------------------------------------------------------------------- */ #if defined(HAVE_INT_LOCALTIME_R) /* * In this case we could define the macro as * #define MT_safe_localtime(timer, result) \ * (localtime_r(timer, result) == 0 ? result : NULL) * I chose to compare the return value of localtime_r with -1 so * that I can catch the cases where localtime_r returns a pointer * to struct tm. The macro definition above would not be able to * detect such mistakes because it is legal to compare a pointer * with 0. */ #define MT_safe_localtime(timer, result) \ (localtime_r(timer, result) == -1 ? NULL: result) #elif defined(HAVE_POINTER_LOCALTIME_R) #define MT_safe_localtime localtime_r #else #define HAVE_LOCALTIME_MONITOR 1 /* We use 'monitor' to serialize our calls * to localtime(). */ static PRLock *monitor = NULL; static struct tm *MT_safe_localtime(const time_t *clock, struct tm *result) { struct tm *tmPtr; int needLock = PR_Initialized(); /* We need to use a lock to protect * against NSPR threads only when the * NSPR thread system is activated. */ if (needLock) PR_Lock(monitor); /* * Microsoft (all flavors) localtime() returns a NULL pointer if 'clock' * represents a time before midnight January 1, 1970. In * that case, we also return a NULL pointer and the struct tm * object pointed to by 'result' is not modified. * * Watcom C/C++ 11.0 localtime() treats time_t as unsigned long * hence, does not recognize negative values of clock as pre-1/1/70. * We have to manually check (WIN16 only) for negative value of * clock and return NULL. * * With negative values of clock, OS/2 returns the struct tm for * clock plus ULONG_MAX. So we also have to check for the invalid * structs returned for timezones west of Greenwich when clock == 0. */ tmPtr = localtime(clock); #if defined(WIN16) || defined(XP_OS2) if ( (PRInt32) *clock < 0 || ( (PRInt32) *clock == 0 && tmPtr->tm_year != 70)) result = NULL; else *result = *tmPtr; #else if (tmPtr) { *result = *tmPtr; } else { result = NULL; } #endif /* WIN16 */ if (needLock) PR_Unlock(monitor); return result; } #endif /* definition of MT_safe_localtime() */ void _PR_InitTime(void) { #ifdef HAVE_LOCALTIME_MONITOR monitor = PR_NewLock(); #endif #ifdef WINCE _MD_InitTime(); #endif } void _PR_CleanupTime(void) { #ifdef HAVE_LOCALTIME_MONITOR if (monitor) { PR_DestroyLock(monitor); monitor = NULL; } #endif #ifdef WINCE _MD_CleanupTime(); #endif } #if defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) PR_IMPLEMENT(PRTimeParameters) PR_LocalTimeParameters(const PRExplodedTime *gmt) { PRTimeParameters retVal; struct tm localTime; time_t secs; PRTime secs64; PRInt64 usecPerSec; PRInt64 usecPerSec_1; PRInt64 maxInt32; PRInt64 minInt32; PRInt32 dayOffset; PRInt32 offset2Jan1970; PRInt32 offsetNew; int isdst2Jan1970; /* * Calculate the GMT offset. First, figure out what is * 00:00:00 Jan. 2, 1970 GMT (which is exactly a day, or 86400 * seconds, since the epoch) in local time. Then we calculate * the difference between local time and GMT in seconds: * gmt_offset = local_time - GMT * * Caveat: the validity of this calculation depends on two * assumptions: * 1. Daylight saving time was not in effect on Jan. 2, 1970. * 2. The time zone of the geographic location has not changed * since Jan. 2, 1970. */ secs = 86400L; (void) MT_safe_localtime(&secs, &localTime); /* GMT is 00:00:00, 2nd of Jan. */ offset2Jan1970 = (PRInt32)localTime.tm_sec + 60L * (PRInt32)localTime.tm_min + 3600L * (PRInt32)localTime.tm_hour + 86400L * (PRInt32)((PRInt32)localTime.tm_mday - 2L); isdst2Jan1970 = localTime.tm_isdst; /* * Now compute DST offset. We calculate the overall offset * of local time from GMT, similar to above. The overall * offset has two components: gmt offset and dst offset. * We subtract gmt offset from the overall offset to get * the dst offset. * overall_offset = local_time - GMT * overall_offset = gmt_offset + dst_offset * ==> dst_offset = local_time - GMT - gmt_offset */ secs64 = PR_ImplodeTime(gmt); /* This is still in microseconds */ LL_I2L(usecPerSec, PR_USEC_PER_SEC); LL_I2L(usecPerSec_1, PR_USEC_PER_SEC - 1); /* Convert to seconds, truncating down (3.1 -> 3 and -3.1 -> -4) */ if (LL_GE_ZERO(secs64)) { LL_DIV(secs64, secs64, usecPerSec); } else { LL_NEG(secs64, secs64); LL_ADD(secs64, secs64, usecPerSec_1); LL_DIV(secs64, secs64, usecPerSec); LL_NEG(secs64, secs64); } LL_I2L(maxInt32, PR_INT32_MAX); LL_I2L(minInt32, PR_INT32_MIN); if (LL_CMP(secs64, >, maxInt32) || LL_CMP(secs64, <, minInt32)) { /* secs64 is too large or too small for time_t (32-bit integer) */ retVal.tp_gmt_offset = offset2Jan1970; retVal.tp_dst_offset = 0; return retVal; } LL_L2I(secs, secs64); /* * On Windows, localtime() (and our MT_safe_localtime() too) * returns a NULL pointer for time before midnight January 1, * 1970 GMT. In that case, we just use the GMT offset for * Jan 2, 1970 and assume that DST was not in effect. */ if (MT_safe_localtime(&secs, &localTime) == NULL) { retVal.tp_gmt_offset = offset2Jan1970; retVal.tp_dst_offset = 0; return retVal; } /* * dayOffset is the offset between local time and GMT in * the day component, which can only be -1, 0, or 1. We * use the day of the week to compute dayOffset. */ dayOffset = (PRInt32) localTime.tm_wday - gmt->tm_wday; /* * Need to adjust for wrapping around of day of the week from * 6 back to 0. */ if (dayOffset == -6) { /* Local time is Sunday (0) and GMT is Saturday (6) */ dayOffset = 1; } else if (dayOffset == 6) { /* Local time is Saturday (6) and GMT is Sunday (0) */ dayOffset = -1; } offsetNew = (PRInt32)localTime.tm_sec - gmt->tm_sec + 60L * ((PRInt32)localTime.tm_min - gmt->tm_min) + 3600L * ((PRInt32)localTime.tm_hour - gmt->tm_hour) + 86400L * (PRInt32)dayOffset; if (localTime.tm_isdst <= 0) { /* DST is not in effect */ retVal.tp_gmt_offset = offsetNew; retVal.tp_dst_offset = 0; } else { /* DST is in effect */ if (isdst2Jan1970 <=0) { /* * DST was not in effect back in 2 Jan. 1970. * Use the offset back then as the GMT offset, * assuming the time zone has not changed since then. */ retVal.tp_gmt_offset = offset2Jan1970; retVal.tp_dst_offset = offsetNew - offset2Jan1970; } else { /* * DST was also in effect back in 2 Jan. 1970. * Then our clever trick (or rather, ugly hack) fails. * We will just assume DST offset is an hour. */ retVal.tp_gmt_offset = offsetNew - 3600; retVal.tp_dst_offset = 3600; } } return retVal; } #endif /* defined(XP_UNIX) || defined(XP_PC) || defined(XP_BEOS) */ /* *------------------------------------------------------------------------ * * PR_USPacificTimeParameters -- * * The time parameters function for the US Pacific Time Zone. * *------------------------------------------------------------------------ */ /* * Returns the mday of the first sunday of the month, where * mday and wday are for a given day in the month. * mdays start with 1 (e.g. 1..31). * wdays start with 0 and are in the range 0..6. 0 = Sunday. */ #define firstSunday(mday, wday) (((mday - wday + 7 - 1) % 7) + 1) /* * Returns the mday for the N'th Sunday of the month, where * mday and wday are for a given day in the month. * mdays start with 1 (e.g. 1..31). * wdays start with 0 and are in the range 0..6. 0 = Sunday. * N has the following values: 0 = first, 1 = second (etc), -1 = last. * ndays is the number of days in that month, the same value as the * mday of the last day of the month. */ static PRInt32 NthSunday(PRInt32 mday, PRInt32 wday, PRInt32 N, PRInt32 ndays) { PRInt32 firstSun = firstSunday(mday, wday); if (N < 0) N = (ndays - firstSun) / 7; return firstSun + (7 * N); } typedef struct DSTParams { PRInt8 dst_start_month; /* 0 = January */ PRInt8 dst_start_Nth_Sunday; /* N as defined above */ PRInt8 dst_start_month_ndays; /* ndays as defined above */ PRInt8 dst_end_month; /* 0 = January */ PRInt8 dst_end_Nth_Sunday; /* N as defined above */ PRInt8 dst_end_month_ndays; /* ndays as defined above */ } DSTParams; static const DSTParams dstParams[2] = { /* year < 2007: First April Sunday - Last October Sunday */ { 3, 0, 30, 9, -1, 31 }, /* year >= 2007: Second March Sunday - First November Sunday */ { 2, 1, 31, 10, 0, 30 } }; PR_IMPLEMENT(PRTimeParameters) PR_USPacificTimeParameters(const PRExplodedTime *gmt) { const DSTParams *dst; PRTimeParameters retVal; PRExplodedTime st; /* * Based on geographic location and GMT, figure out offset of * standard time from GMT. In this example implementation, we * assume the local time zone is US Pacific Time. */ retVal.tp_gmt_offset = -8L * 3600L; /* * Make a copy of GMT. Note that the tm_params field of this copy * is ignored. */ st.tm_usec = gmt->tm_usec; st.tm_sec = gmt->tm_sec; st.tm_min = gmt->tm_min; st.tm_hour = gmt->tm_hour; st.tm_mday = gmt->tm_mday; st.tm_month = gmt->tm_month; st.tm_year = gmt->tm_year; st.tm_wday = gmt->tm_wday; st.tm_yday = gmt->tm_yday; /* Apply the offset to GMT to obtain the local standard time */ ApplySecOffset(&st, retVal.tp_gmt_offset); if (st.tm_year < 2007) { /* first April Sunday - Last October Sunday */ dst = &dstParams[0]; } else { /* Second March Sunday - First November Sunday */ dst = &dstParams[1]; } /* * Apply the rules on standard time or GMT to obtain daylight saving * time offset. In this implementation, we use the US DST rule. */ if (st.tm_month < dst->dst_start_month) { retVal.tp_dst_offset = 0L; } else if (st.tm_month == dst->dst_start_month) { int NthSun = NthSunday(st.tm_mday, st.tm_wday, dst->dst_start_Nth_Sunday, dst->dst_start_month_ndays); if (st.tm_mday < NthSun) { /* Before starting Sunday */ retVal.tp_dst_offset = 0L; } else if (st.tm_mday == NthSun) { /* Starting Sunday */ /* 01:59:59 PST -> 03:00:00 PDT */ if (st.tm_hour < 2) { retVal.tp_dst_offset = 0L; } else { retVal.tp_dst_offset = 3600L; } } else { /* After starting Sunday */ retVal.tp_dst_offset = 3600L; } } else if (st.tm_month < dst->dst_end_month) { retVal.tp_dst_offset = 3600L; } else if (st.tm_month == dst->dst_end_month) { int NthSun = NthSunday(st.tm_mday, st.tm_wday, dst->dst_end_Nth_Sunday, dst->dst_end_month_ndays); if (st.tm_mday < NthSun) { /* Before ending Sunday */ retVal.tp_dst_offset = 3600L; } else if (st.tm_mday == NthSun) { /* Ending Sunday */ /* 01:59:59 PDT -> 01:00:00 PST */ if (st.tm_hour < 1) { retVal.tp_dst_offset = 3600L; } else { retVal.tp_dst_offset = 0L; } } else { /* After ending Sunday */ retVal.tp_dst_offset = 0L; } } else { retVal.tp_dst_offset = 0L; } return retVal; } /* *------------------------------------------------------------------------ * * PR_GMTParameters -- * * Returns the PRTimeParameters for Greenwich Mean Time. * Trivially, both the tp_gmt_offset and tp_dst_offset fields are 0. * *------------------------------------------------------------------------ */ PR_IMPLEMENT(PRTimeParameters) PR_GMTParameters(const PRExplodedTime *gmt) { PRTimeParameters retVal = { 0, 0 }; return retVal; } /* * The following code implements PR_ParseTimeString(). It is based on * ns/lib/xp/xp_time.c, revision 1.25, by Jamie Zawinski . */ /* * We only recognize the abbreviations of a small subset of time zones * in North America, Europe, and Japan. * * PST/PDT: Pacific Standard/Daylight Time * MST/MDT: Mountain Standard/Daylight Time * CST/CDT: Central Standard/Daylight Time * EST/EDT: Eastern Standard/Daylight Time * AST: Atlantic Standard Time * NST: Newfoundland Standard Time * GMT: Greenwich Mean Time * BST: British Summer Time * MET: Middle Europe Time * EET: Eastern Europe Time * JST: Japan Standard Time */ typedef enum { TT_UNKNOWN, TT_SUN, TT_MON, TT_TUE, TT_WED, TT_THU, TT_FRI, TT_SAT, TT_JAN, TT_FEB, TT_MAR, TT_APR, TT_MAY, TT_JUN, TT_JUL, TT_AUG, TT_SEP, TT_OCT, TT_NOV, TT_DEC, TT_PST, TT_PDT, TT_MST, TT_MDT, TT_CST, TT_CDT, TT_EST, TT_EDT, TT_AST, TT_NST, TT_GMT, TT_BST, TT_MET, TT_EET, TT_JST } TIME_TOKEN; /* * This parses a time/date string into a PRTime * (microseconds after "1-Jan-1970 00:00:00 GMT"). * It returns PR_SUCCESS on success, and PR_FAILURE * if the time/date string can't be parsed. * * Many formats are handled, including: * * 14 Apr 89 03:20:12 * 14 Apr 89 03:20 GMT * Fri, 17 Mar 89 4:01:33 * Fri, 17 Mar 89 4:01 GMT * Mon Jan 16 16:12 PDT 1989 * Mon Jan 16 16:12 +0130 1989 * 6 May 1992 16:41-JST (Wednesday) * 22-AUG-1993 10:59:12.82 * 22-AUG-1993 10:59pm * 22-AUG-1993 12:59am * 22-AUG-1993 12:59 PM * Friday, August 04, 1995 3:54 PM * 06/21/95 04:24:34 PM * 20/06/95 21:07 * 95-06-08 19:32:48 EDT * * If the input string doesn't contain a description of the timezone, * we consult the `default_to_gmt' to decide whether the string should * be interpreted relative to the local time zone (PR_FALSE) or GMT (PR_TRUE). * The correct value for this argument depends on what standard specified * the time string which you are parsing. */ PR_IMPLEMENT(PRStatus) PR_ParseTimeStringToExplodedTime( const char *string, PRBool default_to_gmt, PRExplodedTime *result) { TIME_TOKEN dotw = TT_UNKNOWN; TIME_TOKEN month = TT_UNKNOWN; TIME_TOKEN zone = TT_UNKNOWN; int zone_offset = -1; int dst_offset = 0; int date = -1; PRInt32 year = -1; int hour = -1; int min = -1; int sec = -1; const char *rest = string; int iterations = 0; PR_ASSERT(string && result); if (!string || !result) return PR_FAILURE; while (*rest) { if (iterations++ > 1000) { return PR_FAILURE; } switch (*rest) { case 'a': case 'A': if (month == TT_UNKNOWN && (rest[1] == 'p' || rest[1] == 'P') && (rest[2] == 'r' || rest[2] == 'R')) month = TT_APR; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_AST; else if (month == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'g' || rest[2] == 'G')) month = TT_AUG; break; case 'b': case 'B': if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_BST; break; case 'c': case 'C': if (zone == TT_UNKNOWN && (rest[1] == 'd' || rest[1] == 'D') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_CDT; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_CST; break; case 'd': case 'D': if (month == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 'c' || rest[2] == 'C')) month = TT_DEC; break; case 'e': case 'E': if (zone == TT_UNKNOWN && (rest[1] == 'd' || rest[1] == 'D') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_EDT; else if (zone == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_EET; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_EST; break; case 'f': case 'F': if (month == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 'b' || rest[2] == 'B')) month = TT_FEB; else if (dotw == TT_UNKNOWN && (rest[1] == 'r' || rest[1] == 'R') && (rest[2] == 'i' || rest[2] == 'I')) dotw = TT_FRI; break; case 'g': case 'G': if (zone == TT_UNKNOWN && (rest[1] == 'm' || rest[1] == 'M') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_GMT; break; case 'j': case 'J': if (month == TT_UNKNOWN && (rest[1] == 'a' || rest[1] == 'A') && (rest[2] == 'n' || rest[2] == 'N')) month = TT_JAN; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_JST; else if (month == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'l' || rest[2] == 'L')) month = TT_JUL; else if (month == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'n' || rest[2] == 'N')) month = TT_JUN; break; case 'm': case 'M': if (month == TT_UNKNOWN && (rest[1] == 'a' || rest[1] == 'A') && (rest[2] == 'r' || rest[2] == 'R')) month = TT_MAR; else if (month == TT_UNKNOWN && (rest[1] == 'a' || rest[1] == 'A') && (rest[2] == 'y' || rest[2] == 'Y')) month = TT_MAY; else if (zone == TT_UNKNOWN && (rest[1] == 'd' || rest[1] == 'D') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_MDT; else if (zone == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_MET; else if (dotw == TT_UNKNOWN && (rest[1] == 'o' || rest[1] == 'O') && (rest[2] == 'n' || rest[2] == 'N')) dotw = TT_MON; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_MST; break; case 'n': case 'N': if (month == TT_UNKNOWN && (rest[1] == 'o' || rest[1] == 'O') && (rest[2] == 'v' || rest[2] == 'V')) month = TT_NOV; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_NST; break; case 'o': case 'O': if (month == TT_UNKNOWN && (rest[1] == 'c' || rest[1] == 'C') && (rest[2] == 't' || rest[2] == 'T')) month = TT_OCT; break; case 'p': case 'P': if (zone == TT_UNKNOWN && (rest[1] == 'd' || rest[1] == 'D') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_PDT; else if (zone == TT_UNKNOWN && (rest[1] == 's' || rest[1] == 'S') && (rest[2] == 't' || rest[2] == 'T')) zone = TT_PST; break; case 's': case 'S': if (dotw == TT_UNKNOWN && (rest[1] == 'a' || rest[1] == 'A') && (rest[2] == 't' || rest[2] == 'T')) dotw = TT_SAT; else if (month == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 'p' || rest[2] == 'P')) month = TT_SEP; else if (dotw == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'n' || rest[2] == 'N')) dotw = TT_SUN; break; case 't': case 'T': if (dotw == TT_UNKNOWN && (rest[1] == 'h' || rest[1] == 'H') && (rest[2] == 'u' || rest[2] == 'U')) dotw = TT_THU; else if (dotw == TT_UNKNOWN && (rest[1] == 'u' || rest[1] == 'U') && (rest[2] == 'e' || rest[2] == 'E')) dotw = TT_TUE; break; case 'u': case 'U': if (zone == TT_UNKNOWN && (rest[1] == 't' || rest[1] == 'T') && !(rest[2] >= 'A' && rest[2] <= 'Z') && !(rest[2] >= 'a' && rest[2] <= 'z')) /* UT is the same as GMT but UTx is not. */ zone = TT_GMT; break; case 'w': case 'W': if (dotw == TT_UNKNOWN && (rest[1] == 'e' || rest[1] == 'E') && (rest[2] == 'd' || rest[2] == 'D')) dotw = TT_WED; break; case '+': case '-': { const char *end; int sign; if (zone_offset != -1) { /* already got one... */ rest++; break; } if (zone != TT_UNKNOWN && zone != TT_GMT) { /* GMT+0300 is legal, but PST+0300 is not. */ rest++; break; } sign = ((*rest == '+') ? 1 : -1); rest++; /* move over sign */ end = rest; while (*end >= '0' && *end <= '9') end++; if (rest == end) /* no digits here */ break; if ((end - rest) == 4) /* offset in HHMM */ zone_offset = (((((rest[0]-'0')*10) + (rest[1]-'0')) * 60) + (((rest[2]-'0')*10) + (rest[3]-'0'))); else if ((end - rest) == 2) /* offset in hours */ zone_offset = (((rest[0]-'0')*10) + (rest[1]-'0')) * 60; else if ((end - rest) == 1) /* offset in hours */ zone_offset = (rest[0]-'0') * 60; else /* 3 or >4 */ break; zone_offset *= sign; zone = TT_GMT; break; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int tmp_hour = -1; int tmp_min = -1; int tmp_sec = -1; const char *end = rest + 1; while (*end >= '0' && *end <= '9') end++; /* end is now the first character after a range of digits. */ if (*end == ':') { if (hour >= 0 && min >= 0) /* already got it */ break; /* We have seen "[0-9]+:", so this is probably HH:MM[:SS] */ if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; else if ((end - rest) == 2) tmp_hour = ((rest[0]-'0')*10 + (rest[1]-'0')); else tmp_hour = (rest[0]-'0'); /* move over the colon, and parse minutes */ rest = ++end; while (*end >= '0' && *end <= '9') end++; if (end == rest) /* no digits after first colon? */ break; else if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; else if ((end - rest) == 2) tmp_min = ((rest[0]-'0')*10 + (rest[1]-'0')); else tmp_min = (rest[0]-'0'); /* now go for seconds */ rest = end; if (*rest == ':') rest++; end = rest; while (*end >= '0' && *end <= '9') end++; if (end == rest) /* no digits after second colon - that's ok. */ ; else if ((end - rest) > 2) /* it is [0-9][0-9][0-9]+: */ break; else if ((end - rest) == 2) tmp_sec = ((rest[0]-'0')*10 + (rest[1]-'0')); else tmp_sec = (rest[0]-'0'); /* If we made it here, we've parsed hour and min, and possibly sec, so it worked as a unit. */ /* skip over whitespace and see if there's an AM or PM directly following the time. */ if (tmp_hour <= 12) { const char *s = end; while (*s && (*s == ' ' || *s == '\t')) s++; if ((s[0] == 'p' || s[0] == 'P') && (s[1] == 'm' || s[1] == 'M')) /* 10:05pm == 22:05, and 12:05pm == 12:05 */ tmp_hour = (tmp_hour == 12 ? 12 : tmp_hour + 12); else if (tmp_hour == 12 && (s[0] == 'a' || s[0] == 'A') && (s[1] == 'm' || s[1] == 'M')) /* 12:05am == 00:05 */ tmp_hour = 0; } hour = tmp_hour; min = tmp_min; sec = tmp_sec; rest = end; break; } else if ((*end == '/' || *end == '-') && end[1] >= '0' && end[1] <= '9') { /* Perhaps this is 6/16/95, 16/6/95, 6-16-95, or 16-6-95 or even 95-06-05... #### But it doesn't handle 1995-06-22. */ int n1, n2, n3; const char *s; if (month != TT_UNKNOWN) /* if we saw a month name, this can't be. */ break; s = rest; n1 = (*s++ - '0'); /* first 1 or 2 digits */ if (*s >= '0' && *s <= '9') n1 = n1*10 + (*s++ - '0'); if (*s != '/' && *s != '-') /* slash */ break; s++; if (*s < '0' || *s > '9') /* second 1 or 2 digits */ break; n2 = (*s++ - '0'); if (*s >= '0' && *s <= '9') n2 = n2*10 + (*s++ - '0'); if (*s != '/' && *s != '-') /* slash */ break; s++; if (*s < '0' || *s > '9') /* third 1, 2, 4, or 5 digits */ break; n3 = (*s++ - '0'); if (*s >= '0' && *s <= '9') n3 = n3*10 + (*s++ - '0'); if (*s >= '0' && *s <= '9') /* optional digits 3, 4, and 5 */ { n3 = n3*10 + (*s++ - '0'); if (*s < '0' || *s > '9') break; n3 = n3*10 + (*s++ - '0'); if (*s >= '0' && *s <= '9') n3 = n3*10 + (*s++ - '0'); } if ((*s >= '0' && *s <= '9') || /* followed by non-alphanum */ (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) break; /* Ok, we parsed three 1-2 digit numbers, with / or - between them. Now decide what the hell they are (DD/MM/YY or MM/DD/YY or YY/MM/DD.) */ if (n1 > 31 || n1 == 0) /* must be YY/MM/DD */ { if (n2 > 12) break; if (n3 > 31) break; year = n1; if (year < 70) year += 2000; else if (year < 100) year += 1900; month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); date = n3; rest = s; break; } if (n1 > 12 && n2 > 12) /* illegal */ { rest = s; break; } if (n3 < 70) n3 += 2000; else if (n3 < 100) n3 += 1900; if (n1 > 12) /* must be DD/MM/YY */ { date = n1; month = (TIME_TOKEN)(n2 + ((int)TT_JAN) - 1); year = n3; } else /* assume MM/DD/YY */ { /* #### In the ambiguous case, should we consult the locale to find out the local default? */ month = (TIME_TOKEN)(n1 + ((int)TT_JAN) - 1); date = n2; year = n3; } rest = s; } else if ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z')) /* Digits followed by non-punctuation - what's that? */ ; else if ((end - rest) == 5) /* five digits is a year */ year = (year < 0 ? ((rest[0]-'0')*10000L + (rest[1]-'0')*1000L + (rest[2]-'0')*100L + (rest[3]-'0')*10L + (rest[4]-'0')) : year); else if ((end - rest) == 4) /* four digits is a year */ year = (year < 0 ? ((rest[0]-'0')*1000L + (rest[1]-'0')*100L + (rest[2]-'0')*10L + (rest[3]-'0')) : year); else if ((end - rest) == 2) /* two digits - date or year */ { int n = ((rest[0]-'0')*10 + (rest[1]-'0')); /* If we don't have a date (day of the month) and we see a number less than 32, then assume that is the date. Otherwise, if we have a date and not a year, assume this is the year. If it is less than 70, then assume it refers to the 21st century. If it is two digits (>= 70), assume it refers to this century. Otherwise, assume it refers to an unambiguous year. The world will surely end soon. */ if (date < 0 && n < 32) date = n; else if (year < 0) { if (n < 70) year = 2000 + n; else if (n < 100) year = 1900 + n; else year = n; } /* else what the hell is this. */ } else if ((end - rest) == 1) /* one digit - date */ date = (date < 0 ? (rest[0]-'0') : date); /* else, three or more than five digits - what's that? */ break; } } /* Skip to the end of this token, whether we parsed it or not. Tokens are delimited by whitespace, or ,;-/ But explicitly not :+-. */ while (*rest && *rest != ' ' && *rest != '\t' && *rest != ',' && *rest != ';' && *rest != '-' && *rest != '+' && *rest != '/' && *rest != '(' && *rest != ')' && *rest != '[' && *rest != ']') rest++; /* skip over uninteresting chars. */ SKIP_MORE: while (*rest && (*rest == ' ' || *rest == '\t' || *rest == ',' || *rest == ';' || *rest == '/' || *rest == '(' || *rest == ')' || *rest == '[' || *rest == ']')) rest++; /* "-" is ignored at the beginning of a token if we have not yet parsed a year (e.g., the second "-" in "30-AUG-1966"), or if the character after the dash is not a digit. */ if (*rest == '-' && ((rest > string && isalpha((unsigned char)rest[-1]) && year < 0) || rest[1] < '0' || rest[1] > '9')) { rest++; goto SKIP_MORE; } } if (zone != TT_UNKNOWN && zone_offset == -1) { switch (zone) { case TT_PST: zone_offset = -8 * 60; break; case TT_PDT: zone_offset = -8 * 60; dst_offset = 1 * 60; break; case TT_MST: zone_offset = -7 * 60; break; case TT_MDT: zone_offset = -7 * 60; dst_offset = 1 * 60; break; case TT_CST: zone_offset = -6 * 60; break; case TT_CDT: zone_offset = -6 * 60; dst_offset = 1 * 60; break; case TT_EST: zone_offset = -5 * 60; break; case TT_EDT: zone_offset = -5 * 60; dst_offset = 1 * 60; break; case TT_AST: zone_offset = -4 * 60; break; case TT_NST: zone_offset = -3 * 60 - 30; break; case TT_GMT: zone_offset = 0 * 60; break; case TT_BST: zone_offset = 0 * 60; dst_offset = 1 * 60; break; case TT_MET: zone_offset = 1 * 60; break; case TT_EET: zone_offset = 2 * 60; break; case TT_JST: zone_offset = 9 * 60; break; default: PR_ASSERT (0); break; } } /* If we didn't find a year, month, or day-of-the-month, we can't possibly parse this, and in fact, mktime() will do something random (I'm seeing it return "Tue Feb 5 06:28:16 2036", which is no doubt a numerologically significant date... */ if (month == TT_UNKNOWN || date == -1 || year == -1 || year > PR_INT16_MAX) return PR_FAILURE; memset(result, 0, sizeof(*result)); if (sec != -1) result->tm_sec = sec; if (min != -1) result->tm_min = min; if (hour != -1) result->tm_hour = hour; if (date != -1) result->tm_mday = date; if (month != TT_UNKNOWN) result->tm_month = (((int)month) - ((int)TT_JAN)); if (year != -1) result->tm_year = year; if (dotw != TT_UNKNOWN) result->tm_wday = (((int)dotw) - ((int)TT_SUN)); /* * Mainly to compute wday and yday, but normalized time is also required * by the check below that works around a Visual C++ 2005 mktime problem. */ PR_NormalizeTime(result, PR_GMTParameters); /* The remaining work is to set the gmt and dst offsets in tm_params. */ if (zone == TT_UNKNOWN && default_to_gmt) { /* No zone was specified, so pretend the zone was GMT. */ zone = TT_GMT; zone_offset = 0; } if (zone_offset == -1) { /* no zone was specified, and we're to assume that everything is local. */ struct tm localTime; time_t secs; PR_ASSERT(result->tm_month > -1 && result->tm_mday > 0 && result->tm_hour > -1 && result->tm_min > -1 && result->tm_sec > -1); /* * To obtain time_t from a tm structure representing the local * time, we call mktime(). However, we need to see if we are * on 1-Jan-1970 or before. If we are, we can't call mktime() * because mktime() will crash on win16. In that case, we * calculate zone_offset based on the zone offset at * 00:00:00, 2 Jan 1970 GMT, and subtract zone_offset from the * date we are parsing to transform the date to GMT. We also * do so if mktime() returns (time_t) -1 (time out of range). */ /* month, day, hours, mins and secs are always non-negative so we dont need to worry about them. */ if(result->tm_year >= 1970) { PRInt64 usec_per_sec; localTime.tm_sec = result->tm_sec; localTime.tm_min = result->tm_min; localTime.tm_hour = result->tm_hour; localTime.tm_mday = result->tm_mday; localTime.tm_mon = result->tm_month; localTime.tm_year = result->tm_year - 1900; /* Set this to -1 to tell mktime "I don't care". If you set it to 0 or 1, you are making assertions about whether the date you are handing it is in daylight savings mode or not; and if you're wrong, it will "fix" it for you. */ localTime.tm_isdst = -1; #if _MSC_VER == 1400 /* 1400 = Visual C++ 2005 (8.0) */ /* * mktime will return (time_t) -1 if the input is a date * after 23:59:59, December 31, 3000, US Pacific Time (not * UTC as documented): * http://msdn.microsoft.com/en-us/library/d1y53h2a(VS.80).aspx * But if the year is 3001, mktime also invokes the invalid * parameter handler, causing the application to crash. This * problem has been reported in * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=266036. * We avoid this crash by not calling mktime if the date is * out of range. To use a simple test that works in any time * zone, we consider year 3000 out of range as well. (See * bug 480740.) */ if (result->tm_year >= 3000) { /* Emulate what mktime would have done. */ errno = EINVAL; secs = (time_t) -1; } else { secs = mktime(&localTime); } #else secs = mktime(&localTime); #endif if (secs != (time_t) -1) { PRTime usecs64; LL_I2L(usecs64, secs); LL_I2L(usec_per_sec, PR_USEC_PER_SEC); LL_MUL(usecs64, usecs64, usec_per_sec); PR_ExplodeTime(usecs64, PR_LocalTimeParameters, result); return PR_SUCCESS; } } /* So mktime() can't handle this case. We assume the zone_offset for the date we are parsing is the same as the zone offset on 00:00:00 2 Jan 1970 GMT. */ secs = 86400; (void) MT_safe_localtime(&secs, &localTime); zone_offset = localTime.tm_min + 60 * localTime.tm_hour + 1440 * (localTime.tm_mday - 2); } result->tm_params.tp_gmt_offset = zone_offset * 60; result->tm_params.tp_dst_offset = dst_offset * 60; return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_ParseTimeString( const char *string, PRBool default_to_gmt, PRTime *result) { PRExplodedTime tm; PRStatus rv; rv = PR_ParseTimeStringToExplodedTime(string, default_to_gmt, &tm); if (rv != PR_SUCCESS) return rv; *result = PR_ImplodeTime(&tm); return PR_SUCCESS; } /* ******************************************************************* ******************************************************************* ** ** OLD COMPATIBILITY FUNCTIONS ** ******************************************************************* ******************************************************************* */ /* *----------------------------------------------------------------------- * * PR_FormatTime -- * * Format a time value into a buffer. Same semantics as strftime(). * *----------------------------------------------------------------------- */ PR_IMPLEMENT(PRUint32) PR_FormatTime(char *buf, int buflen, const char *fmt, const PRExplodedTime *time) { size_t rv; struct tm a; struct tm *ap; if (time) { ap = &a; a.tm_sec = time->tm_sec; a.tm_min = time->tm_min; a.tm_hour = time->tm_hour; a.tm_mday = time->tm_mday; a.tm_mon = time->tm_month; a.tm_wday = time->tm_wday; a.tm_year = time->tm_year - 1900; a.tm_yday = time->tm_yday; a.tm_isdst = time->tm_params.tp_dst_offset ? 1 : 0; /* * On some platforms, for example SunOS 4, struct tm has two * additional fields: tm_zone and tm_gmtoff. */ #if (__GLIBC__ >= 2) || defined(XP_BEOS) \ || defined(NETBSD) || defined(OPENBSD) || defined(FREEBSD) \ || defined(DARWIN) || defined(SYMBIAN) || defined(ANDROID) a.tm_zone = NULL; a.tm_gmtoff = time->tm_params.tp_gmt_offset + time->tm_params.tp_dst_offset; #endif } else { ap = NULL; } rv = strftime(buf, buflen, fmt, ap); if (!rv && buf && buflen > 0) { /* * When strftime fails, the contents of buf are indeterminate. * Some callers don't check the return value from this function, * so store an empty string in buf in case they try to print it. */ buf[0] = '\0'; } return rv; } /* * The following string arrays and macros are used by PR_FormatTimeUSEnglish(). */ static const char* abbrevDays[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; static const char* days[] = { "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" }; static const char* abbrevMonths[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static const char* months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; /* * Add a single character to the given buffer, incrementing the buffer pointer * and decrementing the buffer size. Return 0 on error. */ #define ADDCHAR( buf, bufSize, ch ) \ do \ { \ if( bufSize < 1 ) \ { \ *(--buf) = '\0'; \ return 0; \ } \ *buf++ = ch; \ bufSize--; \ } \ while(0) /* * Add a string to the given buffer, incrementing the buffer pointer * and decrementing the buffer size appropriately. Return 0 on error. */ #define ADDSTR( buf, bufSize, str ) \ do \ { \ PRUint32 strSize = strlen( str ); \ if( strSize > bufSize ) \ { \ if( bufSize==0 ) \ *(--buf) = '\0'; \ else \ *buf = '\0'; \ return 0; \ } \ memcpy(buf, str, strSize); \ buf += strSize; \ bufSize -= strSize; \ } \ while(0) /* Needed by PR_FormatTimeUSEnglish() */ static unsigned int pr_WeekOfYear(const PRExplodedTime* time, unsigned int firstDayOfWeek); /*********************************************************************************** * * Description: * This is a dumbed down version of strftime that will format the date in US * English regardless of the setting of the global locale. This functionality is * needed to write things like MIME headers which must always be in US English. * **********************************************************************************/ PR_IMPLEMENT(PRUint32) PR_FormatTimeUSEnglish( char* buf, PRUint32 bufSize, const char* format, const PRExplodedTime* time ) { char* bufPtr = buf; const char* fmtPtr; char tmpBuf[ 40 ]; const int tmpBufSize = sizeof( tmpBuf ); for( fmtPtr=format; *fmtPtr != '\0'; fmtPtr++ ) { if( *fmtPtr != '%' ) { ADDCHAR( bufPtr, bufSize, *fmtPtr ); } else { switch( *(++fmtPtr) ) { case '%': /* escaped '%' character */ ADDCHAR( bufPtr, bufSize, '%' ); break; case 'a': /* abbreviated weekday name */ ADDSTR( bufPtr, bufSize, abbrevDays[ time->tm_wday ] ); break; case 'A': /* full weekday name */ ADDSTR( bufPtr, bufSize, days[ time->tm_wday ] ); break; case 'b': /* abbreviated month name */ ADDSTR( bufPtr, bufSize, abbrevMonths[ time->tm_month ] ); break; case 'B': /* full month name */ ADDSTR(bufPtr, bufSize, months[ time->tm_month ] ); break; case 'c': /* Date and time. */ PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%a %b %d %H:%M:%S %Y", time ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'd': /* day of month ( 01 - 31 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_mday ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'H': /* hour ( 00 - 23 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_hour ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'I': /* hour ( 01 - 12 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld", (time->tm_hour%12) ? time->tm_hour%12 : (PRInt32) 12 ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'j': /* day number of year ( 001 - 366 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.3d",time->tm_yday + 1); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'm': /* month number ( 01 - 12 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_month+1); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'M': /* minute ( 00 - 59 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_min ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'p': /* locale's equivalent of either AM or PM */ ADDSTR( bufPtr, bufSize, (time->tm_hour<12)?"AM":"PM" ); break; case 'S': /* seconds ( 00 - 61 ), allows for leap seconds */ PR_snprintf(tmpBuf,tmpBufSize,"%.2ld",time->tm_sec ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'U': /* week number of year ( 00 - 53 ), Sunday is the first day of week 1 */ PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 0 ) ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'w': /* weekday number ( 0 - 6 ), Sunday = 0 */ PR_snprintf(tmpBuf,tmpBufSize,"%d",time->tm_wday ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'W': /* Week number of year ( 00 - 53 ), Monday is the first day of week 1 */ PR_snprintf(tmpBuf,tmpBufSize,"%.2d", pr_WeekOfYear( time, 1 ) ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'x': /* Date representation */ PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%m/%d/%y", time ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'X': /* Time representation. */ PR_FormatTimeUSEnglish( tmpBuf, tmpBufSize, "%H:%M:%S", time ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'y': /* year within century ( 00 - 99 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.2d",time->tm_year % 100 ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'Y': /* year as ccyy ( for example 1986 ) */ PR_snprintf(tmpBuf,tmpBufSize,"%.4d",time->tm_year ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; case 'Z': /* Time zone name or no characters if no time zone exists. * Since time zone name is supposed to be independant of locale, we * defer to PR_FormatTime() for this option. */ PR_FormatTime( tmpBuf, tmpBufSize, "%Z", time ); ADDSTR( bufPtr, bufSize, tmpBuf ); break; default: /* Unknown format. Simply copy format into output buffer. */ ADDCHAR( bufPtr, bufSize, '%' ); ADDCHAR( bufPtr, bufSize, *fmtPtr ); break; } } } ADDCHAR( bufPtr, bufSize, '\0' ); return (PRUint32)(bufPtr - buf - 1); } /*********************************************************************************** * * Description: * Returns the week number of the year (0-53) for the given time. firstDayOfWeek * is the day on which the week is considered to start (0=Sun, 1=Mon, ...). * Week 1 starts the first time firstDayOfWeek occurs in the year. In other words, * a partial week at the start of the year is considered week 0. * **********************************************************************************/ static unsigned int pr_WeekOfYear(const PRExplodedTime* time, unsigned int firstDayOfWeek) { int dayOfWeek; int dayOfYear; /* Get the day of the year for the given time then adjust it to represent the * first day of the week containing the given time. */ dayOfWeek = time->tm_wday - firstDayOfWeek; if (dayOfWeek < 0) dayOfWeek += 7; dayOfYear = time->tm_yday - dayOfWeek; if( dayOfYear <= 0 ) { /* If dayOfYear is <= 0, it is in the first partial week of the year. */ return 0; } else { /* Count the number of full weeks ( dayOfYear / 7 ) then add a week if there * are any days left over ( dayOfYear % 7 ). Because we are only counting to * the first day of the week containing the given time, rather than to the * actual day representing the given time, any days in week 0 will be "absorbed" * as extra days in the given week. */ return (dayOfYear / 7) + ( (dayOfYear % 7) == 0 ? 0 : 1 ); } } nspr-4.11/nspr/pr/src/misc/prtpool.c0000644000000000000000000006503712623070344015553 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" /* * Thread pools * Thread pools create and manage threads to provide support for * scheduling jobs onto one or more threads. * */ #ifdef OPT_WINNT #include #endif /* * worker thread */ typedef struct wthread { PRCList links; PRThread *thread; } wthread; /* * queue of timer jobs */ typedef struct timer_jobq { PRCList list; PRLock *lock; PRCondVar *cv; PRInt32 cnt; PRCList wthreads; } timer_jobq; /* * queue of jobs */ typedef struct tp_jobq { PRCList list; PRInt32 cnt; PRLock *lock; PRCondVar *cv; PRCList wthreads; #ifdef OPT_WINNT HANDLE nt_completion_port; #endif } tp_jobq; /* * queue of IO jobs */ typedef struct io_jobq { PRCList list; PRPollDesc *pollfds; PRInt32 npollfds; PRJob **polljobs; PRLock *lock; PRInt32 cnt; PRFileDesc *notify_fd; PRCList wthreads; } io_jobq; /* * Threadpool */ struct PRThreadPool { PRInt32 init_threads; PRInt32 max_threads; PRInt32 current_threads; PRInt32 idle_threads; PRUint32 stacksize; tp_jobq jobq; io_jobq ioq; timer_jobq timerq; PRLock *join_lock; /* used with jobp->join_cv */ PRCondVar *shutdown_cv; PRBool shutdown; }; typedef enum io_op_type { JOB_IO_READ, JOB_IO_WRITE, JOB_IO_CONNECT, JOB_IO_ACCEPT } io_op_type; #ifdef OPT_WINNT typedef struct NT_notifier { OVERLAPPED overlapped; /* must be first */ PRJob *jobp; } NT_notifier; #endif struct PRJob { PRCList links; /* for linking jobs */ PRBool on_ioq; /* job on ioq */ PRBool on_timerq; /* job on timerq */ PRJobFn job_func; void *job_arg; PRCondVar *join_cv; PRBool join_wait; /* == PR_TRUE, when waiting to join */ PRCondVar *cancel_cv; /* for cancelling IO jobs */ PRBool cancel_io; /* for cancelling IO jobs */ PRThreadPool *tpool; /* back pointer to thread pool */ PRJobIoDesc *iod; io_op_type io_op; PRInt16 io_poll_flags; PRNetAddr *netaddr; PRIntervalTime timeout; /* relative value */ PRIntervalTime absolute; #ifdef OPT_WINNT NT_notifier nt_notifier; #endif }; #define JOB_LINKS_PTR(_qp) \ ((PRJob *) ((char *) (_qp) - offsetof(PRJob, links))) #define WTHREAD_LINKS_PTR(_qp) \ ((wthread *) ((char *) (_qp) - offsetof(wthread, links))) #define JOINABLE_JOB(_jobp) (NULL != (_jobp)->join_cv) #define JOIN_NOTIFY(_jobp) \ PR_BEGIN_MACRO \ PR_Lock(_jobp->tpool->join_lock); \ _jobp->join_wait = PR_FALSE; \ PR_NotifyCondVar(_jobp->join_cv); \ PR_Unlock(_jobp->tpool->join_lock); \ PR_END_MACRO #define CANCEL_IO_JOB(jobp) \ PR_BEGIN_MACRO \ jobp->cancel_io = PR_FALSE; \ jobp->on_ioq = PR_FALSE; \ PR_REMOVE_AND_INIT_LINK(&jobp->links); \ tp->ioq.cnt--; \ PR_NotifyCondVar(jobp->cancel_cv); \ PR_END_MACRO static void delete_job(PRJob *jobp); static PRThreadPool * alloc_threadpool(void); static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp); static void notify_ioq(PRThreadPool *tp); static void notify_timerq(PRThreadPool *tp); /* * locks are acquired in the following order * * tp->ioq.lock,tp->timerq.lock * | * V * tp->jobq->lock */ /* * worker thread function */ static void wstart(void *arg) { PRThreadPool *tp = (PRThreadPool *) arg; PRCList *head; /* * execute jobs until shutdown */ while (!tp->shutdown) { PRJob *jobp; #ifdef OPT_WINNT BOOL rv; DWORD unused, shutdown; LPOVERLAPPED olp; PR_Lock(tp->jobq.lock); tp->idle_threads++; PR_Unlock(tp->jobq.lock); rv = GetQueuedCompletionStatus(tp->jobq.nt_completion_port, &unused, &shutdown, &olp, INFINITE); PR_ASSERT(rv); if (shutdown) break; jobp = ((NT_notifier *) olp)->jobp; PR_Lock(tp->jobq.lock); tp->idle_threads--; tp->jobq.cnt--; PR_Unlock(tp->jobq.lock); #else PR_Lock(tp->jobq.lock); while (PR_CLIST_IS_EMPTY(&tp->jobq.list) && (!tp->shutdown)) { tp->idle_threads++; PR_WaitCondVar(tp->jobq.cv, PR_INTERVAL_NO_TIMEOUT); tp->idle_threads--; } if (tp->shutdown) { PR_Unlock(tp->jobq.lock); break; } head = PR_LIST_HEAD(&tp->jobq.list); /* * remove job from queue */ PR_REMOVE_AND_INIT_LINK(head); tp->jobq.cnt--; jobp = JOB_LINKS_PTR(head); PR_Unlock(tp->jobq.lock); #endif jobp->job_func(jobp->job_arg); if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { JOIN_NOTIFY(jobp); } } PR_Lock(tp->jobq.lock); tp->current_threads--; PR_Unlock(tp->jobq.lock); } /* * add a job to the work queue */ static void add_to_jobq(PRThreadPool *tp, PRJob *jobp) { /* * add to jobq */ #ifdef OPT_WINNT PR_Lock(tp->jobq.lock); tp->jobq.cnt++; PR_Unlock(tp->jobq.lock); /* * notify worker thread(s) */ PostQueuedCompletionStatus(tp->jobq.nt_completion_port, 0, FALSE, &jobp->nt_notifier.overlapped); #else PR_Lock(tp->jobq.lock); PR_APPEND_LINK(&jobp->links,&tp->jobq.list); tp->jobq.cnt++; if ((tp->idle_threads < tp->jobq.cnt) && (tp->current_threads < tp->max_threads)) { wthread *wthrp; /* * increment thread count and unlock the jobq lock */ tp->current_threads++; PR_Unlock(tp->jobq.lock); /* create new worker thread */ wthrp = PR_NEWZAP(wthread); if (wthrp) { wthrp->thread = PR_CreateThread(PR_USER_THREAD, wstart, tp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,tp->stacksize); if (NULL == wthrp->thread) { PR_DELETE(wthrp); /* this sets wthrp to NULL */ } } PR_Lock(tp->jobq.lock); if (NULL == wthrp) { tp->current_threads--; } else { PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads); } } /* * wakeup a worker thread */ PR_NotifyCondVar(tp->jobq.cv); PR_Unlock(tp->jobq.lock); #endif } /* * io worker thread function */ static void io_wstart(void *arg) { PRThreadPool *tp = (PRThreadPool *) arg; int pollfd_cnt, pollfds_used; int rv; PRCList *qp, *nextqp; PRPollDesc *pollfds; PRJob **polljobs; int poll_timeout; PRIntervalTime now; /* * scan io_jobq * construct poll list * call PR_Poll * for all fds, for which poll returns true, move the job to * jobq and wakeup worker thread. */ while (!tp->shutdown) { PRJob *jobp; pollfd_cnt = tp->ioq.cnt + 10; if (pollfd_cnt > tp->ioq.npollfds) { /* * re-allocate pollfd array if the current one is not large * enough */ if (NULL != tp->ioq.pollfds) PR_Free(tp->ioq.pollfds); tp->ioq.pollfds = (PRPollDesc *) PR_Malloc(pollfd_cnt * (sizeof(PRPollDesc) + sizeof(PRJob *))); PR_ASSERT(NULL != tp->ioq.pollfds); /* * array of pollfds */ pollfds = tp->ioq.pollfds; tp->ioq.polljobs = (PRJob **) (&tp->ioq.pollfds[pollfd_cnt]); /* * parallel array of jobs */ polljobs = tp->ioq.polljobs; tp->ioq.npollfds = pollfd_cnt; } pollfds_used = 0; /* * add the notify fd; used for unblocking io thread(s) */ pollfds[pollfds_used].fd = tp->ioq.notify_fd; pollfds[pollfds_used].in_flags = PR_POLL_READ; pollfds[pollfds_used].out_flags = 0; polljobs[pollfds_used] = NULL; pollfds_used++; /* * fill in the pollfd array */ PR_Lock(tp->ioq.lock); for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = nextqp) { nextqp = qp->next; jobp = JOB_LINKS_PTR(qp); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); continue; } if (pollfds_used == (pollfd_cnt)) break; pollfds[pollfds_used].fd = jobp->iod->socket; pollfds[pollfds_used].in_flags = jobp->io_poll_flags; pollfds[pollfds_used].out_flags = 0; polljobs[pollfds_used] = jobp; pollfds_used++; } if (!PR_CLIST_IS_EMPTY(&tp->ioq.list)) { qp = tp->ioq.list.next; jobp = JOB_LINKS_PTR(qp); if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout) poll_timeout = PR_INTERVAL_NO_TIMEOUT; else if (PR_INTERVAL_NO_WAIT == jobp->timeout) poll_timeout = PR_INTERVAL_NO_WAIT; else { poll_timeout = jobp->absolute - PR_IntervalNow(); if (poll_timeout <= 0) /* already timed out */ poll_timeout = PR_INTERVAL_NO_WAIT; } } else { poll_timeout = PR_INTERVAL_NO_TIMEOUT; } PR_Unlock(tp->ioq.lock); /* * XXXX * should retry if more jobs have been added to the queue? * */ PR_ASSERT(pollfds_used <= pollfd_cnt); rv = PR_Poll(tp->ioq.pollfds, pollfds_used, poll_timeout); if (tp->shutdown) { break; } if (rv > 0) { /* * at least one io event is set */ PRStatus rval_status; PRInt32 index; PR_ASSERT(pollfds[0].fd == tp->ioq.notify_fd); /* * reset the pollable event, if notified */ if (pollfds[0].out_flags & PR_POLL_READ) { rval_status = PR_WaitForPollableEvent(tp->ioq.notify_fd); PR_ASSERT(PR_SUCCESS == rval_status); } for(index = 1; index < (pollfds_used); index++) { PRInt16 events = pollfds[index].in_flags; PRInt16 revents = pollfds[index].out_flags; jobp = polljobs[index]; if ((revents & PR_POLL_NVAL) || /* busted in all cases */ (revents & PR_POLL_ERR) || ((events & PR_POLL_WRITE) && (revents & PR_POLL_HUP))) { /* write op & hup */ PR_Lock(tp->ioq.lock); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); PR_Unlock(tp->ioq.lock); continue; } PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; jobp->on_ioq = PR_FALSE; PR_Unlock(tp->ioq.lock); /* set error */ if (PR_POLL_NVAL & revents) jobp->iod->error = PR_BAD_DESCRIPTOR_ERROR; else if (PR_POLL_HUP & revents) jobp->iod->error = PR_CONNECT_RESET_ERROR; else jobp->iod->error = PR_IO_ERROR; /* * add to jobq */ add_to_jobq(tp, jobp); } else if (revents) { /* * add to jobq */ PR_Lock(tp->ioq.lock); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); PR_Unlock(tp->ioq.lock); continue; } PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; jobp->on_ioq = PR_FALSE; PR_Unlock(tp->ioq.lock); if (jobp->io_op == JOB_IO_CONNECT) { if (PR_GetConnectStatus(&pollfds[index]) == PR_SUCCESS) jobp->iod->error = 0; else jobp->iod->error = PR_GetError(); } else jobp->iod->error = 0; add_to_jobq(tp, jobp); } } } /* * timeout processing */ now = PR_IntervalNow(); PR_Lock(tp->ioq.lock); for (qp = tp->ioq.list.next; qp != &tp->ioq.list; qp = nextqp) { nextqp = qp->next; jobp = JOB_LINKS_PTR(qp); if (jobp->cancel_io) { CANCEL_IO_JOB(jobp); continue; } if (PR_INTERVAL_NO_TIMEOUT == jobp->timeout) break; if ((PR_INTERVAL_NO_WAIT != jobp->timeout) && ((PRInt32)(jobp->absolute - now) > 0)) break; PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->ioq.cnt--; jobp->on_ioq = PR_FALSE; jobp->iod->error = PR_IO_TIMEOUT_ERROR; add_to_jobq(tp, jobp); } PR_Unlock(tp->ioq.lock); } } /* * timer worker thread function */ static void timer_wstart(void *arg) { PRThreadPool *tp = (PRThreadPool *) arg; PRCList *qp; PRIntervalTime timeout; PRIntervalTime now; /* * call PR_WaitCondVar with minimum value of all timeouts */ while (!tp->shutdown) { PRJob *jobp; PR_Lock(tp->timerq.lock); if (PR_CLIST_IS_EMPTY(&tp->timerq.list)) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { PRCList *qp; qp = tp->timerq.list.next; jobp = JOB_LINKS_PTR(qp); timeout = jobp->absolute - PR_IntervalNow(); if (timeout <= 0) timeout = PR_INTERVAL_NO_WAIT; /* already timed out */ } if (PR_INTERVAL_NO_WAIT != timeout) PR_WaitCondVar(tp->timerq.cv, timeout); if (tp->shutdown) { PR_Unlock(tp->timerq.lock); break; } /* * move expired-timer jobs to jobq */ now = PR_IntervalNow(); while (!PR_CLIST_IS_EMPTY(&tp->timerq.list)) { qp = tp->timerq.list.next; jobp = JOB_LINKS_PTR(qp); if ((PRInt32)(jobp->absolute - now) > 0) { break; } /* * job timed out */ PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->timerq.cnt--; jobp->on_timerq = PR_FALSE; add_to_jobq(tp, jobp); } PR_Unlock(tp->timerq.lock); } } static void delete_threadpool(PRThreadPool *tp) { if (NULL != tp) { if (NULL != tp->shutdown_cv) PR_DestroyCondVar(tp->shutdown_cv); if (NULL != tp->jobq.cv) PR_DestroyCondVar(tp->jobq.cv); if (NULL != tp->jobq.lock) PR_DestroyLock(tp->jobq.lock); if (NULL != tp->join_lock) PR_DestroyLock(tp->join_lock); #ifdef OPT_WINNT if (NULL != tp->jobq.nt_completion_port) CloseHandle(tp->jobq.nt_completion_port); #endif /* Timer queue */ if (NULL != tp->timerq.cv) PR_DestroyCondVar(tp->timerq.cv); if (NULL != tp->timerq.lock) PR_DestroyLock(tp->timerq.lock); if (NULL != tp->ioq.lock) PR_DestroyLock(tp->ioq.lock); if (NULL != tp->ioq.pollfds) PR_Free(tp->ioq.pollfds); if (NULL != tp->ioq.notify_fd) PR_DestroyPollableEvent(tp->ioq.notify_fd); PR_Free(tp); } return; } static PRThreadPool * alloc_threadpool(void) { PRThreadPool *tp; tp = (PRThreadPool *) PR_CALLOC(sizeof(*tp)); if (NULL == tp) goto failed; tp->jobq.lock = PR_NewLock(); if (NULL == tp->jobq.lock) goto failed; tp->jobq.cv = PR_NewCondVar(tp->jobq.lock); if (NULL == tp->jobq.cv) goto failed; tp->join_lock = PR_NewLock(); if (NULL == tp->join_lock) goto failed; #ifdef OPT_WINNT tp->jobq.nt_completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (NULL == tp->jobq.nt_completion_port) goto failed; #endif tp->ioq.lock = PR_NewLock(); if (NULL == tp->ioq.lock) goto failed; /* Timer queue */ tp->timerq.lock = PR_NewLock(); if (NULL == tp->timerq.lock) goto failed; tp->timerq.cv = PR_NewCondVar(tp->timerq.lock); if (NULL == tp->timerq.cv) goto failed; tp->shutdown_cv = PR_NewCondVar(tp->jobq.lock); if (NULL == tp->shutdown_cv) goto failed; tp->ioq.notify_fd = PR_NewPollableEvent(); if (NULL == tp->ioq.notify_fd) goto failed; return tp; failed: delete_threadpool(tp); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } /* Create thread pool */ PR_IMPLEMENT(PRThreadPool *) PR_CreateThreadPool(PRInt32 initial_threads, PRInt32 max_threads, PRUint32 stacksize) { PRThreadPool *tp; PRThread *thr; int i; wthread *wthrp; tp = alloc_threadpool(); if (NULL == tp) return NULL; tp->init_threads = initial_threads; tp->max_threads = max_threads; tp->stacksize = stacksize; PR_INIT_CLIST(&tp->jobq.list); PR_INIT_CLIST(&tp->ioq.list); PR_INIT_CLIST(&tp->timerq.list); PR_INIT_CLIST(&tp->jobq.wthreads); PR_INIT_CLIST(&tp->ioq.wthreads); PR_INIT_CLIST(&tp->timerq.wthreads); tp->shutdown = PR_FALSE; PR_Lock(tp->jobq.lock); for(i=0; i < initial_threads; ++i) { thr = PR_CreateThread(PR_USER_THREAD, wstart, tp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD,stacksize); PR_ASSERT(thr); wthrp = PR_NEWZAP(wthread); PR_ASSERT(wthrp); wthrp->thread = thr; PR_APPEND_LINK(&wthrp->links, &tp->jobq.wthreads); } tp->current_threads = initial_threads; thr = PR_CreateThread(PR_USER_THREAD, io_wstart, tp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,stacksize); PR_ASSERT(thr); wthrp = PR_NEWZAP(wthread); PR_ASSERT(wthrp); wthrp->thread = thr; PR_APPEND_LINK(&wthrp->links, &tp->ioq.wthreads); thr = PR_CreateThread(PR_USER_THREAD, timer_wstart, tp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,PR_JOINABLE_THREAD,stacksize); PR_ASSERT(thr); wthrp = PR_NEWZAP(wthread); PR_ASSERT(wthrp); wthrp->thread = thr; PR_APPEND_LINK(&wthrp->links, &tp->timerq.wthreads); PR_Unlock(tp->jobq.lock); return tp; } static void delete_job(PRJob *jobp) { if (NULL != jobp) { if (NULL != jobp->join_cv) { PR_DestroyCondVar(jobp->join_cv); jobp->join_cv = NULL; } if (NULL != jobp->cancel_cv) { PR_DestroyCondVar(jobp->cancel_cv); jobp->cancel_cv = NULL; } PR_DELETE(jobp); } } static PRJob * alloc_job(PRBool joinable, PRThreadPool *tp) { PRJob *jobp; jobp = PR_NEWZAP(PRJob); if (NULL == jobp) goto failed; if (joinable) { jobp->join_cv = PR_NewCondVar(tp->join_lock); jobp->join_wait = PR_TRUE; if (NULL == jobp->join_cv) goto failed; } else { jobp->join_cv = NULL; } #ifdef OPT_WINNT jobp->nt_notifier.jobp = jobp; #endif return jobp; failed: delete_job(jobp); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } /* queue a job */ PR_IMPLEMENT(PRJob *) PR_QueueJob(PRThreadPool *tpool, PRJobFn fn, void *arg, PRBool joinable) { PRJob *jobp; jobp = alloc_job(joinable, tpool); if (NULL == jobp) return NULL; jobp->job_func = fn; jobp->job_arg = arg; jobp->tpool = tpool; add_to_jobq(tpool, jobp); return jobp; } /* queue a job, when a socket is readable or writeable */ static PRJob * queue_io_job(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable, io_op_type op) { PRJob *jobp; PRIntervalTime now; jobp = alloc_job(joinable, tpool); if (NULL == jobp) { return NULL; } /* * Add a new job to io_jobq * wakeup io worker thread */ jobp->job_func = fn; jobp->job_arg = arg; jobp->tpool = tpool; jobp->iod = iod; if (JOB_IO_READ == op) { jobp->io_op = JOB_IO_READ; jobp->io_poll_flags = PR_POLL_READ; } else if (JOB_IO_WRITE == op) { jobp->io_op = JOB_IO_WRITE; jobp->io_poll_flags = PR_POLL_WRITE; } else if (JOB_IO_ACCEPT == op) { jobp->io_op = JOB_IO_ACCEPT; jobp->io_poll_flags = PR_POLL_READ; } else if (JOB_IO_CONNECT == op) { jobp->io_op = JOB_IO_CONNECT; jobp->io_poll_flags = PR_POLL_WRITE|PR_POLL_EXCEPT; } else { delete_job(jobp); PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } jobp->timeout = iod->timeout; if ((PR_INTERVAL_NO_TIMEOUT == iod->timeout) || (PR_INTERVAL_NO_WAIT == iod->timeout)) { jobp->absolute = iod->timeout; } else { now = PR_IntervalNow(); jobp->absolute = now + iod->timeout; } PR_Lock(tpool->ioq.lock); if (PR_CLIST_IS_EMPTY(&tpool->ioq.list) || (PR_INTERVAL_NO_TIMEOUT == iod->timeout)) { PR_APPEND_LINK(&jobp->links,&tpool->ioq.list); } else if (PR_INTERVAL_NO_WAIT == iod->timeout) { PR_INSERT_LINK(&jobp->links,&tpool->ioq.list); } else { PRCList *qp; PRJob *tmp_jobp; /* * insert into the timeout-sorted ioq */ for (qp = tpool->ioq.list.prev; qp != &tpool->ioq.list; qp = qp->prev) { tmp_jobp = JOB_LINKS_PTR(qp); if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) { break; } } PR_INSERT_AFTER(&jobp->links,qp); } jobp->on_ioq = PR_TRUE; tpool->ioq.cnt++; /* * notify io worker thread(s) */ PR_Unlock(tpool->ioq.lock); notify_ioq(tpool); return jobp; } /* queue a job, when a socket is readable */ PR_IMPLEMENT(PRJob *) PR_QueueJob_Read(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable) { return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_READ)); } /* queue a job, when a socket is writeable */ PR_IMPLEMENT(PRJob *) PR_QueueJob_Write(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn,void * arg, PRBool joinable) { return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_WRITE)); } /* queue a job, when a socket has a pending connection */ PR_IMPLEMENT(PRJob *) PR_QueueJob_Accept(PRThreadPool *tpool, PRJobIoDesc *iod, PRJobFn fn, void * arg, PRBool joinable) { return (queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_ACCEPT)); } /* queue a job, when a socket can be connected */ PR_IMPLEMENT(PRJob *) PR_QueueJob_Connect(PRThreadPool *tpool, PRJobIoDesc *iod, const PRNetAddr *addr, PRJobFn fn, void * arg, PRBool joinable) { PRStatus rv; PRErrorCode err; rv = PR_Connect(iod->socket, addr, PR_INTERVAL_NO_WAIT); if ((rv == PR_FAILURE) && ((err = PR_GetError()) == PR_IN_PROGRESS_ERROR)){ /* connection pending */ return(queue_io_job(tpool, iod, fn, arg, joinable, JOB_IO_CONNECT)); } else { /* * connection succeeded or failed; add to jobq right away */ if (rv == PR_FAILURE) iod->error = err; else iod->error = 0; return(PR_QueueJob(tpool, fn, arg, joinable)); } } /* queue a job, when a timer expires */ PR_IMPLEMENT(PRJob *) PR_QueueJob_Timer(PRThreadPool *tpool, PRIntervalTime timeout, PRJobFn fn, void * arg, PRBool joinable) { PRIntervalTime now; PRJob *jobp; if (PR_INTERVAL_NO_TIMEOUT == timeout) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } if (PR_INTERVAL_NO_WAIT == timeout) { /* * no waiting; add to jobq right away */ return(PR_QueueJob(tpool, fn, arg, joinable)); } jobp = alloc_job(joinable, tpool); if (NULL == jobp) { return NULL; } /* * Add a new job to timer_jobq * wakeup timer worker thread */ jobp->job_func = fn; jobp->job_arg = arg; jobp->tpool = tpool; jobp->timeout = timeout; now = PR_IntervalNow(); jobp->absolute = now + timeout; PR_Lock(tpool->timerq.lock); jobp->on_timerq = PR_TRUE; if (PR_CLIST_IS_EMPTY(&tpool->timerq.list)) PR_APPEND_LINK(&jobp->links,&tpool->timerq.list); else { PRCList *qp; PRJob *tmp_jobp; /* * insert into the sorted timer jobq */ for (qp = tpool->timerq.list.prev; qp != &tpool->timerq.list; qp = qp->prev) { tmp_jobp = JOB_LINKS_PTR(qp); if ((PRInt32)(jobp->absolute - tmp_jobp->absolute) >= 0) { break; } } PR_INSERT_AFTER(&jobp->links,qp); } tpool->timerq.cnt++; /* * notify timer worker thread(s) */ notify_timerq(tpool); PR_Unlock(tpool->timerq.lock); return jobp; } static void notify_timerq(PRThreadPool *tp) { /* * wakeup the timer thread(s) */ PR_NotifyCondVar(tp->timerq.cv); } static void notify_ioq(PRThreadPool *tp) { PRStatus rval_status; /* * wakeup the io thread(s) */ rval_status = PR_SetPollableEvent(tp->ioq.notify_fd); PR_ASSERT(PR_SUCCESS == rval_status); } /* * cancel a job * * XXXX: is this needed? likely to be removed */ PR_IMPLEMENT(PRStatus) PR_CancelJob(PRJob *jobp) { PRStatus rval = PR_FAILURE; PRThreadPool *tp; if (jobp->on_timerq) { /* * now, check again while holding the timerq lock */ tp = jobp->tpool; PR_Lock(tp->timerq.lock); if (jobp->on_timerq) { jobp->on_timerq = PR_FALSE; PR_REMOVE_AND_INIT_LINK(&jobp->links); tp->timerq.cnt--; PR_Unlock(tp->timerq.lock); if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { JOIN_NOTIFY(jobp); } rval = PR_SUCCESS; } else PR_Unlock(tp->timerq.lock); } else if (jobp->on_ioq) { /* * now, check again while holding the ioq lock */ tp = jobp->tpool; PR_Lock(tp->ioq.lock); if (jobp->on_ioq) { jobp->cancel_cv = PR_NewCondVar(tp->ioq.lock); if (NULL == jobp->cancel_cv) { PR_Unlock(tp->ioq.lock); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return PR_FAILURE; } /* * mark job 'cancelled' and notify io thread(s) * XXXX: * this assumes there is only one io thread; when there * are multiple threads, the io thread processing this job * must be notified. */ jobp->cancel_io = PR_TRUE; PR_Unlock(tp->ioq.lock); /* release, reacquire ioq lock */ notify_ioq(tp); PR_Lock(tp->ioq.lock); while (jobp->cancel_io) PR_WaitCondVar(jobp->cancel_cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(tp->ioq.lock); PR_ASSERT(!jobp->on_ioq); if (!JOINABLE_JOB(jobp)) { delete_job(jobp); } else { JOIN_NOTIFY(jobp); } rval = PR_SUCCESS; } else PR_Unlock(tp->ioq.lock); } if (PR_FAILURE == rval) PR_SetError(PR_INVALID_STATE_ERROR, 0); return rval; } /* join a job, wait until completion */ PR_IMPLEMENT(PRStatus) PR_JoinJob(PRJob *jobp) { if (!JOINABLE_JOB(jobp)) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } PR_Lock(jobp->tpool->join_lock); while(jobp->join_wait) PR_WaitCondVar(jobp->join_cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(jobp->tpool->join_lock); delete_job(jobp); return PR_SUCCESS; } /* shutdown threadpool */ PR_IMPLEMENT(PRStatus) PR_ShutdownThreadPool(PRThreadPool *tpool) { PRStatus rval = PR_SUCCESS; PR_Lock(tpool->jobq.lock); tpool->shutdown = PR_TRUE; PR_NotifyAllCondVar(tpool->shutdown_cv); PR_Unlock(tpool->jobq.lock); return rval; } /* * join thread pool * wait for termination of worker threads * reclaim threadpool resources */ PR_IMPLEMENT(PRStatus) PR_JoinThreadPool(PRThreadPool *tpool) { PRStatus rval = PR_SUCCESS; PRCList *head; PRStatus rval_status; PR_Lock(tpool->jobq.lock); while (!tpool->shutdown) PR_WaitCondVar(tpool->shutdown_cv, PR_INTERVAL_NO_TIMEOUT); /* * wakeup worker threads */ #ifdef OPT_WINNT /* * post shutdown notification for all threads */ { int i; for(i=0; i < tpool->current_threads; i++) { PostQueuedCompletionStatus(tpool->jobq.nt_completion_port, 0, TRUE, NULL); } } #else PR_NotifyAllCondVar(tpool->jobq.cv); #endif /* * wakeup io thread(s) */ notify_ioq(tpool); /* * wakeup timer thread(s) */ PR_Lock(tpool->timerq.lock); notify_timerq(tpool); PR_Unlock(tpool->timerq.lock); while (!PR_CLIST_IS_EMPTY(&tpool->jobq.wthreads)) { wthread *wthrp; head = PR_LIST_HEAD(&tpool->jobq.wthreads); PR_REMOVE_AND_INIT_LINK(head); PR_Unlock(tpool->jobq.lock); wthrp = WTHREAD_LINKS_PTR(head); rval_status = PR_JoinThread(wthrp->thread); PR_ASSERT(PR_SUCCESS == rval_status); PR_DELETE(wthrp); PR_Lock(tpool->jobq.lock); } PR_Unlock(tpool->jobq.lock); while (!PR_CLIST_IS_EMPTY(&tpool->ioq.wthreads)) { wthread *wthrp; head = PR_LIST_HEAD(&tpool->ioq.wthreads); PR_REMOVE_AND_INIT_LINK(head); wthrp = WTHREAD_LINKS_PTR(head); rval_status = PR_JoinThread(wthrp->thread); PR_ASSERT(PR_SUCCESS == rval_status); PR_DELETE(wthrp); } while (!PR_CLIST_IS_EMPTY(&tpool->timerq.wthreads)) { wthread *wthrp; head = PR_LIST_HEAD(&tpool->timerq.wthreads); PR_REMOVE_AND_INIT_LINK(head); wthrp = WTHREAD_LINKS_PTR(head); rval_status = PR_JoinThread(wthrp->thread); PR_ASSERT(PR_SUCCESS == rval_status); PR_DELETE(wthrp); } /* * Delete queued jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->jobq.list)) { PRJob *jobp; head = PR_LIST_HEAD(&tpool->jobq.list); PR_REMOVE_AND_INIT_LINK(head); jobp = JOB_LINKS_PTR(head); tpool->jobq.cnt--; delete_job(jobp); } /* delete io jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->ioq.list)) { PRJob *jobp; head = PR_LIST_HEAD(&tpool->ioq.list); PR_REMOVE_AND_INIT_LINK(head); tpool->ioq.cnt--; jobp = JOB_LINKS_PTR(head); delete_job(jobp); } /* delete timer jobs */ while (!PR_CLIST_IS_EMPTY(&tpool->timerq.list)) { PRJob *jobp; head = PR_LIST_HEAD(&tpool->timerq.list); PR_REMOVE_AND_INIT_LINK(head); tpool->timerq.cnt--; jobp = JOB_LINKS_PTR(head); delete_job(jobp); } PR_ASSERT(0 == tpool->jobq.cnt); PR_ASSERT(0 == tpool->ioq.cnt); PR_ASSERT(0 == tpool->timerq.cnt); delete_threadpool(tpool); return rval; } nspr-4.11/nspr/pr/src/misc/prtrace.c0000644000000000000000000005760712623070344015520 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** prtrace.c -- NSPR Trace Instrumentation ** ** Implement the API defined in prtrace.h ** ** ** */ #include #include "primpl.h" #define DEFAULT_TRACE_BUFSIZE ( 1024 * 1024 ) #define DEFAULT_BUFFER_SEGMENTS 2 /* ** Enumerate states in a RName structure */ typedef enum TraceState { Running = 1, Suspended = 2 } TraceState; /* ** Define QName structure */ typedef struct QName { PRCList link; PRCList rNameList; char name[PRTRACE_NAME_MAX+1]; } QName; /* ** Define RName structure */ typedef struct RName { PRCList link; PRLock *lock; QName *qName; TraceState state; char name[PRTRACE_NAME_MAX+1]; char desc[PRTRACE_DESC_MAX+1]; } RName; /* ** The Trace Facility database ** */ static PRLogModuleInfo *lm; static PRLock *traceLock; /* Facility Lock */ static PRCList qNameList; /* anchor to all QName structures */ static TraceState traceState = Running; /* ** in-memory trace buffer controls */ static PRTraceEntry *tBuf; /* pointer to buffer */ static PRInt32 bufSize; /* size of buffer, in bytes, rounded up to sizeof(PRTraceEntry) */ static volatile PRInt32 next; /* index to next PRTraceEntry */ static PRInt32 last; /* index of highest numbered trace entry */ /* ** Real-time buffer capture controls */ static PRInt32 fetchLastSeen = 0; static PRBool fetchLostData = PR_FALSE; /* ** Buffer write-to-file controls */ static PRLock *logLock; /* Sync lock */ static PRCondVar *logCVar; /* Sync Condidtion Variable */ /* ** Inter-thread state communication. ** Controling thread writes to logOrder under protection of logCVar ** the logging thread reads logOrder and sets logState on Notify. ** ** logSegments, logCount, logLostData must be read and written under ** protection of logLock, logCVar. ** */ static enum LogState { LogNotRunning, /* Initial state */ LogReset, /* Causes logger to re-calc controls */ LogActive, /* Logging in progress, set only by log thread */ LogSuspend, /* Suspend Logging */ LogResume, /* Resume Logging => LogActive */ LogStop /* Stop the log thread */ } logOrder, logState, localState; /* controlling state variables */ static PRInt32 logSegments; /* Number of buffer segments */ static PRInt32 logEntries; /* number of Trace Entries in the buffer */ static PRInt32 logEntriesPerSegment; /* number of PRTraceEntries per buffer segment */ static PRInt32 logSegSize; /* size of buffer segment */ static PRInt32 logCount; /* number of segments pending output */ static PRInt32 logLostData; /* number of lost log buffer segments */ /* ** end Trace Database ** */ /* ** _PR_InitializeTrace() -- Initialize the trace facility */ static void NewTraceBuffer( PRInt32 size ) { /* ** calculate the size of the buffer ** round down so that each segment has the same number of ** trace entries */ logSegments = DEFAULT_BUFFER_SEGMENTS; logEntries = size / sizeof(PRTraceEntry); logEntriesPerSegment = logEntries / logSegments; logEntries = logSegments * logEntriesPerSegment; bufSize = logEntries * sizeof(PRTraceEntry); logSegSize = logEntriesPerSegment * sizeof(PRTraceEntry); PR_ASSERT( bufSize != 0); PR_LOG( lm, PR_LOG_ERROR, ("NewTraceBuffer: logSegments: %ld, logEntries: %ld, logEntriesPerSegment: %ld, logSegSize: %ld", logSegments, logEntries, logEntriesPerSegment, logSegSize )); tBuf = PR_Malloc( bufSize ); if ( tBuf == NULL ) { PR_LOG( lm, PR_LOG_ERROR, ("PRTrace: Failed to get trace buffer")); PR_ASSERT( 0 ); } else { PR_LOG( lm, PR_LOG_NOTICE, ("PRTrace: Got trace buffer of size: %ld, at %p", bufSize, tBuf)); } next = 0; last = logEntries -1; logCount = 0; logLostData = PR_TRUE; /* not really on first call */ logOrder = LogReset; } /* end NewTraceBuffer() */ /* ** _PR_InitializeTrace() -- Initialize the trace facility */ static void _PR_InitializeTrace( void ) { /* The lock pointer better be null on this call */ PR_ASSERT( traceLock == NULL ); traceLock = PR_NewLock(); PR_ASSERT( traceLock != NULL ); PR_Lock( traceLock ); PR_INIT_CLIST( &qNameList ); lm = PR_NewLogModule("trace"); bufSize = DEFAULT_TRACE_BUFSIZE; NewTraceBuffer( bufSize ); /* Initialize logging controls */ logLock = PR_NewLock(); logCVar = PR_NewCondVar( logLock ); PR_Unlock( traceLock ); return; } /* end _PR_InitializeTrace() */ /* ** Create a Trace Handle */ PR_IMPLEMENT(PRTraceHandle) PR_CreateTrace( const char *qName, /* QName for this trace handle */ const char *rName, /* RName for this trace handle */ const char *description /* description for this trace handle */ ) { QName *qnp; RName *rnp; PRBool matchQname = PR_FALSE; /* Self initialize, if necessary */ if ( traceLock == NULL ) _PR_InitializeTrace(); /* Validate input arguments */ PR_ASSERT( strlen(qName) <= PRTRACE_NAME_MAX ); PR_ASSERT( strlen(rName) <= PRTRACE_NAME_MAX ); PR_ASSERT( strlen(description) <= PRTRACE_DESC_MAX ); PR_LOG( lm, PR_LOG_DEBUG, ("PRTRACE: CreateTrace: Qname: %s, RName: %s", qName, rName)); /* Lock the Facility */ PR_Lock( traceLock ); /* Do we already have a matching QName? */ if (!PR_CLIST_IS_EMPTY( &qNameList )) { qnp = (QName *) PR_LIST_HEAD( &qNameList ); do { if ( strcmp(qnp->name, qName) == 0) { matchQname = PR_TRUE; break; } qnp = (QName *)PR_NEXT_LINK( &qnp->link ); } while( qnp != (QName *)&qNameList ); } /* ** If we did not find a matching QName, ** allocate one and initialize it. ** link it onto the qNameList. ** */ if ( matchQname != PR_TRUE ) { qnp = PR_NEWZAP( QName ); PR_ASSERT( qnp != NULL ); PR_INIT_CLIST( &qnp->link ); PR_INIT_CLIST( &qnp->rNameList ); strcpy( qnp->name, qName ); PR_APPEND_LINK( &qnp->link, &qNameList ); } /* Do we already have a matching RName? */ if (!PR_CLIST_IS_EMPTY( &qnp->rNameList )) { rnp = (RName *) PR_LIST_HEAD( &qnp->rNameList ); do { /* ** No duplicate RNames are allowed within a QName ** */ PR_ASSERT( strcmp(rnp->name, rName)); rnp = (RName *)PR_NEXT_LINK( &rnp->link ); } while( rnp != (RName *)&qnp->rNameList ); } /* Get a new RName structure; initialize its members */ rnp = PR_NEWZAP( RName ); PR_ASSERT( rnp != NULL ); PR_INIT_CLIST( &rnp->link ); strcpy( rnp->name, rName ); strcpy( rnp->desc, description ); rnp->lock = PR_NewLock(); rnp->state = Running; if ( rnp->lock == NULL ) { PR_ASSERT(0); } PR_APPEND_LINK( &rnp->link, &qnp->rNameList ); /* add RName to QName's rnList */ rnp->qName = qnp; /* point the RName to the QName */ /* Unlock the Facility */ PR_Unlock( traceLock ); PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Create: QName: %s %p, RName: %s %p\n\t", qName, qnp, rName, rnp )); return((PRTraceHandle)rnp); } /* end PR_CreateTrace() */ /* ** */ PR_IMPLEMENT(void) PR_DestroyTrace( PRTraceHandle handle /* Handle to be destroyed */ ) { RName *rnp = (RName *)handle; QName *qnp = rnp->qName; PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting: QName: %s, RName: %s", qnp->name, rnp->name)); /* Lock the Facility */ PR_Lock( traceLock ); /* ** Remove RName from the list of RNames in QName ** and free RName */ PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting RName: %s, %p", rnp->name, rnp)); PR_REMOVE_LINK( &rnp->link ); PR_Free( rnp->lock ); PR_DELETE( rnp ); /* ** If this is the last RName within QName ** remove QName from the qNameList and free it */ if ( PR_CLIST_IS_EMPTY( &qnp->rNameList ) ) { PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: Deleting unused QName: %s, %p", qnp->name, qnp)); PR_REMOVE_LINK( &qnp->link ); PR_DELETE( qnp ); } /* Unlock the Facility */ PR_Unlock( traceLock ); return; } /* end PR_DestroyTrace() */ /* ** Create a TraceEntry in the trace buffer */ PR_IMPLEMENT(void) PR_Trace( PRTraceHandle handle, /* use this trace handle */ PRUint32 userData0, /* User supplied data word 0 */ PRUint32 userData1, /* User supplied data word 1 */ PRUint32 userData2, /* User supplied data word 2 */ PRUint32 userData3, /* User supplied data word 3 */ PRUint32 userData4, /* User supplied data word 4 */ PRUint32 userData5, /* User supplied data word 5 */ PRUint32 userData6, /* User supplied data word 6 */ PRUint32 userData7 /* User supplied data word 7 */ ) { PRTraceEntry *tep; PRInt32 mark; if ( (traceState == Suspended ) || ( ((RName *)handle)->state == Suspended )) return; /* ** Get the next trace entry slot w/ minimum delay */ PR_Lock( traceLock ); tep = &tBuf[next++]; if ( next > last ) next = 0; if ( fetchLostData == PR_FALSE && next == fetchLastSeen ) fetchLostData = PR_TRUE; mark = next; PR_Unlock( traceLock ); /* ** We have a trace entry. Fill it in. */ tep->thread = PR_GetCurrentThread(); tep->handle = handle; tep->time = PR_Now(); tep->userData[0] = userData0; tep->userData[1] = userData1; tep->userData[2] = userData2; tep->userData[3] = userData3; tep->userData[4] = userData4; tep->userData[5] = userData5; tep->userData[6] = userData6; tep->userData[7] = userData7; /* When buffer segment is full, signal trace log thread to run */ if (( mark % logEntriesPerSegment) == 0 ) { PR_Lock( logLock ); logCount++; PR_NotifyCondVar( logCVar ); PR_Unlock( logLock ); /* ** Gh0D! This is awful! ** Anyway, to minimize lost trace data segments, ** I inserted the PR_Sleep(0) to cause a context switch ** so that the log thread could run. ** I know, it perturbs the universe and may cause ** funny things to happen in the optimized builds. ** Take it out, lose data; leave it in risk Heisenberg. */ /* PR_Sleep(0); */ } return; } /* end PR_Trace() */ /* ** */ PR_IMPLEMENT(void) PR_SetTraceOption( PRTraceOption command, /* One of the enumerated values */ void *value /* command value or NULL */ ) { RName * rnp; switch ( command ) { case PRTraceBufSize : PR_Lock( traceLock ); PR_Free( tBuf ); bufSize = *(PRInt32 *)value; NewTraceBuffer( bufSize ); PR_Unlock( traceLock ); PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceBufSize: %ld", bufSize)); break; case PRTraceEnable : rnp = *(RName **)value; rnp->state = Running; PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceEnable: %p", rnp)); break; case PRTraceDisable : rnp = *(RName **)value; rnp->state = Suspended; PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceDisable: %p", rnp)); break; case PRTraceSuspend : traceState = Suspended; PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceSuspend")); break; case PRTraceResume : traceState = Running; PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceResume")); break; case PRTraceSuspendRecording : PR_Lock( logLock ); logOrder = LogSuspend; PR_NotifyCondVar( logCVar ); PR_Unlock( logLock ); PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceSuspendRecording")); break; case PRTraceResumeRecording : PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceResumeRecording")); if ( logState != LogSuspend ) break; PR_Lock( logLock ); logOrder = LogResume; PR_NotifyCondVar( logCVar ); PR_Unlock( logLock ); break; case PRTraceStopRecording : PR_Lock( logLock ); logOrder = LogStop; PR_NotifyCondVar( logCVar ); PR_Unlock( logLock ); PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceStopRecording")); break; case PRTraceLockHandles : PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceLockTraceHandles")); PR_Lock( traceLock ); break; case PRTraceUnLockHandles : PR_LOG( lm, PR_LOG_DEBUG, ("PRSetTraceOption: PRTraceUnLockHandles")); PR_Unlock( traceLock ); break; default: PR_LOG( lm, PR_LOG_ERROR, ("PRSetTraceOption: Invalid command %ld", command )); PR_ASSERT( 0 ); break; } /* end switch() */ return; } /* end PR_SetTraceOption() */ /* ** */ PR_IMPLEMENT(void) PR_GetTraceOption( PRTraceOption command, /* One of the enumerated values */ void *value /* command value or NULL */ ) { switch ( command ) { case PRTraceBufSize : *((PRInt32 *)value) = bufSize; PR_LOG( lm, PR_LOG_DEBUG, ("PRGetTraceOption: PRTraceBufSize: %ld", bufSize )); break; default: PR_LOG( lm, PR_LOG_ERROR, ("PRGetTraceOption: Invalid command %ld", command )); PR_ASSERT( 0 ); break; } /* end switch() */ return; } /* end PR_GetTraceOption() */ /* ** */ PR_IMPLEMENT(PRTraceHandle) PR_GetTraceHandleFromName( const char *qName, /* QName search argument */ const char *rName /* RName search argument */ ) { const char *qn, *rn, *desc; PRTraceHandle qh, rh = NULL; RName *rnp = NULL; PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetTraceHandleFromName:\n\t" "QName: %s, RName: %s", qName, rName )); qh = PR_FindNextTraceQname( NULL ); while (qh != NULL) { rh = PR_FindNextTraceRname( NULL, qh ); while ( rh != NULL ) { PR_GetTraceNameFromHandle( rh, &qn, &rn, &desc ); if ( (strcmp( qName, qn ) == 0) && (strcmp( rName, rn ) == 0 )) { rnp = (RName *)rh; goto foundIt; } rh = PR_FindNextTraceRname( rh, qh ); } qh = PR_FindNextTraceQname( NULL ); } foundIt: PR_LOG( lm, PR_LOG_DEBUG, ("PR_Counter: GetConterHandleFromName: %p", rnp )); return(rh); } /* end PR_GetTraceHandleFromName() */ /* ** */ PR_IMPLEMENT(void) PR_GetTraceNameFromHandle( PRTraceHandle handle, /* handle as search argument */ const char **qName, /* pointer to associated QName */ const char **rName, /* pointer to associated RName */ const char **description /* pointer to associated description */ ) { RName *rnp = (RName *)handle; QName *qnp = rnp->qName; *qName = qnp->name; *rName = rnp->name; *description = rnp->desc; PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: GetConterNameFromHandle: " "QNp: %p, RNp: %p,\n\tQName: %s, RName: %s, Desc: %s", qnp, rnp, qnp->name, rnp->name, rnp->desc )); return; } /* end PR_GetTraceNameFromHandle() */ /* ** */ PR_IMPLEMENT(PRTraceHandle) PR_FindNextTraceQname( PRTraceHandle handle ) { QName *qnp = (QName *)handle; if ( PR_CLIST_IS_EMPTY( &qNameList )) qnp = NULL; else if ( qnp == NULL ) qnp = (QName *)PR_LIST_HEAD( &qNameList ); else if ( PR_NEXT_LINK( &qnp->link ) == &qNameList ) qnp = NULL; else qnp = (QName *)PR_NEXT_LINK( &qnp->link ); PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextQname: Handle: %p, Returns: %p", handle, qnp )); return((PRTraceHandle)qnp); } /* end PR_FindNextTraceQname() */ /* ** */ PR_IMPLEMENT(PRTraceHandle) PR_FindNextTraceRname( PRTraceHandle rhandle, PRTraceHandle qhandle ) { RName *rnp = (RName *)rhandle; QName *qnp = (QName *)qhandle; if ( PR_CLIST_IS_EMPTY( &qnp->rNameList )) rnp = NULL; else if ( rnp == NULL ) rnp = (RName *)PR_LIST_HEAD( &qnp->rNameList ); else if ( PR_NEXT_LINK( &rnp->link ) == &qnp->rNameList ) rnp = NULL; else rnp = (RName *)PR_NEXT_LINK( &rnp->link ); PR_LOG( lm, PR_LOG_DEBUG, ("PRTrace: FindNextRname: Rhandle: %p, QHandle: %p, Returns: %p", rhandle, qhandle, rnp )); return((PRTraceHandle)rnp); } /* end PR_FindNextTraceRname() */ /* ** */ static PRFileDesc * InitializeRecording( void ) { char *logFileName; PRFileDesc *logFile; /* Self initialize, if necessary */ if ( traceLock == NULL ) _PR_InitializeTrace(); PR_LOG( lm, PR_LOG_DEBUG, ("PR_RecordTraceEntries: begins")); logLostData = 0; /* reset at entry */ logState = LogReset; #ifdef XP_UNIX if ((getuid() != geteuid()) || (getgid() != getegid())) { return NULL; } #endif /* XP_UNIX */ /* Get the filename for the logfile from the environment */ logFileName = PR_GetEnv( "NSPR_TRACE_LOG" ); if ( logFileName == NULL ) { PR_LOG( lm, PR_LOG_ERROR, ("RecordTraceEntries: Environment variable not defined. Exiting")); return NULL; } /* Open the logfile */ logFile = PR_Open( logFileName, PR_WRONLY | PR_CREATE_FILE, 0666 ); if ( logFile == NULL ) { PR_LOG( lm, PR_LOG_ERROR, ("RecordTraceEntries: Cannot open %s as trace log file. OS error: %ld", logFileName, PR_GetOSError())); return NULL; } return logFile; } /* end InitializeRecording() */ /* ** */ static void ProcessOrders( void ) { switch ( logOrder ) { case LogReset : logOrder = logState = localState; PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: LogReset")); break; case LogSuspend : localState = logOrder = logState = LogSuspend; PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: LogSuspend")); break; case LogResume : localState = logOrder = logState = LogActive; PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: LogResume")); break; case LogStop : logOrder = logState = LogStop; PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: LogStop")); break; default : PR_LOG( lm, PR_LOG_ERROR, ("RecordTraceEntries: Invalid logOrder: %ld", logOrder )); PR_ASSERT( 0 ); break; } /* end switch() */ return ; } /* end ProcessOrders() */ /* ** */ static void WriteTraceSegment( PRFileDesc *logFile, void *buf, PRInt32 amount ) { PRInt32 rc; PR_LOG( lm, PR_LOG_ERROR, ("WriteTraceSegment: Buffer: %p, Amount: %ld", buf, amount)); rc = PR_Write( logFile, buf , amount ); if ( rc == -1 ) PR_LOG( lm, PR_LOG_ERROR, ("RecordTraceEntries: PR_Write() failed. Error: %ld", PR_GetError() )); else if ( rc != amount ) PR_LOG( lm, PR_LOG_ERROR, ("RecordTraceEntries: PR_Write() Tried to write: %ld, Wrote: %ld", amount, rc)); else PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: PR_Write(): Buffer: %p, bytes: %ld", buf, amount)); return; } /* end WriteTraceSegment() */ /* ** */ PR_IMPLEMENT(void) PR_RecordTraceEntries( void ) { PRFileDesc *logFile; PRInt32 lostSegments; PRInt32 currentSegment = 0; void *buf; PRBool doWrite; logFile = InitializeRecording(); if ( logFile == NULL ) { PR_LOG( lm, PR_LOG_DEBUG, ("PR_RecordTraceEntries: Failed to initialize")); return; } /* Do this until told to stop */ while ( logState != LogStop ) { PR_Lock( logLock ); while ( (logCount == 0) && ( logOrder == logState ) ) PR_WaitCondVar( logCVar, PR_INTERVAL_NO_TIMEOUT ); /* Handle state transitions */ if ( logOrder != logState ) ProcessOrders(); /* recalculate local controls */ if ( logCount ) { lostSegments = logCount - logSegments; if ( lostSegments > 0 ) { logLostData += ( logCount - logSegments ); logCount = (logCount % logSegments); currentSegment = logCount; PR_LOG( lm, PR_LOG_DEBUG, ("PR_RecordTraceEntries: LostData segments: %ld", logLostData)); } else { logCount--; } buf = tBuf + ( logEntriesPerSegment * currentSegment ); if (++currentSegment >= logSegments ) currentSegment = 0; doWrite = PR_TRUE; } else doWrite = PR_FALSE; PR_Unlock( logLock ); if ( doWrite == PR_TRUE ) { if ( localState != LogSuspend ) WriteTraceSegment( logFile, buf, logSegSize ); else PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: PR_Write(): is suspended" )); } } /* end while(logState...) */ PR_Close( logFile ); PR_LOG( lm, PR_LOG_DEBUG, ("RecordTraceEntries: exiting")); return; } /* end PR_RecordTraceEntries() */ /* ** */ PR_IMPLEMENT(PRIntn) PR_GetTraceEntries( PRTraceEntry *buffer, /* where to write output */ PRInt32 count, /* number to get */ PRInt32 *found /* number you got */ ) { PRInt32 rc; PRInt32 copied = 0; PR_Lock( traceLock ); /* ** Depending on where the LastSeen and Next indices are, ** copy the trace buffer in one or two pieces. */ PR_LOG( lm, PR_LOG_ERROR, ("PR_GetTraceEntries: Next: %ld, LastSeen: %ld", next, fetchLastSeen)); if ( fetchLastSeen <= next ) { while (( count-- > 0 ) && (fetchLastSeen < next )) { *(buffer + copied++) = *(tBuf + fetchLastSeen++); } PR_LOG( lm, PR_LOG_ERROR, ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen)); } else /* copy in 2 parts */ { while ( count-- > 0 && fetchLastSeen <= last ) { *(buffer + copied++) = *(tBuf + fetchLastSeen++); } fetchLastSeen = 0; PR_LOG( lm, PR_LOG_ERROR, ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen)); while ( count-- > 0 && fetchLastSeen < next ) { *(buffer + copied++) = *(tBuf + fetchLastSeen++); } PR_LOG( lm, PR_LOG_ERROR, ("PR_GetTraceEntries: Copied: %ld, LastSeen: %ld", copied, fetchLastSeen)); } *found = copied; rc = ( fetchLostData == PR_TRUE )? 1 : 0; fetchLostData = PR_FALSE; PR_Unlock( traceLock ); return rc; } /* end PR_GetTraceEntries() */ /* end prtrace.c */ nspr-4.11/nspr/pr/src/nspr.def0000644000000000000000000002234012623070344014405 0ustar 00000000000000;+# ;+# This Source Code Form is subject to the terms of the Mozilla Public ;+# License, v. 2.0. If a copy of the MPL was not distributed with this ;+# file, You can obtain one at http://mozilla.org/MPL/2.0/. ;+# ;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS ;+# 1. For all unix platforms, the string ";-" means "remove this line" ;+# 2. For all unix platforms, the string " DATA " will be removed from any ;+# line on which it occurs. ;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. ;+# On AIX, lines containing ";+" will be removed. ;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. ;+# 5. For all unix platforms, after the above processing has taken place, ;+# all characters after the first ";" on the line will be removed. ;+# And for AIX, the first ";" will also be removed. ;+# This file is passed directly to windows. Since ';' is a comment, all UNIX ;+# directives are hidden behind ";", ";+", and ";-" ;+# ;+NSPR_4.0 { ;+ global: LIBRARY nspr4 ;- EXPORTS ;- LL_MaxInt; LL_MinInt; LL_Zero; PR_Abort; PR_AddToCounter; PR_Accept; PR_AcceptRead; PR_Access; PR_AddWaitFileDesc; PR_AllocFileDesc; PR_Assert; PR_AtomicAdd; PR_AtomicDecrement; PR_AtomicIncrement; PR_AtomicSet; PR_AttachSharedMemory; PR_AttachThread; PR_Available; PR_Available64; PR_Bind; PR_BlockClockInterrupts; PR_BlockInterrupt; PR_CEnterMonitor; PR_CExitMonitor; PR_CNotify; PR_CNotifyAll; PR_CSetOnMonitorRecycle; PR_CWait; PR_CallOnce; PR_Calloc; PR_CancelJob; PR_CancelWaitFileDesc; PR_CancelWaitGroup; PR_CeilingLog2; PR_ChangeFileDescNativeHandle; PR_Cleanup; PR_ClearInterrupt; PR_ClearThreadGCAble; PR_Close; PR_CloseDir; PR_CloseFileMap; PR_CloseSemaphore; PR_CloseSharedMemory; PR_Connect; PR_CreateCounter; PR_ConvertIPv4AddrToIPv6; PR_CreateAlarm; PR_CreateFileMap; PR_CreateIOLayerStub; PR_CreateOrderedLock; PR_CreateMWaitEnumerator; PR_CreatePipe; PR_CreateProcess; PR_CreateProcessDetached; PR_CreateSocketPollFd; PR_CreateStack; PR_CreateThread; PR_CreateThreadGCAble; PR_CreateTrace; PR_CreateThreadPool; PR_DecrementCounter; PR_CreateWaitGroup; PR_Delete; PR_DeleteSemaphore; PR_DeleteSharedMemory; PR_DestroyAlarm; PR_DestroyCounter; PR_DestroyCondVar; PR_DestroyLock; PR_DestroyMWaitEnumerator; PR_DestroyOrderedLock; PR_DestroyMonitor; PR_DestroyPollableEvent; PR_DestroyProcessAttr; PR_DestroyRWLock; PR_DestroySem; PR_DestroySocketPollFd; PR_DestroyTrace; PR_DestroyStack; PR_DestroyWaitGroup; PR_DetachProcess; PR_DetachSharedMemory; PR_DetachThread; PR_DisableClockInterrupts; PR_EnableClockInterrupts; PR_EnterMonitor; PR_EnumerateHostEnt; PR_EnumerateThreads; PR_EnumerateWaitGroup; PR_ErrorInstallCallback; PR_ErrorInstallTable; PR_ErrorLanguages; PR_ErrorToName; PR_ErrorToString; PR_ExitMonitor; PR_ExplodeTime; PR_ExportFileMapAsString; PR_FD_CLR; PR_FD_ISSET; PR_FD_NCLR; PR_FD_NISSET; PR_FD_NSET; PR_FD_SET; PR_FD_ZERO; PR_FileDesc2NativeHandle; PR_FindSymbol; PR_FindSymbolAndLibrary; PR_FloorLog2; PR_FormatTime; PR_FindNextCounterQname; PR_FindNextCounterRname; PR_FindNextTraceQname; PR_FindNextTraceRname; PR_FormatTimeUSEnglish; PR_Free; PR_FreeLibraryName; PR_GMTParameters; PR_GetConnectStatus; PR_GetCurrentThread; PR_GetDefaultIOMethods; PR_GetDescType; PR_GetDirectorySeparator; PR_GetCounter; PR_GetCounterHandleFromName; PR_GetCounterNameFromHandle; PR_GetDirectorySepartor; PR_GetEnv; PR_GetError; PR_GetErrorText; PR_GetErrorTextLength; PR_GetFileInfo; PR_GetFileInfo64; PR_GetFileMethods; PR_GetGCRegisters; PR_GetHostByAddr; PR_GetHostByName; PR_GetIPNodeByName; PR_GetIdentitiesLayer; PR_GetInheritedFD; PR_GetInheritedFileMap; PR_GetLayersIdentity; PR_GetLibraryName; PR_GetLibraryPath; PR_GetMonitorEntryCount; PR_GetNameForIdentity; PR_GetOSError; PR_GetOpenFileInfo; PR_GetOpenFileInfo64; PR_GetPageShift; PR_GetPageSize; PR_GetPeerName; PR_GetPipeMethods; PR_GetProtoByName; PR_GetProtoByNumber; PR_GetRandomNoise; PR_GetSP; PR_GetSockName; PR_GetSocketOption; PR_GetSpecialFD; PR_GetStackSpaceLeft; PR_GetSysfdTableMax; PR_GetSystemInfo; PR_GetTCPMethods; PR_GetThreadAffinityMask; PR_GetThreadID; PR_GetThreadPriority; PR_GetThreadPrivate; PR_GetThreadScope; PR_GetThreadState; PR_GetThreadType; PR_GetUDPMethods; PR_GetUniqueIdentity; PR_ImplodeTime; PR_ImportFile; PR_ImportFileMapFromString; PR_ImportTCPSocket; PR_ImportUDPSocket; PR_GetTraceEntries; PR_GetTraceHandleFromName; PR_GetTraceNameFromHandle; PR_GetTraceOption; PR_Init; PR_Initialize; PR_InitializeNetAddr; PR_Initialized; PR_Interrupt; PR_IntervalNow; PR_IntervalToMicroseconds; PR_IntervalToMilliseconds; PR_IncrementCounter; PR_IntervalToSeconds; PR_IsNetAddrType; PR_JoinJob; PR_JoinThread; PR_JoinThreadPool; PR_KillProcess; PR_Listen; PR_LoadLibrary; PR_LoadLibraryWithFlags; PR_LoadStaticLibrary; PR_LocalTimeParameters; PR_Lock; PR_LockFile; PR_LogFlush; PR_LogPrint; PR_MakeDir; PR_Malloc; PR_MemMap; PR_MemUnmap; PR_MicrosecondsToInterval; PR_MillisecondsToInterval; PR_LockOrderedLock; PR_MkDir; PR_NetAddrToString; PR_NewCondVar; PR_NewLock; PR_NewLogModule; PR_NewMonitor; PR_NewNamedMonitor; PR_NewPollableEvent; PR_NewProcessAttr; PR_NewRWLock; PR_NewSem; PR_NewTCPSocket; PR_NewTCPSocketPair; PR_NewThreadPrivateIndex; PR_NewUDPSocket; PR_NormalizeTime; PR_Notify; PR_NotifyAll; PR_NotifyAllCondVar; PR_NotifyCondVar; PR_Now; PR_Open; PR_OpenAnonFileMap; PR_OpenDir; PR_OpenFile; PR_OpenSemaphore; PR_OpenSharedMemory; PR_OpenTCPSocket; PR_OpenUDPSocket; PR_ParseTimeString; PR_Poll; PR_PopIOLayer; PR_PostSem; PR_PostSemaphore; PR_ProcessAttrSetCurrentDirectory; PR_ProcessAttrSetInheritableFD; PR_ProcessAttrSetInheritableFileMap; PR_ProcessAttrSetStdioRedirect; PR_ProcessExit; PR_PushIOLayer; PR_QueueJob; PR_QueueJob_Accept; PR_QueueJob_Connect; PR_QueueJob_Read; PR_QueueJob_Timer; PR_QueueJob_Write; PR_RWLock_Rlock; PR_RWLock_Unlock; PR_RWLock_Wlock; PR_Read; PR_ReadDir; PR_Realloc; PR_Recv; PR_RecvFrom; PR_Rename; PR_ResetAlarm; PR_ResetProcessAttr; PR_ResumeAll; PR_RmDir; PR_ScanStackPointers; PR_RecordTraceEntries; PR_SecondsToInterval; PR_Seek; PR_Seek64; PR_Select; PR_Send; PR_SendFile; PR_SendTo; PR_SetAlarm; PR_SetConcurrency; PR_SetError; PR_SetErrorText; PR_SetFDCacheSize; PR_SetFDInheritable; PR_SetLibraryPath; PR_SetLogBuffering; PR_SetLogFile; PR_SetNetAddr; PR_SetPollableEvent; PR_SetSocketOption; PR_SetCounter; PR_SetStdioRedirect; PR_SetSysfdTableSize; PR_SetThreadAffinityMask; PR_SetThreadDumpProc; PR_SetThreadGCAble; PR_SetThreadPriority; PR_SetThreadPrivate; PR_SetThreadRecycleMode; PR_Shutdown; PR_ShutdownThreadPool; PR_Sleep; PR_Socket; PR_StackPop; PR_StackPush; PR_Stat; PR_StringToNetAddr; PR_SuspendAll; PR_Sync; PR_TLockFile; PR_ThreadScanStackPointers; PR_SetTraceOption; PR_TicksPerSecond; PR_TransmitFile; PR_USPacificTimeParameters; PR_UnblockClockInterrupts; PR_UnblockInterrupt; PR_UnloadLibrary; PR_SubtractFromCounter; PR_Unlock; PR_UnlockFile; PR_VersionCheck; PR_Wait; PR_WaitCondVar; PR_WaitForPollableEvent; PR_Trace; PR_WaitProcess; PR_WaitRecvReady; PR_WaitSem; PR_WaitSemaphore; PR_Write; PR_Writev; PR_Yield; PR_UnlockOrderedLock; PR_cnvtf; PR_dtoa; PR_fprintf; PR_htonl; PR_htonll; PR_htons; PR_ntohl; PR_ntohll; PR_ntohs; PR_smprintf; PR_smprintf_free; PR_snprintf; PR_sprintf_append; PR_sscanf; PR_strtod; PR_sxprintf; PR_vfprintf; PR_vsmprintf; PR_vsnprintf; PR_vsprintf_append; PR_vsxprintf; PRP_DestroyNakedCondVar; PRP_NakedBroadcast; PRP_NakedNotify; PRP_NakedWait; PRP_NewNakedCondVar; PRP_TryLock; libVersionPoint; ;+ local: *; ;+}; ;+ ;+NSPRprivate { ;+ global: GetExecutionEnvironment; PT_FPrintStats; SetExecutionEnvironment; ;+ local: *; ;+}; ;+ ;+NSPR_4.1 { ;+ global: PR_ConnectContinue; PR_CreateIOLayer; PR_EmulateAcceptRead; PR_EmulateSendFile; PR_FindFunctionSymbol; PR_FindFunctionSymbolAndLibrary; PR_GetMemMapAlignment; PR_GetNumberOfProcessors; PR_ImportPipe; PR_SetEnv; ;+} NSPR_4.0; ;+ ;+NSPR_4.3 { ;+ global: LL_MaxUint; PR_CallOnceWithArg; PR_GetLibraryFilePathname; ;+} NSPR_4.1; ;+ ;+NSPR_4.4 { ;+ global: PR_GetPathSeparator; ;+} NSPR_4.3; ;+ ;+NSPR_4.5 { ;+ global: PR_EnumerateAddrInfo; PR_FreeAddrInfo; PR_GetAddrInfoByName; PR_GetCanonNameFromAddrInfo; ;+} NSPR_4.4; ;+ ;+NSPR_4.6 { ;+ global: PR_GetPhysicalMemorySize; ;+} NSPR_4.5; ;+NSPR_4.7 { ;+ global: PR_ParseTimeStringToExplodedTime; ;+} NSPR_4.6; ;+NSPR_4.8 { ;+ global: PR_AssertCurrentThreadOwnsLock; PR_AssertCurrentThreadInMonitor; ;+} NSPR_4.7; ;+NSPR_4.8.9 { ;+ global: PR_GetVersion; ;+} NSPR_4.8; ;+NSPR_4.9.2 { ;+ global: PR_GetThreadName; PR_SetCurrentThreadName; ;+} NSPR_4.8.9; ;+NSPR_4.10.3 { ;+ global: PR_SyncMemMap; ;+} NSPR_4.9.2; nspr-4.11/nspr/pr/src/nspr.rc0000644000000000000000000000366412623070344014263 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include #define MY_LIBNAME "nspr" #define MY_FILEDESCRIPTION "NSPR Library" #define STRINGIZE(x) #x #define STRINGIZE2(x) STRINGIZE(x) #define PR_VMAJOR_STR STRINGIZE2(PR_VMAJOR) #ifdef _DEBUG #define MY_DEBUG_STR " (debug)" #define MY_FILEFLAGS_1 VS_FF_DEBUG #else #define MY_DEBUG_STR "" #define MY_FILEFLAGS_1 0x0L #endif #if PR_BETA #define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE #else #define MY_FILEFLAGS_2 MY_FILEFLAGS_1 #endif #ifdef WINNT #define MY_FILEOS VOS_NT_WINDOWS32 #define MY_INTERNAL_NAME "lib" MY_LIBNAME PR_VMAJOR_STR #else #define MY_FILEOS VOS__WINDOWS32 #define MY_INTERNAL_NAME MY_LIBNAME PR_VMAJOR_STR #endif ///////////////////////////////////////////////////////////////////////////// // // Version-information resource // VS_VERSION_INFO VERSIONINFO FILEVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 PRODUCTVERSION PR_VMAJOR,PR_VMINOR,PR_VPATCH,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS MY_FILEFLAGS_2 FILEOS MY_FILEOS FILETYPE VFT_DLL FILESUBTYPE 0x0L // not used BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904B0" // Lang=US English, CharSet=Unicode BEGIN VALUE "CompanyName", "Mozilla Foundation\0" VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" VALUE "FileVersion", PR_VERSION "\0" VALUE "InternalName", MY_INTERNAL_NAME "\0" VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" VALUE "ProductName", "Netscape Portable Runtime\0" VALUE "ProductVersion", PR_VERSION "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END nspr-4.11/nspr/pr/src/os2extra.def0000644000000000000000000000110112623070344015162 0ustar 00000000000000; This Source Code Form is subject to the terms of the Mozilla Public ; License, v. 2.0. If a copy of the MPL was not distributed with this ; file, You can obtain one at http://mozilla.org/MPL/2.0/. ; ; Support plugins that were explicitly linked to the Visual Age ; version of nspr4.dll. ; PR_NewMonitor PR_EnterMonitor PR_ExitMonitor PR_GetCurrentThread PR_AttachThread PR_DetachThread ; ; Exception handler functions that are used by nsAppRunner.cpp ; _PR_OS2_SetFloatExcpHandler _PR_OS2_UnsetFloatExcpHandler nspr-4.11/nspr/pr/src/prvrsion.c0000644000000000000000000000614612623070344014777 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include "prvrsion.h" /************************************************************************/ /**************************IDENTITY AND VERSIONING***********************/ /************************************************************************/ #include "_pr_bld.h" #if !defined(_BUILD_TIME) #ifdef HAVE_LONG_LONG #define _BUILD_TIME 0 #else #define _BUILD_TIME {0, 0} #endif #endif #if !defined(_BUILD_STRING) #define _BUILD_STRING "" #endif #if !defined(_PRODUCTION) #define _PRODUCTION "" #endif #if defined(DEBUG) #define _DEBUG_STRING " (debug)" #else #define _DEBUG_STRING "" #endif /* * A trick to expand the PR_VMAJOR macro before concatenation. */ #define CONCAT(x, y) x ## y #define CONCAT2(x, y) CONCAT(x, y) #define VERSION_DESC_NAME CONCAT2(prVersionDescription_libnspr, PR_VMAJOR) PRVersionDescription VERSION_DESC_NAME = { /* version */ 2, /* this is the only one supported */ /* buildTime */ _BUILD_TIME, /* usecs since midnight 1/1/1970 GMT */ /* buildTimeString */ _BUILD_STRING, /* ditto, but human readable */ /* vMajor */ PR_VMAJOR, /* NSPR's version number */ /* vMinor */ PR_VMINOR, /* and minor version */ /* vPatch */ PR_VPATCH, /* and patch */ /* beta */ PR_BETA, /* beta build boolean */ #if defined(DEBUG) /* debug */ PR_TRUE, /* a debug build */ #else /* debug */ PR_FALSE, /* an optomized build */ #endif /* special */ PR_FALSE, /* they're all special, but ... */ /* filename */ _PRODUCTION, /* the produced library name */ /* description */ "Portable runtime", /* what we are */ /* security */ "N/A", /* not applicable here */ /* copywrite */ "Copyright (c) 1998 Netscape Communications Corporation. All Rights Reserved", /* comment */ "License information: http://www.mozilla.org/MPL/", /* specialString */ "" }; #ifdef XP_UNIX /* * Version information for the 'ident' and 'what commands * * NOTE: the first component of the concatenated rcsid string * must not end in a '$' to prevent rcs keyword substitution. */ static char rcsid[] = "$Header: NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING " $"; static char sccsid[] = "@(#)NSPR " PR_VERSION _DEBUG_STRING " " _BUILD_STRING; #endif /* XP_UNIX */ PR_IMPLEMENT(const PRVersionDescription*) libVersionPoint(void) { #ifdef XP_UNIX /* * Add dummy references to rcsid and sccsid to prevent them * from being optimized away as unused variables. */ const char *dummy; dummy = rcsid; dummy = sccsid; #endif return &VERSION_DESC_NAME; } /* versionEntryPointType */ /* prvrsion.c */ nspr-4.11/nspr/pr/src/pthreads/.cvsignore0000644000000000000000000000001112623070344016544 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/pthreads/Makefile.in0000644000000000000000000000120612623070344016620 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = \ ptio.c \ ptsynch.c \ ptthread.c \ ptmisc.c \ $(NULL) TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/pthreads/ptio.c0000644000000000000000000044420012623070344015677 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: ptio.c ** Descritpion: Implemenation of I/O methods for pthreads */ #if defined(_PR_PTHREADS) #if defined(_PR_POLL_WITH_SELECT) #if !(defined(HPUX) && defined(_USE_BIG_FDS)) /* set fd limit for select(), before including system header files */ #define FD_SETSIZE (16 * 1024) #endif #endif #include #include /* for memset() */ #include #include #include #include #include #include #include #include #include #if defined(DARWIN) #include /* for uname */ #endif #if defined(SOLARIS) || defined(UNIXWARE) #include /* to pick up FIONREAD */ #endif #ifdef _PR_POLL_AVAILABLE #include #endif #ifdef AIX /* To pick up sysconf() */ #include #include /* for dlopen */ #else /* To pick up getrlimit() etc. */ #include #include #endif #ifdef SOLARIS /* * Define HAVE_SENDFILEV if the system has the sendfilev() system call. * Code built this way won't run on a system without sendfilev(). * We can define HAVE_SENDFILEV by default when the minimum release * of Solaris that NSPR supports has sendfilev(). */ #ifdef HAVE_SENDFILEV #include #define SOLARIS_SENDFILEV(a, b, c, d) sendfilev((a), (b), (c), (d)) #else #include /* for dlopen */ /* * Match the definitions in . */ typedef struct sendfilevec { int sfv_fd; /* input fd */ uint_t sfv_flag; /* flags */ off_t sfv_off; /* offset to start reading from */ size_t sfv_len; /* amount of data */ } sendfilevec_t; #define SFV_FD_SELF (-2) /* * extern ssize_t sendfilev(int, const struct sendfilevec *, int, size_t *); */ static ssize_t (*pt_solaris_sendfilev_fptr)() = NULL; #define SOLARIS_SENDFILEV(a, b, c, d) \ (*pt_solaris_sendfilev_fptr)((a), (b), (c), (d)) #endif /* HAVE_SENDFILEV */ #endif /* SOLARIS */ /* * The send_file() system call is available in AIX 4.3.2 or later. * If this file is compiled on an older AIX system, it attempts to * look up the send_file symbol at run time to determine whether * we can use the faster PR_SendFile/PR_TransmitFile implementation based on * send_file(). On AIX 4.3.2 or later, we can safely skip this * runtime function dispatching and just use the send_file based * implementation. */ #ifdef AIX #ifdef SF_CLOSE #define HAVE_SEND_FILE #endif #ifdef HAVE_SEND_FILE #define AIX_SEND_FILE(a, b, c) send_file(a, b, c) #else /* HAVE_SEND_FILE */ /* * The following definitions match those in * on AIX 4.3.2. */ /* * Structure for the send_file() system call */ struct sf_parms { /* --------- header parms ---------- */ void *header_data; /* Input/Output. Points to header buf */ uint_t header_length; /* Input/Output. Length of the header */ /* --------- file parms ------------ */ int file_descriptor; /* Input. File descriptor of the file */ unsigned long long file_size; /* Output. Size of the file */ unsigned long long file_offset; /* Input/Output. Starting offset */ long long file_bytes; /* Input/Output. no. of bytes to send */ /* --------- trailer parms --------- */ void *trailer_data; /* Input/Output. Points to trailer buf */ uint_t trailer_length; /* Input/Output. Length of the trailer */ /* --------- return info ----------- */ unsigned long long bytes_sent; /* Output. no. of bytes sent */ }; /* * Flags for the send_file() system call */ #define SF_CLOSE 0x00000001 /* close the socket after completion */ #define SF_REUSE 0x00000002 /* reuse socket. not supported */ #define SF_DONT_CACHE 0x00000004 /* don't apply network buffer cache */ #define SF_SYNC_CACHE 0x00000008 /* sync/update network buffer cache */ /* * prototype: size_t send_file(int *, struct sf_parms *, uint_t); */ static ssize_t (*pt_aix_sendfile_fptr)() = NULL; #define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c) #endif /* HAVE_SEND_FILE */ #endif /* AIX */ #ifdef LINUX #include #endif #include "primpl.h" #ifdef HAVE_NETINET_TCP_H #include /* TCP_NODELAY, TCP_MAXSEG */ #endif #ifdef LINUX /* TCP_CORK is not defined in on Red Hat Linux 6.0 */ #ifndef TCP_CORK #define TCP_CORK 3 #endif #endif #ifdef _PR_IPV6_V6ONLY_PROBE static PRBool _pr_ipv6_v6only_on_by_default; #endif #if (defined(HPUX) && !defined(HPUX10_30) && !defined(HPUX11)) #define _PRSelectFdSetArg_t int * #elif defined(AIX4_1) #define _PRSelectFdSetArg_t void * #elif defined(IRIX) || (defined(AIX) && !defined(AIX4_1)) \ || defined(OSF1) || defined(SOLARIS) \ || defined(HPUX10_30) || defined(HPUX11) \ || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \ || defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) \ || defined(BSDI) || defined(NTO) || defined(DARWIN) \ || defined(UNIXWARE) || defined(RISCOS) || defined(SYMBIAN) #define _PRSelectFdSetArg_t fd_set * #else #error "Cannot determine architecture" #endif #if defined(SOLARIS) #ifndef PROTO_SDP /* on solaris, SDP is a new type of protocol */ #define PROTO_SDP 257 #endif #define _PR_HAVE_SDP #elif defined(LINUX) #ifndef AF_INET_SDP /* on linux, SDP is a new type of address family */ #define AF_INET_SDP 27 #endif #define _PR_HAVE_SDP #endif /* LINUX */ static PRFileDesc *pt_SetMethods( PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported); static PRLock *_pr_flock_lock; /* For PR_LockFile() etc. */ static PRCondVar *_pr_flock_cv; /* For PR_LockFile() etc. */ static PRLock *_pr_rename_lock; /* For PR_Rename() */ /**************************************************************************/ /* These two functions are only used in assertions. */ #if defined(DEBUG) PRBool IsValidNetAddr(const PRNetAddr *addr) { if ((addr != NULL) && (addr->raw.family != AF_UNIX) && (addr->raw.family != PR_AF_INET6) && (addr->raw.family != AF_INET)) { return PR_FALSE; } return PR_TRUE; } static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len) { /* * The definition of the length of a Unix domain socket address * is not uniform, so we don't check it. */ if ((addr != NULL) && (addr->raw.family != AF_UNIX) && (PR_NETADDR_SIZE(addr) != addr_len)) { #if defined(LINUX) && __GLIBC__ == 2 && __GLIBC_MINOR__ == 1 /* * In glibc 2.1, struct sockaddr_in6 is 24 bytes. In glibc 2.2 * and in the 2.4 kernel, struct sockaddr_in6 has the scope_id * field and is 28 bytes. It is possible for socket functions * to return an addr_len greater than sizeof(struct sockaddr_in6). * We need to allow that. (Bugzilla bug #77264) */ if ((PR_AF_INET6 == addr->raw.family) && (sizeof(addr->ipv6) == addr_len)) { return PR_TRUE; } #endif return PR_FALSE; } return PR_TRUE; } #endif /* DEBUG */ /*****************************************************************************/ /************************* I/O Continuation machinery ************************/ /*****************************************************************************/ /* * The polling interval defines the maximum amount of time that a thread * might hang up before an interrupt is noticed. */ #define PT_DEFAULT_POLL_MSEC 5000 #if defined(_PR_POLL_WITH_SELECT) #define PT_DEFAULT_SELECT_SEC (PT_DEFAULT_POLL_MSEC/PR_MSEC_PER_SEC) #define PT_DEFAULT_SELECT_USEC \ ((PT_DEFAULT_POLL_MSEC % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC) #endif /* * pt_SockLen is the type for the length of a socket address * structure, used in the address length argument to bind, * connect, accept, getsockname, getpeername, etc. Posix.1g * defines this type as socklen_t. It is size_t or int on * most current systems. */ #if defined(HAVE_SOCKLEN_T) \ || (defined(__GLIBC__) && __GLIBC__ >= 2) typedef socklen_t pt_SockLen; #elif (defined(AIX) && !defined(AIX4_1)) typedef PRSize pt_SockLen; #else typedef PRIntn pt_SockLen; #endif typedef struct pt_Continuation pt_Continuation; typedef PRBool (*ContinuationFn)(pt_Continuation *op, PRInt16 revents); typedef enum pr_ContuationStatus { pt_continuation_pending, pt_continuation_done } pr_ContuationStatus; struct pt_Continuation { /* The building of the continuation operation */ ContinuationFn function; /* what function to continue */ union { PRIntn osfd; } arg1; /* #1 - the op's fd */ union { void* buffer; } arg2; /* #2 - primary transfer buffer */ union { PRSize amount; /* #3 - size of 'buffer', or */ pt_SockLen *addr_len; /* - length of address */ #ifdef HPUX11 /* * For sendfile() */ struct file_spec { off_t offset; /* offset in file to send */ size_t nbytes; /* length of file data to send */ size_t st_size; /* file size */ } file_spec; #endif } arg3; union { PRIntn flags; } arg4; /* #4 - read/write flags */ union { PRNetAddr *addr; } arg5; /* #5 - send/recv address */ #ifdef HPUX11 /* * For sendfile() */ int filedesc; /* descriptor of file to send */ int nbytes_to_send; /* size of header and file */ #endif /* HPUX11 */ #ifdef SOLARIS /* * For sendfilev() */ int nbytes_to_send; /* size of header and file */ #endif /* SOLARIS */ #ifdef LINUX /* * For sendfile() */ int in_fd; /* descriptor of file to send */ off_t offset; size_t count; #endif /* LINUX */ PRIntervalTime timeout; /* client (relative) timeout */ PRInt16 event; /* flags for poll()'s events */ /* ** The representation and notification of the results of the operation. ** These function can either return an int return code or a pointer to ** some object. */ union { PRSize code; void *object; } result; PRIntn syserrno; /* in case it failed, why (errno) */ pr_ContuationStatus status; /* the status of the operation */ }; #if defined(DEBUG) PTDebug pt_debug; /* this is shared between several modules */ PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) { PTDebug stats; char buffer[100]; PRExplodedTime tod; PRInt64 elapsed, aMil; stats = pt_debug; /* a copy */ PR_ExplodeTime(stats.timeStarted, PR_LocalTimeParameters, &tod); (void)PR_FormatTime(buffer, sizeof(buffer), "%T", &tod); LL_SUB(elapsed, PR_Now(), stats.timeStarted); LL_I2L(aMil, 1000000); LL_DIV(elapsed, elapsed, aMil); if (NULL != msg) PR_fprintf(debug_out, "%s", msg); PR_fprintf( debug_out, "\tstarted: %s[%lld]\n", buffer, elapsed); PR_fprintf( debug_out, "\tlocks [created: %u, destroyed: %u]\n", stats.locks_created, stats.locks_destroyed); PR_fprintf( debug_out, "\tlocks [acquired: %u, released: %u]\n", stats.locks_acquired, stats.locks_released); PR_fprintf( debug_out, "\tcvars [created: %u, destroyed: %u]\n", stats.cvars_created, stats.cvars_destroyed); PR_fprintf( debug_out, "\tcvars [notified: %u, delayed_delete: %u]\n", stats.cvars_notified, stats.delayed_cv_deletes); } /* PT_FPrintStats */ #else PR_IMPLEMENT(void) PT_FPrintStats(PRFileDesc *debug_out, const char *msg) { /* do nothing */ } /* PT_FPrintStats */ #endif /* DEBUG */ #if defined(_PR_POLL_WITH_SELECT) /* * OSF1 and HPUX report the POLLHUP event for a socket when the * shutdown(SHUT_WR) operation is called for the remote end, even though * the socket is still writeable. Use select(), instead of poll(), to * workaround this problem. */ static void pt_poll_now_with_select(pt_Continuation *op) { PRInt32 msecs; fd_set rd, wr, *rdp, *wrp; struct timeval tv; PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRThread *self = PR_GetCurrentThread(); PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout); PR_ASSERT(op->arg1.osfd < FD_SETSIZE); switch (op->timeout) { case PR_INTERVAL_NO_TIMEOUT: tv.tv_sec = PT_DEFAULT_SELECT_SEC; tv.tv_usec = PT_DEFAULT_SELECT_USEC; do { PRIntn rv; if (op->event & POLLIN) { FD_ZERO(&rd); FD_SET(op->arg1.osfd, &rd); rdp = &rd; } else rdp = NULL; if (op->event & POLLOUT) { FD_ZERO(&wr); FD_SET(op->arg1.osfd, &wr); wrp = ≀ } else wrp = NULL; rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv); if (_PT_THREAD_INTERRUPTED(self)) { self->state &= ~PT_THREAD_ABORTED; op->result.code = -1; op->syserrno = EINTR; op->status = pt_continuation_done; return; } if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN))) continue; /* go around the loop again */ if (rv > 0) { PRInt16 revents = 0; if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd)) revents |= POLLIN; if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr)) revents |= POLLOUT; if (op->function(op, revents)) op->status = pt_continuation_done; } else if (rv == -1) { op->result.code = -1; op->syserrno = errno; op->status = pt_continuation_done; } /* else, select timed out */ } while (pt_continuation_done != op->status); break; default: now = epoch = PR_IntervalNow(); remaining = op->timeout; do { PRIntn rv; if (op->event & POLLIN) { FD_ZERO(&rd); FD_SET(op->arg1.osfd, &rd); rdp = &rd; } else rdp = NULL; if (op->event & POLLOUT) { FD_ZERO(&wr); FD_SET(op->arg1.osfd, &wr); wrp = ≀ } else wrp = NULL; wait_for_remaining = PR_TRUE; msecs = (PRInt32)PR_IntervalToMilliseconds(remaining); if (msecs > PT_DEFAULT_POLL_MSEC) { wait_for_remaining = PR_FALSE; msecs = PT_DEFAULT_POLL_MSEC; } tv.tv_sec = msecs/PR_MSEC_PER_SEC; tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC; rv = select(op->arg1.osfd + 1, rdp, wrp, NULL, &tv); if (_PT_THREAD_INTERRUPTED(self)) { self->state &= ~PT_THREAD_ABORTED; op->result.code = -1; op->syserrno = EINTR; op->status = pt_continuation_done; return; } if (rv > 0) { PRInt16 revents = 0; if ((op->event & POLLIN) && FD_ISSET(op->arg1.osfd, &rd)) revents |= POLLIN; if ((op->event & POLLOUT) && FD_ISSET(op->arg1.osfd, &wr)) revents |= POLLOUT; if (op->function(op, revents)) op->status = pt_continuation_done; } else if ((rv == 0) || ((errno == EINTR) || (errno == EAGAIN))) { if (rv == 0) { /* select timed out */ if (wait_for_remaining) now += remaining; else now += PR_MillisecondsToInterval(msecs); } else now = PR_IntervalNow(); elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= op->timeout) { op->result.code = -1; op->syserrno = ETIMEDOUT; op->status = pt_continuation_done; } else remaining = op->timeout - elapsed; } else { op->result.code = -1; op->syserrno = errno; op->status = pt_continuation_done; } } while (pt_continuation_done != op->status); break; } } /* pt_poll_now_with_select */ #endif /* _PR_POLL_WITH_SELECT */ static void pt_poll_now(pt_Continuation *op) { PRInt32 msecs; PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRThread *self = PR_GetCurrentThread(); PR_ASSERT(PR_INTERVAL_NO_WAIT != op->timeout); #if defined (_PR_POLL_WITH_SELECT) /* * If the fd is small enough call the select-based poll operation */ if (op->arg1.osfd < FD_SETSIZE) { pt_poll_now_with_select(op); return; } #endif switch (op->timeout) { case PR_INTERVAL_NO_TIMEOUT: msecs = PT_DEFAULT_POLL_MSEC; do { PRIntn rv; struct pollfd tmp_pfd; tmp_pfd.revents = 0; tmp_pfd.fd = op->arg1.osfd; tmp_pfd.events = op->event; rv = poll(&tmp_pfd, 1, msecs); if (_PT_THREAD_INTERRUPTED(self)) { self->state &= ~PT_THREAD_ABORTED; op->result.code = -1; op->syserrno = EINTR; op->status = pt_continuation_done; return; } if ((-1 == rv) && ((errno == EINTR) || (errno == EAGAIN))) continue; /* go around the loop again */ if (rv > 0) { PRInt16 events = tmp_pfd.events; PRInt16 revents = tmp_pfd.revents; if ((revents & POLLNVAL) /* busted in all cases */ || ((events & POLLOUT) && (revents & POLLHUP))) /* write op & hup */ { op->result.code = -1; if (POLLNVAL & revents) op->syserrno = EBADF; else if (POLLHUP & revents) op->syserrno = EPIPE; op->status = pt_continuation_done; } else { if (op->function(op, revents)) op->status = pt_continuation_done; } } else if (rv == -1) { op->result.code = -1; op->syserrno = errno; op->status = pt_continuation_done; } /* else, poll timed out */ } while (pt_continuation_done != op->status); break; default: now = epoch = PR_IntervalNow(); remaining = op->timeout; do { PRIntn rv; struct pollfd tmp_pfd; tmp_pfd.revents = 0; tmp_pfd.fd = op->arg1.osfd; tmp_pfd.events = op->event; wait_for_remaining = PR_TRUE; msecs = (PRInt32)PR_IntervalToMilliseconds(remaining); if (msecs > PT_DEFAULT_POLL_MSEC) { wait_for_remaining = PR_FALSE; msecs = PT_DEFAULT_POLL_MSEC; } rv = poll(&tmp_pfd, 1, msecs); if (_PT_THREAD_INTERRUPTED(self)) { self->state &= ~PT_THREAD_ABORTED; op->result.code = -1; op->syserrno = EINTR; op->status = pt_continuation_done; return; } if (rv > 0) { PRInt16 events = tmp_pfd.events; PRInt16 revents = tmp_pfd.revents; if ((revents & POLLNVAL) /* busted in all cases */ || ((events & POLLOUT) && (revents & POLLHUP))) /* write op & hup */ { op->result.code = -1; if (POLLNVAL & revents) op->syserrno = EBADF; else if (POLLHUP & revents) op->syserrno = EPIPE; op->status = pt_continuation_done; } else { if (op->function(op, revents)) { op->status = pt_continuation_done; } } } else if ((rv == 0) || ((errno == EINTR) || (errno == EAGAIN))) { if (rv == 0) /* poll timed out */ { if (wait_for_remaining) now += remaining; else now += PR_MillisecondsToInterval(msecs); } else now = PR_IntervalNow(); elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= op->timeout) { op->result.code = -1; op->syserrno = ETIMEDOUT; op->status = pt_continuation_done; } else remaining = op->timeout - elapsed; } else { op->result.code = -1; op->syserrno = errno; op->status = pt_continuation_done; } } while (pt_continuation_done != op->status); break; } } /* pt_poll_now */ static PRIntn pt_Continue(pt_Continuation *op) { op->status = pt_continuation_pending; /* set default value */ /* * let each thread call poll directly */ pt_poll_now(op); PR_ASSERT(pt_continuation_done == op->status); return op->result.code; } /* pt_Continue */ /*****************************************************************************/ /*********************** specific continuation functions *********************/ /*****************************************************************************/ static PRBool pt_connect_cont(pt_Continuation *op, PRInt16 revents) { op->syserrno = _MD_unix_get_nonblocking_connect_error(op->arg1.osfd); if (op->syserrno != 0) { op->result.code = -1; } else { op->result.code = 0; } return PR_TRUE; /* this one is cooked */ } /* pt_connect_cont */ static PRBool pt_accept_cont(pt_Continuation *op, PRInt16 revents) { op->syserrno = 0; op->result.code = accept( op->arg1.osfd, op->arg2.buffer, op->arg3.addr_len); if (-1 == op->result.code) { op->syserrno = errno; if (EWOULDBLOCK == errno || EAGAIN == errno || ECONNABORTED == errno) return PR_FALSE; /* do nothing - this one ain't finished */ } return PR_TRUE; } /* pt_accept_cont */ static PRBool pt_read_cont(pt_Continuation *op, PRInt16 revents) { /* * Any number of bytes will complete the operation. It need * not (and probably will not) satisfy the request. The only * error we continue is EWOULDBLOCK|EAGAIN. */ op->result.code = read( op->arg1.osfd, op->arg2.buffer, op->arg3.amount); op->syserrno = errno; return ((-1 == op->result.code) && (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ? PR_FALSE : PR_TRUE; } /* pt_read_cont */ static PRBool pt_recv_cont(pt_Continuation *op, PRInt16 revents) { /* * Any number of bytes will complete the operation. It need * not (and probably will not) satisfy the request. The only * error we continue is EWOULDBLOCK|EAGAIN. */ #if defined(SOLARIS) if (0 == op->arg4.flags) op->result.code = read( op->arg1.osfd, op->arg2.buffer, op->arg3.amount); else op->result.code = recv( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags); #else op->result.code = recv( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags); #endif op->syserrno = errno; return ((-1 == op->result.code) && (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ? PR_FALSE : PR_TRUE; } /* pt_recv_cont */ static PRBool pt_send_cont(pt_Continuation *op, PRInt16 revents) { PRIntn bytes; #if defined(SOLARIS) PRInt32 tmp_amount = op->arg3.amount; #endif /* * We want to write the entire amount out, no matter how many * tries it takes. Keep advancing the buffer and the decrementing * the amount until the amount goes away. Return the total bytes * (which should be the original amount) when finished (or an * error). */ #if defined(SOLARIS) retry: bytes = write(op->arg1.osfd, op->arg2.buffer, tmp_amount); #else bytes = send( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags); #endif op->syserrno = errno; #if defined(SOLARIS) /* * The write system call has been reported to return the ERANGE error * on occasion. Try to write in smaller chunks to workaround this bug. */ if ((bytes == -1) && (op->syserrno == ERANGE)) { if (tmp_amount > 1) { tmp_amount = tmp_amount/2; /* half the bytes */ goto retry; } } #endif if (bytes >= 0) /* this is progress */ { char *bp = (char*)op->arg2.buffer; bp += bytes; /* adjust the buffer pointer */ op->arg2.buffer = bp; op->result.code += bytes; /* accumulate the number sent */ op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; } else return PR_FALSE; } /* pt_send_cont */ static PRBool pt_write_cont(pt_Continuation *op, PRInt16 revents) { PRIntn bytes; /* * We want to write the entire amount out, no matter how many * tries it takes. Keep advancing the buffer and the decrementing * the amount until the amount goes away. Return the total bytes * (which should be the original amount) when finished (or an * error). */ bytes = write(op->arg1.osfd, op->arg2.buffer, op->arg3.amount); op->syserrno = errno; if (bytes >= 0) /* this is progress */ { char *bp = (char*)op->arg2.buffer; bp += bytes; /* adjust the buffer pointer */ op->arg2.buffer = bp; op->result.code += bytes; /* accumulate the number sent */ op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; } else return PR_FALSE; } /* pt_write_cont */ static PRBool pt_writev_cont(pt_Continuation *op, PRInt16 revents) { PRIntn bytes; struct iovec *iov = (struct iovec*)op->arg2.buffer; /* * Same rules as write, but continuing seems to be a bit more * complicated. As the number of bytes sent grows, we have to * redefine the vector we're pointing at. We might have to * modify an individual vector parms or we might have to eliminate * a pair altogether. */ bytes = writev(op->arg1.osfd, iov, op->arg3.amount); op->syserrno = errno; if (bytes >= 0) /* this is progress */ { PRIntn iov_index; op->result.code += bytes; /* accumulate the number sent */ for (iov_index = 0; iov_index < op->arg3.amount; ++iov_index) { /* how much progress did we make in the i/o vector? */ if (bytes < iov[iov_index].iov_len) { /* this element's not done yet */ char **bp = (char**)&(iov[iov_index].iov_base); iov[iov_index].iov_len -= bytes; /* there's that much left */ *bp += bytes; /* starting there */ break; /* go off and do that */ } bytes -= iov[iov_index].iov_len; /* that element's consumed */ } op->arg2.buffer = &iov[iov_index]; /* new start of array */ op->arg3.amount -= iov_index; /* and array length */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; } else return PR_FALSE; } /* pt_writev_cont */ static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents) { PRIntn bytes = sendto( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags, (struct sockaddr*)op->arg5.addr, PR_NETADDR_SIZE(op->arg5.addr)); op->syserrno = errno; if (bytes >= 0) /* this is progress */ { char *bp = (char*)op->arg2.buffer; bp += bytes; /* adjust the buffer pointer */ op->arg2.buffer = bp; op->result.code += bytes; /* accumulate the number sent */ op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; } else return PR_FALSE; } /* pt_sendto_cont */ static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents) { pt_SockLen addr_len = sizeof(PRNetAddr); op->result.code = recvfrom( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags, (struct sockaddr*)op->arg5.addr, &addr_len); op->syserrno = errno; return ((-1 == op->result.code) && (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ? PR_FALSE : PR_TRUE; } /* pt_recvfrom_cont */ #ifdef AIX static PRBool pt_aix_sendfile_cont(pt_Continuation *op, PRInt16 revents) { struct sf_parms *sf_struct = (struct sf_parms *) op->arg2.buffer; ssize_t rv; unsigned long long saved_file_offset; long long saved_file_bytes; saved_file_offset = sf_struct->file_offset; saved_file_bytes = sf_struct->file_bytes; sf_struct->bytes_sent = 0; if ((sf_struct->file_bytes > 0) && (sf_struct->file_size > 0)) PR_ASSERT((sf_struct->file_bytes + sf_struct->file_offset) <= sf_struct->file_size); rv = AIX_SEND_FILE(&op->arg1.osfd, sf_struct, op->arg4.flags); op->syserrno = errno; if (rv != -1) { op->result.code += sf_struct->bytes_sent; /* * A bug in AIX 4.3.2 prevents the 'file_bytes' field from * being updated. So, 'file_bytes' is maintained by NSPR to * avoid conflict when this bug is fixed in AIX, in the future. */ if (saved_file_bytes != -1) saved_file_bytes -= (sf_struct->file_offset - saved_file_offset); sf_struct->file_bytes = saved_file_bytes; } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { op->result.code = -1; } else { return PR_FALSE; } if (rv == 1) { /* more data to send */ return PR_FALSE; } return PR_TRUE; } #endif /* AIX */ #ifdef HPUX11 static PRBool pt_hpux_sendfile_cont(pt_Continuation *op, PRInt16 revents) { struct iovec *hdtrl = (struct iovec *) op->arg2.buffer; int count; count = sendfile(op->arg1.osfd, op->filedesc, op->arg3.file_spec.offset, op->arg3.file_spec.nbytes, hdtrl, op->arg4.flags); PR_ASSERT(count <= op->nbytes_to_send); op->syserrno = errno; if (count != -1) { op->result.code += count; } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { op->result.code = -1; } else { return PR_FALSE; } if (count != -1 && count < op->nbytes_to_send) { if (count < hdtrl[0].iov_len) { /* header not sent */ hdtrl[0].iov_base = ((char *) hdtrl[0].iov_base) + count; hdtrl[0].iov_len -= count; } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes)) { /* header sent, file not sent */ PRUint32 file_nbytes_sent = count - hdtrl[0].iov_len; hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; op->arg3.file_spec.offset += file_nbytes_sent; op->arg3.file_spec.nbytes -= file_nbytes_sent; } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes + hdtrl[1].iov_len)) { PRUint32 trailer_nbytes_sent = count - (hdtrl[0].iov_len + op->arg3.file_spec.nbytes); /* header sent, file sent, trailer not sent */ hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; /* * set file offset and len so that no more file data is * sent */ op->arg3.file_spec.offset = op->arg3.file_spec.st_size; op->arg3.file_spec.nbytes = 0; hdtrl[1].iov_base =((char *) hdtrl[1].iov_base)+ trailer_nbytes_sent; hdtrl[1].iov_len -= trailer_nbytes_sent; } op->nbytes_to_send -= count; return PR_FALSE; } return PR_TRUE; } #endif /* HPUX11 */ #ifdef SOLARIS static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents) { struct sendfilevec *vec = (struct sendfilevec *) op->arg2.buffer; size_t xferred; ssize_t count; count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred); op->syserrno = errno; PR_ASSERT((count == -1) || (count == xferred)); if (count == -1) { if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN && op->syserrno != EINTR) { op->result.code = -1; return PR_TRUE; } count = xferred; } else if (count == 0) { /* * We are now at EOF. The file was truncated. Solaris sendfile is * supposed to return 0 and no error in this case, though some versions * may return -1 and EINVAL . */ op->result.code = -1; op->syserrno = 0; /* will be treated as EOF */ return PR_TRUE; } PR_ASSERT(count <= op->nbytes_to_send); op->result.code += count; if (count < op->nbytes_to_send) { op->nbytes_to_send -= count; while (count >= vec->sfv_len) { count -= vec->sfv_len; vec++; op->arg3.amount--; } PR_ASSERT(op->arg3.amount > 0); vec->sfv_off += count; vec->sfv_len -= count; PR_ASSERT(vec->sfv_len > 0); op->arg2.buffer = vec; return PR_FALSE; } return PR_TRUE; } #endif /* SOLARIS */ #ifdef LINUX static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents) { ssize_t rv; off_t oldoffset; oldoffset = op->offset; rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count); op->syserrno = errno; if (rv == -1) { if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { op->result.code = -1; return PR_TRUE; } rv = 0; } PR_ASSERT(rv == op->offset - oldoffset); op->result.code += rv; if (rv < op->count) { op->count -= rv; return PR_FALSE; } return PR_TRUE; } #endif /* LINUX */ void _PR_InitIO(void) { #if defined(DEBUG) memset(&pt_debug, 0, sizeof(PTDebug)); pt_debug.timeStarted = PR_Now(); #endif _pr_flock_lock = PR_NewLock(); PR_ASSERT(NULL != _pr_flock_lock); _pr_flock_cv = PR_NewCondVar(_pr_flock_lock); PR_ASSERT(NULL != _pr_flock_cv); _pr_rename_lock = PR_NewLock(); PR_ASSERT(NULL != _pr_rename_lock); _PR_InitFdCache(); /* do that */ _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE, PR_TRUE); _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE, PR_TRUE); _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE, PR_TRUE); PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr); #ifdef _PR_IPV6_V6ONLY_PROBE /* In Mac OS X v10.3 Panther Beta the IPV6_V6ONLY socket option * is turned on by default, contrary to what RFC 3493, Section * 5.3 says. So we have to turn it off. Find out whether we * are running on such a system. */ { int osfd; osfd = socket(AF_INET6, SOCK_STREAM, 0); if (osfd != -1) { int on; socklen_t optlen = sizeof(on); if (getsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY, &on, &optlen) == 0) { _pr_ipv6_v6only_on_by_default = on; } close(osfd); } } #endif } /* _PR_InitIO */ void _PR_CleanupIO(void) { _PR_Putfd(_pr_stdin); _pr_stdin = NULL; _PR_Putfd(_pr_stdout); _pr_stdout = NULL; _PR_Putfd(_pr_stderr); _pr_stderr = NULL; _PR_CleanupFdCache(); if (_pr_flock_cv) { PR_DestroyCondVar(_pr_flock_cv); _pr_flock_cv = NULL; } if (_pr_flock_lock) { PR_DestroyLock(_pr_flock_lock); _pr_flock_lock = NULL; } if (_pr_rename_lock) { PR_DestroyLock(_pr_rename_lock); _pr_rename_lock = NULL; } } /* _PR_CleanupIO */ PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd) { PRFileDesc *result = NULL; PR_ASSERT(osfd >= PR_StandardInput && osfd <= PR_StandardError); if (!_pr_initialized) _PR_ImplicitInitialization(); switch (osfd) { case PR_StandardInput: result = _pr_stdin; break; case PR_StandardOutput: result = _pr_stdout; break; case PR_StandardError: result = _pr_stderr; break; default: (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); } return result; } /* PR_GetSpecialFD */ /*****************************************************************************/ /***************************** I/O private methods ***************************/ /*****************************************************************************/ static PRBool pt_TestAbort(void) { PRThread *me = PR_GetCurrentThread(); if(_PT_THREAD_INTERRUPTED(me)) { PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); me->state &= ~PT_THREAD_ABORTED; return PR_TRUE; } return PR_FALSE; } /* pt_TestAbort */ static void pt_MapError(void (*mapper)(PRIntn), PRIntn syserrno) { switch (syserrno) { case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); break; case ETIMEDOUT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; default: mapper(syserrno); } } /* pt_MapError */ static PRStatus pt_Close(PRFileDesc *fd) { if ((NULL == fd) || (NULL == fd->secret) || ((_PR_FILEDESC_OPEN != fd->secret->state) && (_PR_FILEDESC_CLOSED != fd->secret->state))) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if (pt_TestAbort()) return PR_FAILURE; if (_PR_FILEDESC_OPEN == fd->secret->state) { if (-1 == close(fd->secret->md.osfd)) { #ifdef OSF1 /* * Bug 86941: On Tru64 UNIX V5.0A and V5.1, the close() * system call, when called to close a TCP socket, may * return -1 with errno set to EINVAL but the system call * does close the socket successfully. An application * may safely ignore the EINVAL error. This bug is fixed * on Tru64 UNIX V5.1A and later. The defect tracking * number is QAR 81431. */ if (PR_DESC_SOCKET_TCP != fd->methods->file_type || EINVAL != errno) { pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno); return PR_FAILURE; } #else pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno); return PR_FAILURE; #endif } fd->secret->state = _PR_FILEDESC_CLOSED; } _PR_Putfd(fd); return PR_SUCCESS; } /* pt_Close */ static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount) { PRInt32 syserrno, bytes = -1; if (pt_TestAbort()) return bytes; bytes = read(fd->secret->md.osfd, buf, amount); syserrno = errno; if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking)) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.timeout = PR_INTERVAL_NO_TIMEOUT; op.function = pt_read_cont; op.event = POLLIN | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes < 0) pt_MapError(_PR_MD_MAP_READ_ERROR, syserrno); return bytes; } /* pt_Read */ static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount) { PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE; if (pt_TestAbort()) return bytes; bytes = write(fd->secret->md.osfd, buf, amount); syserrno = errno; if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) ) { buf = (char *) buf + bytes; amount -= bytes; fNeedContinue = PR_TRUE; } if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { bytes = 0; fNeedContinue = PR_TRUE; } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.timeout = PR_INTERVAL_NO_TIMEOUT; op.result.code = bytes; /* initialize the number sent */ op.function = pt_write_cont; op.event = POLLOUT | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes == -1) pt_MapError(_PR_MD_MAP_WRITE_ERROR, syserrno); return bytes; } /* pt_Write */ static PRInt32 pt_Writev( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_len, PRIntervalTime timeout) { PRIntn iov_index; PRBool fNeedContinue = PR_FALSE; PRInt32 syserrno, bytes, rv = -1; struct iovec osiov_local[PR_MAX_IOVECTOR_SIZE], *osiov; int osiov_len; if (pt_TestAbort()) return rv; /* Ensured by PR_Writev */ PR_ASSERT(iov_len <= PR_MAX_IOVECTOR_SIZE); /* * We can't pass iov to writev because PRIOVec and struct iovec * may not be binary compatible. Make osiov a copy of iov and * pass osiov to writev. We can modify osiov if we need to * continue the operation. */ osiov = osiov_local; osiov_len = iov_len; for (iov_index = 0; iov_index < osiov_len; iov_index++) { osiov[iov_index].iov_base = iov[iov_index].iov_base; osiov[iov_index].iov_len = iov[iov_index].iov_len; } rv = bytes = writev(fd->secret->md.osfd, osiov, osiov_len); syserrno = errno; if (!fd->secret->nonblocking) { if (bytes >= 0) { /* * If we moved some bytes, how does that implicate the * i/o vector list? In other words, exactly where are * we within that array? What are the parameters for * resumption? Maybe we're done! */ for ( ;osiov_len > 0; osiov++, osiov_len--) { if (bytes < osiov->iov_len) { /* this one's not done yet */ osiov->iov_base = (char*)osiov->iov_base + bytes; osiov->iov_len -= bytes; break; /* go off and do that */ } bytes -= osiov->iov_len; /* this one's done cooked */ } PR_ASSERT(osiov_len > 0 || bytes == 0); if (osiov_len > 0) { if (PR_INTERVAL_NO_WAIT == timeout) { rv = -1; syserrno = ETIMEDOUT; } else fNeedContinue = PR_TRUE; } } else if (syserrno == EWOULDBLOCK || syserrno == EAGAIN) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { rv = 0; fNeedContinue = PR_TRUE; } } } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)osiov; op.arg3.amount = osiov_len; op.timeout = timeout; op.result.code = rv; op.function = pt_writev_cont; op.event = POLLOUT | POLLPRI; rv = pt_Continue(&op); syserrno = op.syserrno; } if (rv == -1) pt_MapError(_PR_MD_MAP_WRITEV_ERROR, syserrno); return rv; } /* pt_Writev */ static PRInt32 pt_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) { return _PR_MD_LSEEK(fd, offset, whence); } /* pt_Seek */ static PRInt64 pt_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) { return _PR_MD_LSEEK64(fd, offset, whence); } /* pt_Seek64 */ static PRInt32 pt_Available_f(PRFileDesc *fd) { PRInt32 result, cur, end; cur = _PR_MD_LSEEK(fd, 0, PR_SEEK_CUR); if (cur >= 0) end = _PR_MD_LSEEK(fd, 0, PR_SEEK_END); if ((cur < 0) || (end < 0)) { return -1; } result = end - cur; _PR_MD_LSEEK(fd, cur, PR_SEEK_SET); return result; } /* pt_Available_f */ static PRInt64 pt_Available64_f(PRFileDesc *fd) { PRInt64 result, cur, end; PRInt64 minus_one; LL_I2L(minus_one, -1); cur = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_CUR); if (LL_GE_ZERO(cur)) end = _PR_MD_LSEEK64(fd, LL_ZERO, PR_SEEK_END); if (!LL_GE_ZERO(cur) || !LL_GE_ZERO(end)) return minus_one; LL_SUB(result, end, cur); (void)_PR_MD_LSEEK64(fd, cur, PR_SEEK_SET); return result; } /* pt_Available64_f */ static PRInt32 pt_Available_s(PRFileDesc *fd) { PRInt32 rv, bytes = -1; if (pt_TestAbort()) return bytes; rv = ioctl(fd->secret->md.osfd, FIONREAD, &bytes); if (rv == -1) pt_MapError(_PR_MD_MAP_SOCKETAVAILABLE_ERROR, errno); return bytes; } /* pt_Available_s */ static PRInt64 pt_Available64_s(PRFileDesc *fd) { PRInt64 rv; LL_I2L(rv, pt_Available_s(fd)); return rv; } /* pt_Available64_s */ static PRStatus pt_FileInfo(PRFileDesc *fd, PRFileInfo *info) { PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, info); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; } /* pt_FileInfo */ static PRStatus pt_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info) { PRInt32 rv = _PR_MD_GETOPENFILEINFO64(fd, info); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; } /* pt_FileInfo64 */ static PRStatus pt_Synch(PRFileDesc *fd) { return (NULL == fd) ? PR_FAILURE : PR_SUCCESS; } /* pt_Synch */ static PRStatus pt_Fsync(PRFileDesc *fd) { PRIntn rv = -1; if (pt_TestAbort()) return PR_FAILURE; rv = fsync(fd->secret->md.osfd); if (rv < 0) { pt_MapError(_PR_MD_MAP_FSYNC_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS; } /* pt_Fsync */ static PRStatus pt_Connect( PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout) { PRIntn rv = -1, syserrno; pt_SockLen addr_len; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif if (pt_TestAbort()) return PR_FAILURE; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); addr_len = PR_NETADDR_SIZE(addr); #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { md_af = AF_INET6; #ifndef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; #endif } #endif #ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; ((struct sockaddr*)&addrCopy)->sa_family = md_af; addrp = &addrCopy; #endif rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len); syserrno = errno; if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking)) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)addrp; op.arg3.amount = addr_len; op.timeout = timeout; op.function = pt_connect_cont; op.event = POLLOUT | POLLPRI; rv = pt_Continue(&op); syserrno = op.syserrno; } } if (-1 == rv) { pt_MapError(_PR_MD_MAP_CONNECT_ERROR, syserrno); return PR_FAILURE; } return PR_SUCCESS; } /* pt_Connect */ static PRStatus pt_ConnectContinue( PRFileDesc *fd, PRInt16 out_flags) { int err; PRInt32 osfd; if (out_flags & PR_POLL_NVAL) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if ((out_flags & (PR_POLL_WRITE | PR_POLL_EXCEPT | PR_POLL_ERR | PR_POLL_HUP)) == 0) { PR_ASSERT(out_flags == 0); PR_SetError(PR_IN_PROGRESS_ERROR, 0); return PR_FAILURE; } osfd = fd->secret->md.osfd; err = _MD_unix_get_nonblocking_connect_error(osfd); if (err != 0) { _PR_MD_MAP_CONNECT_ERROR(err); return PR_FAILURE; } return PR_SUCCESS; } /* pt_ConnectContinue */ PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd) { /* Find the NSPR layer and invoke its connectcontinue method */ PRFileDesc *bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER); if (NULL == bottom) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } return pt_ConnectContinue(bottom, pd->out_flags); } /* PR_GetConnectStatus */ static PRFileDesc* pt_Accept( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PRFileDesc *newfd = NULL; PRIntn syserrno, osfd = -1; pt_SockLen addr_len = sizeof(PRNetAddr); #ifdef SYMBIAN PRNetAddr dummy_addr; #endif if (pt_TestAbort()) return newfd; #ifdef SYMBIAN /* On Symbian OS, accept crashes if addr is NULL. */ if (!addr) addr = &dummy_addr; #endif #ifdef _PR_STRICT_ADDR_LEN if (addr) { /* * Set addr->raw.family just so that we can use the * PR_NETADDR_SIZE macro. */ addr->raw.family = fd->secret->af; addr_len = PR_NETADDR_SIZE(addr); } #endif osfd = accept(fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len); syserrno = errno; if (osfd == -1) { if (fd->secret->nonblocking) goto failed; if (EWOULDBLOCK != syserrno && EAGAIN != syserrno && ECONNABORTED != syserrno) goto failed; else { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = addr; op.arg3.addr_len = &addr_len; op.timeout = timeout; op.function = pt_accept_cont; op.event = POLLIN | POLLPRI; osfd = pt_Continue(&op); syserrno = op.syserrno; } if (osfd < 0) goto failed; } } #ifdef _PR_HAVE_SOCKADDR_LEN /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE, PR_FALSE); if (newfd == NULL) close(osfd); /* $$$ whoops! this doesn't work $$$ */ else { PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); #ifdef LINUX /* * On Linux, experiments showed that the accepted sockets * inherit the TCP_NODELAY socket option of the listening * socket. */ newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay; #endif } return newfd; failed: pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno); return NULL; } /* pt_Accept */ static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr) { PRIntn rv; pt_SockLen addr_len; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif if (pt_TestAbort()) return PR_FAILURE; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); if (addr->raw.family == AF_UNIX) { /* Disallow relative pathnames */ if (addr->local.path[0] != '/') { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } } #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { md_af = AF_INET6; #ifndef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; #endif } #endif addr_len = PR_NETADDR_SIZE(addr); #ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; ((struct sockaddr*)&addrCopy)->sa_family = md_af; addrp = &addrCopy; #endif rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len); if (rv == -1) { pt_MapError(_PR_MD_MAP_BIND_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS; } /* pt_Bind */ static PRStatus pt_Listen(PRFileDesc *fd, PRIntn backlog) { PRIntn rv; if (pt_TestAbort()) return PR_FAILURE; rv = listen(fd->secret->md.osfd, backlog); if (rv == -1) { pt_MapError(_PR_MD_MAP_LISTEN_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS; } /* pt_Listen */ static PRStatus pt_Shutdown(PRFileDesc *fd, PRIntn how) { PRIntn rv = -1; if (pt_TestAbort()) return PR_FAILURE; rv = shutdown(fd->secret->md.osfd, how); if (rv == -1) { pt_MapError(_PR_MD_MAP_SHUTDOWN_ERROR, errno); return PR_FAILURE; } return PR_SUCCESS; } /* pt_Shutdown */ static PRInt16 pt_Poll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { *out_flags = 0; return in_flags; } /* pt_Poll */ static PRInt32 pt_Recv( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 syserrno, bytes = -1; PRIntn osflags; if (0 == flags) osflags = 0; else if (PR_MSG_PEEK == flags) { #ifdef SYMBIAN /* MSG_PEEK doesn't work as expected. */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return bytes; #else osflags = MSG_PEEK; #endif } else { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return bytes; } if (pt_TestAbort()) return bytes; /* recv() is a much slower call on pre-2.6 Solaris than read(). */ #if defined(SOLARIS) if (0 == osflags) bytes = read(fd->secret->md.osfd, buf, amount); else bytes = recv(fd->secret->md.osfd, buf, amount, osflags); #else bytes = recv(fd->secret->md.osfd, buf, amount, osflags); #endif syserrno = errno; if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking)) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.arg4.flags = osflags; op.timeout = timeout; op.function = pt_recv_cont; op.event = POLLIN | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } } if (bytes < 0) pt_MapError(_PR_MD_MAP_RECV_ERROR, syserrno); return bytes; } /* pt_Recv */ static PRInt32 pt_SocketRead(PRFileDesc *fd, void *buf, PRInt32 amount) { return pt_Recv(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); } /* pt_SocketRead */ static PRInt32 pt_Send( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE; #if defined(SOLARIS) PRInt32 tmp_amount = amount; #endif /* * Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h, * which has the following: * # define send cma_send * extern int cma_send (int , void *, int, int ); * So we need to cast away the 'const' of argument #2 for send(). */ #if defined (HPUX) && defined(_PR_DCETHREADS) #define PT_SENDBUF_CAST (void *) #else #define PT_SENDBUF_CAST #endif if (pt_TestAbort()) return bytes; /* * On pre-2.6 Solaris, send() is much slower than write(). * On 2.6 and beyond, with in-kernel sockets, send() and * write() are fairly equivalent in performance. */ #if defined(SOLARIS) PR_ASSERT(0 == flags); retry: bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, tmp_amount); #else bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags); #endif syserrno = errno; #if defined(SOLARIS) /* * The write system call has been reported to return the ERANGE error * on occasion. Try to write in smaller chunks to workaround this bug. */ if ((bytes == -1) && (syserrno == ERANGE)) { if (tmp_amount > 1) { tmp_amount = tmp_amount/2; /* half the bytes */ goto retry; } } #endif if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) { bytes = -1; syserrno = ETIMEDOUT; } else { buf = (char *) buf + bytes; amount -= bytes; fNeedContinue = PR_TRUE; } } if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else { bytes = 0; fNeedContinue = PR_TRUE; } } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.arg4.flags = flags; op.timeout = timeout; op.result.code = bytes; /* initialize the number sent */ op.function = pt_send_cont; op.event = POLLOUT | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes == -1) pt_MapError(_PR_MD_MAP_SEND_ERROR, syserrno); return bytes; } /* pt_Send */ static PRInt32 pt_SocketWrite(PRFileDesc *fd, const void *buf, PRInt32 amount) { return pt_Send(fd, buf, amount, 0, PR_INTERVAL_NO_TIMEOUT); } /* pt_SocketWrite */ static PRInt32 pt_SendTo( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE; pt_SockLen addr_len; const PRNetAddr *addrp = addr; #if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6) PRUint16 md_af = addr->raw.family; PRNetAddr addrCopy; #endif if (pt_TestAbort()) return bytes; PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); #if defined(_PR_INET6) if (addr->raw.family == PR_AF_INET6) { md_af = AF_INET6; #ifndef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; addrCopy.raw.family = AF_INET6; addrp = &addrCopy; #endif } #endif addr_len = PR_NETADDR_SIZE(addr); #ifdef _PR_HAVE_SOCKADDR_LEN addrCopy = *addr; ((struct sockaddr*)&addrCopy)->sa_len = addr_len; ((struct sockaddr*)&addrCopy)->sa_family = md_af; addrp = &addrCopy; #endif bytes = sendto( fd->secret->md.osfd, buf, amount, flags, (struct sockaddr*)addrp, addr_len); syserrno = errno; if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else fNeedContinue = PR_TRUE; } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.arg4.flags = flags; op.arg5.addr = (PRNetAddr*)addrp; op.timeout = timeout; op.result.code = 0; /* initialize the number sent */ op.function = pt_sendto_cont; op.event = POLLOUT | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes < 0) pt_MapError(_PR_MD_MAP_SENDTO_ERROR, syserrno); return bytes; } /* pt_SendTo */ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { PRBool fNeedContinue = PR_FALSE; PRInt32 syserrno, bytes = -1; pt_SockLen addr_len = sizeof(PRNetAddr); if (pt_TestAbort()) return bytes; bytes = recvfrom( fd->secret->md.osfd, buf, amount, flags, (struct sockaddr*)addr, &addr_len); syserrno = errno; if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT; else fNeedContinue = PR_TRUE; } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.arg4.flags = flags; op.arg5.addr = addr; op.timeout = timeout; op.function = pt_recvfrom_cont; op.event = POLLIN | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes >= 0) { #ifdef _PR_HAVE_SOCKADDR_LEN /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ #ifdef _PR_INET6 if (addr && (AF_INET6 == addr->raw.family)) addr->raw.family = PR_AF_INET6; #endif } else pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno); return bytes; } /* pt_RecvFrom */ #ifdef AIX #ifndef HAVE_SEND_FILE static pthread_once_t pt_aix_sendfile_once_block = PTHREAD_ONCE_INIT; static void pt_aix_sendfile_init_routine(void) { void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); pt_aix_sendfile_fptr = (ssize_t (*)()) dlsym(handle, "send_file"); dlclose(handle); } /* * pt_AIXDispatchSendFile */ static PRInt32 pt_AIXDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { int rv; rv = pthread_once(&pt_aix_sendfile_once_block, pt_aix_sendfile_init_routine); PR_ASSERT(0 == rv); if (pt_aix_sendfile_fptr) { return pt_AIXSendFile(sd, sfd, flags, timeout); } else { return PR_EmulateSendFile(sd, sfd, flags, timeout); } } #endif /* !HAVE_SEND_FILE */ /* * pt_AIXSendFile * * Send file sfd->fd across socket sd. If specified, header and trailer * buffers are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * * This implementation takes advantage of the send_file() system * call available in AIX 4.3.2. */ static PRInt32 pt_AIXSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { struct sf_parms sf_struct; uint_t send_flags; ssize_t rv; int syserrno; PRInt32 count; unsigned long long saved_file_offset; long long saved_file_bytes; sf_struct.header_data = (void *) sfd->header; /* cast away the 'const' */ sf_struct.header_length = sfd->hlen; sf_struct.file_descriptor = sfd->fd->secret->md.osfd; sf_struct.file_size = 0; sf_struct.file_offset = sfd->file_offset; if (sfd->file_nbytes == 0) sf_struct.file_bytes = -1; else sf_struct.file_bytes = sfd->file_nbytes; sf_struct.trailer_data = (void *) sfd->trailer; sf_struct.trailer_length = sfd->tlen; sf_struct.bytes_sent = 0; saved_file_offset = sf_struct.file_offset; saved_file_bytes = sf_struct.file_bytes; send_flags = 0; /* flags processed at the end */ /* The first argument to send_file() is int*. */ PR_ASSERT(sizeof(int) == sizeof(sd->secret->md.osfd)); do { rv = AIX_SEND_FILE(&sd->secret->md.osfd, &sf_struct, send_flags); } while (rv == -1 && (syserrno = errno) == EINTR); if (rv == -1) { if (syserrno == EAGAIN || syserrno == EWOULDBLOCK) { count = 0; /* Not a real error. Need to continue. */ } else { count = -1; } } else { count = sf_struct.bytes_sent; /* * A bug in AIX 4.3.2 prevents the 'file_bytes' field from * being updated. So, 'file_bytes' is maintained by NSPR to * avoid conflict when this bug is fixed in AIX, in the future. */ if (saved_file_bytes != -1) saved_file_bytes -= (sf_struct.file_offset - saved_file_offset); sf_struct.file_bytes = saved_file_bytes; } if ((rv == 1) || ((rv == -1) && (count == 0))) { pt_Continuation op; op.arg1.osfd = sd->secret->md.osfd; op.arg2.buffer = &sf_struct; op.arg4.flags = send_flags; op.result.code = count; op.timeout = timeout; op.function = pt_aix_sendfile_cont; op.event = POLLOUT | POLLPRI; count = pt_Continue(&op); syserrno = op.syserrno; } if (count == -1) { pt_MapError(_MD_aix_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { PR_Close(sd); } PR_ASSERT(count == (sfd->hlen + sfd->tlen + ((sfd->file_nbytes == 0) ? sf_struct.file_size - sfd->file_offset : sfd->file_nbytes))); return count; } #endif /* AIX */ #ifdef HPUX11 /* * pt_HPUXSendFile * * Send file sfd->fd across socket sd. If specified, header and trailer * buffers are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * * This implementation takes advantage of the sendfile() system * call available in HP-UX B.11.00. */ static PRInt32 pt_HPUXSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { struct stat statbuf; size_t nbytes_to_send, file_nbytes_to_send; struct iovec hdtrl[2]; /* optional header and trailer buffers */ int send_flags; PRInt32 count; int syserrno; if (sfd->file_nbytes == 0) { /* Get file size */ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) { _PR_MD_MAP_FSTAT_ERROR(errno); return -1; } file_nbytes_to_send = statbuf.st_size - sfd->file_offset; } else { file_nbytes_to_send = sfd->file_nbytes; } nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send; hdtrl[0].iov_base = (void *) sfd->header; /* cast away the 'const' */ hdtrl[0].iov_len = sfd->hlen; hdtrl[1].iov_base = (void *) sfd->trailer; hdtrl[1].iov_len = sfd->tlen; /* * SF_DISCONNECT seems to close the socket even if sendfile() * only does a partial send on a nonblocking socket. This * would prevent the subsequent sendfile() calls on that socket * from working. So we don't use the SD_DISCONNECT flag. */ send_flags = 0; do { count = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd, sfd->file_offset, file_nbytes_to_send, hdtrl, send_flags); } while (count == -1 && (syserrno = errno) == EINTR); if (count == -1 && (syserrno == EAGAIN || syserrno == EWOULDBLOCK)) { count = 0; } if (count != -1 && count < nbytes_to_send) { pt_Continuation op; if (count < sfd->hlen) { /* header not sent */ hdtrl[0].iov_base = ((char *) sfd->header) + count; hdtrl[0].iov_len = sfd->hlen - count; op.arg3.file_spec.offset = sfd->file_offset; op.arg3.file_spec.nbytes = file_nbytes_to_send; } else if (count < (sfd->hlen + file_nbytes_to_send)) { /* header sent, file not sent */ hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; op.arg3.file_spec.offset = sfd->file_offset + count - sfd->hlen; op.arg3.file_spec.nbytes = file_nbytes_to_send - (count - sfd->hlen); } else if (count < (sfd->hlen + file_nbytes_to_send + sfd->tlen)) { PRUint32 trailer_nbytes_sent; /* header sent, file sent, trailer not sent */ hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; /* * set file offset and len so that no more file data is * sent */ op.arg3.file_spec.offset = statbuf.st_size; op.arg3.file_spec.nbytes = 0; trailer_nbytes_sent = count - sfd->hlen - file_nbytes_to_send; hdtrl[1].iov_base = ((char *) sfd->trailer) + trailer_nbytes_sent; hdtrl[1].iov_len = sfd->tlen - trailer_nbytes_sent; } op.arg1.osfd = sd->secret->md.osfd; op.filedesc = sfd->fd->secret->md.osfd; op.arg2.buffer = hdtrl; op.arg3.file_spec.st_size = statbuf.st_size; op.arg4.flags = send_flags; op.nbytes_to_send = nbytes_to_send - count; op.result.code = count; op.timeout = timeout; op.function = pt_hpux_sendfile_cont; op.event = POLLOUT | POLLPRI; count = pt_Continue(&op); syserrno = op.syserrno; } if (count == -1) { pt_MapError(_MD_hpux_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { PR_Close(sd); } PR_ASSERT(count == nbytes_to_send); return count; } #endif /* HPUX11 */ #ifdef SOLARIS /* * pt_SolarisSendFile * * Send file sfd->fd across socket sd. If specified, header and trailer * buffers are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * * This implementation takes advantage of the sendfilev() system * call available in Solaris 8. */ static PRInt32 pt_SolarisSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { struct stat statbuf; size_t nbytes_to_send, file_nbytes_to_send; struct sendfilevec sfv_struct[3]; int sfvcnt = 0; size_t xferred; PRInt32 count; int syserrno; if (sfd->file_nbytes == 0) { /* Get file size */ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) { _PR_MD_MAP_FSTAT_ERROR(errno); return -1; } file_nbytes_to_send = statbuf.st_size - sfd->file_offset; } else { file_nbytes_to_send = sfd->file_nbytes; } nbytes_to_send = sfd->hlen + sfd->tlen + file_nbytes_to_send; if (sfd->hlen != 0) { sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF; sfv_struct[sfvcnt].sfv_flag = 0; sfv_struct[sfvcnt].sfv_off = (off_t) sfd->header; sfv_struct[sfvcnt].sfv_len = sfd->hlen; sfvcnt++; } if (file_nbytes_to_send != 0) { sfv_struct[sfvcnt].sfv_fd = sfd->fd->secret->md.osfd; sfv_struct[sfvcnt].sfv_flag = 0; sfv_struct[sfvcnt].sfv_off = sfd->file_offset; sfv_struct[sfvcnt].sfv_len = file_nbytes_to_send; sfvcnt++; } if (sfd->tlen != 0) { sfv_struct[sfvcnt].sfv_fd = SFV_FD_SELF; sfv_struct[sfvcnt].sfv_flag = 0; sfv_struct[sfvcnt].sfv_off = (off_t) sfd->trailer; sfv_struct[sfvcnt].sfv_len = sfd->tlen; sfvcnt++; } if (0 == sfvcnt) { count = 0; goto done; } /* * Strictly speaking, we may have sent some bytes when the * sendfilev() is interrupted and we should retry it from an * updated offset. We are not doing that here. */ count = SOLARIS_SENDFILEV(sd->secret->md.osfd, sfv_struct, sfvcnt, &xferred); PR_ASSERT((count == -1) || (count == xferred)); if (count == -1) { syserrno = errno; if (syserrno == EINTR || syserrno == EAGAIN || syserrno == EWOULDBLOCK) { count = xferred; } } else if (count == 0) { /* * We are now at EOF. The file was truncated. Solaris sendfile is * supposed to return 0 and no error in this case, though some versions * may return -1 and EINVAL . */ count = -1; syserrno = 0; /* will be treated as EOF */ } if (count != -1 && count < nbytes_to_send) { pt_Continuation op; struct sendfilevec *vec = sfv_struct; PRInt32 rem = count; while (rem >= vec->sfv_len) { rem -= vec->sfv_len; vec++; sfvcnt--; } PR_ASSERT(sfvcnt > 0); vec->sfv_off += rem; vec->sfv_len -= rem; PR_ASSERT(vec->sfv_len > 0); op.arg1.osfd = sd->secret->md.osfd; op.arg2.buffer = vec; op.arg3.amount = sfvcnt; op.arg4.flags = 0; op.nbytes_to_send = nbytes_to_send - count; op.result.code = count; op.timeout = timeout; op.function = pt_solaris_sendfile_cont; op.event = POLLOUT | POLLPRI; count = pt_Continue(&op); syserrno = op.syserrno; } done: if (count == -1) { pt_MapError(_MD_solaris_map_sendfile_error, syserrno); return -1; } if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { PR_Close(sd); } PR_ASSERT(count == nbytes_to_send); return count; } #ifndef HAVE_SENDFILEV static pthread_once_t pt_solaris_sendfilev_once_block = PTHREAD_ONCE_INIT; static void pt_solaris_sendfilev_init_routine(void) { void *handle; PRBool close_it = PR_FALSE; /* * We do not want to unload libsendfile.so. This handle is leaked * intentionally. */ handle = dlopen("libsendfile.so", RTLD_LAZY | RTLD_GLOBAL); PR_LOG(_pr_io_lm, PR_LOG_DEBUG, ("dlopen(libsendfile.so) returns %p", handle)); if (NULL == handle) { /* * The dlopen(0, mode) call is to allow for the possibility that * sendfilev() may become part of a standard system library in a * future Solaris release. */ handle = dlopen(0, RTLD_LAZY | RTLD_GLOBAL); PR_LOG(_pr_io_lm, PR_LOG_DEBUG, ("dlopen(0) returns %p", handle)); close_it = PR_TRUE; } pt_solaris_sendfilev_fptr = (ssize_t (*)()) dlsym(handle, "sendfilev"); PR_LOG(_pr_io_lm, PR_LOG_DEBUG, ("dlsym(sendfilev) returns %p", pt_solaris_sendfilev_fptr)); if (close_it) { dlclose(handle); } } /* * pt_SolarisDispatchSendFile */ static PRInt32 pt_SolarisDispatchSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { int rv; rv = pthread_once(&pt_solaris_sendfilev_once_block, pt_solaris_sendfilev_init_routine); PR_ASSERT(0 == rv); if (pt_solaris_sendfilev_fptr) { return pt_SolarisSendFile(sd, sfd, flags, timeout); } else { return PR_EmulateSendFile(sd, sfd, flags, timeout); } } #endif /* !HAVE_SENDFILEV */ #endif /* SOLARIS */ #ifdef LINUX /* * pt_LinuxSendFile * * Send file sfd->fd across socket sd. If specified, header and trailer * buffers are sent before and after the file, respectively. * * PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file * * return number of bytes sent or -1 on error * * This implementation takes advantage of the sendfile() system * call available in Linux kernel 2.2 or higher. */ static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { struct stat statbuf; size_t file_nbytes_to_send; PRInt32 count = 0; ssize_t rv; int syserrno; off_t offset; PRBool tcp_cork_enabled = PR_FALSE; int tcp_cork; if (sfd->file_nbytes == 0) { /* Get file size */ if (fstat(sfd->fd->secret->md.osfd, &statbuf) == -1) { _PR_MD_MAP_FSTAT_ERROR(errno); return -1; } file_nbytes_to_send = statbuf.st_size - sfd->file_offset; } else { file_nbytes_to_send = sfd->file_nbytes; } if ((sfd->hlen != 0 || sfd->tlen != 0) && sd->secret->md.tcp_nodelay == 0) { tcp_cork = 1; if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK, &tcp_cork, sizeof tcp_cork) == 0) { tcp_cork_enabled = PR_TRUE; } else { syserrno = errno; if (syserrno != EINVAL) { _PR_MD_MAP_SETSOCKOPT_ERROR(syserrno); return -1; } /* * The most likely reason for the EINVAL error is that * TCP_NODELAY is set (with a function other than * PR_SetSocketOption). This is not fatal, so we keep * on going. */ PR_LOG(_pr_io_lm, PR_LOG_WARNING, ("pt_LinuxSendFile: " "setsockopt(TCP_CORK) failed with EINVAL\n")); } } if (sfd->hlen != 0) { count = PR_Send(sd, sfd->header, sfd->hlen, 0, timeout); if (count == -1) { goto failed; } } if (file_nbytes_to_send != 0) { offset = sfd->file_offset; do { rv = sendfile(sd->secret->md.osfd, sfd->fd->secret->md.osfd, &offset, file_nbytes_to_send); } while (rv == -1 && (syserrno = errno) == EINTR); if (rv == -1) { if (syserrno != EAGAIN && syserrno != EWOULDBLOCK) { _MD_linux_map_sendfile_error(syserrno); count = -1; goto failed; } rv = 0; } PR_ASSERT(rv == offset - sfd->file_offset); count += rv; if (rv < file_nbytes_to_send) { pt_Continuation op; op.arg1.osfd = sd->secret->md.osfd; op.in_fd = sfd->fd->secret->md.osfd; op.offset = offset; op.count = file_nbytes_to_send - rv; op.result.code = count; op.timeout = timeout; op.function = pt_linux_sendfile_cont; op.event = POLLOUT | POLLPRI; count = pt_Continue(&op); syserrno = op.syserrno; if (count == -1) { pt_MapError(_MD_linux_map_sendfile_error, syserrno); goto failed; } } } if (sfd->tlen != 0) { rv = PR_Send(sd, sfd->trailer, sfd->tlen, 0, timeout); if (rv == -1) { count = -1; goto failed; } count += rv; } failed: if (tcp_cork_enabled) { tcp_cork = 0; if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK, &tcp_cork, sizeof tcp_cork) == -1 && count != -1) { _PR_MD_MAP_SETSOCKOPT_ERROR(errno); count = -1; } } if (count != -1) { if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) { PR_Close(sd); } PR_ASSERT(count == sfd->hlen + sfd->tlen + file_nbytes_to_send); } return count; } #endif /* LINUX */ #ifdef AIX extern int _pr_aix_send_file_use_disabled; #endif static PRInt32 pt_SendFile( PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { if (pt_TestAbort()) return -1; /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return -1; } #ifdef HPUX11 return(pt_HPUXSendFile(sd, sfd, flags, timeout)); #elif defined(AIX) #ifdef HAVE_SEND_FILE /* * A bug in AIX 4.3.2 results in corruption of data transferred by * send_file(); AIX patch PTF U463956 contains the fix. A user can * disable the use of send_file function in NSPR, when this patch is * not installed on the system, by setting the envionment variable * NSPR_AIX_SEND_FILE_USE_DISABLED to 1. */ if (_pr_aix_send_file_use_disabled) return(PR_EmulateSendFile(sd, sfd, flags, timeout)); else return(pt_AIXSendFile(sd, sfd, flags, timeout)); #else return(PR_EmulateSendFile(sd, sfd, flags, timeout)); /* return(pt_AIXDispatchSendFile(sd, sfd, flags, timeout));*/ #endif /* HAVE_SEND_FILE */ #elif defined(SOLARIS) #ifdef HAVE_SENDFILEV return(pt_SolarisSendFile(sd, sfd, flags, timeout)); #else return(pt_SolarisDispatchSendFile(sd, sfd, flags, timeout)); #endif /* HAVE_SENDFILEV */ #elif defined(LINUX) return(pt_LinuxSendFile(sd, sfd, flags, timeout)); #else return(PR_EmulateSendFile(sd, sfd, flags, timeout)); #endif } static PRInt32 pt_TransmitFile( PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRSendFileData sfd; sfd.fd = fd; sfd.file_offset = 0; sfd.file_nbytes = 0; sfd.header = headers; sfd.hlen = hlen; sfd.trailer = NULL; sfd.tlen = 0; return(pt_SendFile(sd, &sfd, flags, timeout)); } /* pt_TransmitFile */ static PRInt32 pt_AcceptRead( PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { PRInt32 rv = -1; if (pt_TestAbort()) return rv; /* The socket must be in blocking mode. */ if (sd->secret->nonblocking) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return rv; } rv = PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout); return rv; } /* pt_AcceptRead */ static PRStatus pt_GetSockName(PRFileDesc *fd, PRNetAddr *addr) { PRIntn rv = -1; pt_SockLen addr_len = sizeof(PRNetAddr); if (pt_TestAbort()) return PR_FAILURE; rv = getsockname( fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len); if (rv == -1) { pt_MapError(_PR_MD_MAP_GETSOCKNAME_ERROR, errno); return PR_FAILURE; } else { #ifdef _PR_HAVE_SOCKADDR_LEN /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); return PR_SUCCESS; } } /* pt_GetSockName */ static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) { PRIntn rv = -1; pt_SockLen addr_len = sizeof(PRNetAddr); if (pt_TestAbort()) return PR_FAILURE; rv = getpeername( fd->secret->md.osfd, (struct sockaddr*)addr, &addr_len); if (rv == -1) { pt_MapError(_PR_MD_MAP_GETPEERNAME_ERROR, errno); return PR_FAILURE; } else { #ifdef _PR_HAVE_SOCKADDR_LEN /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr*)addr)->sa_family; } #endif /* _PR_HAVE_SOCKADDR_LEN */ #ifdef _PR_INET6 if (AF_INET6 == addr->raw.family) addr->raw.family = PR_AF_INET6; #endif PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE); PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE); return PR_SUCCESS; } } /* pt_GetPeerName */ static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) { PRIntn rv; pt_SockLen length; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a getsockopt() call */ if (PR_SockOpt_Nonblocking == data->option) { data->value.non_blocking = fd->secret->nonblocking; return PR_SUCCESS; } rv = _PR_MapOptionName(data->option, &level, &name); if (PR_SUCCESS == rv) { switch (data->option) { case PR_SockOpt_Linger: { struct linger linger; length = sizeof(linger); rv = getsockopt( fd->secret->md.osfd, level, name, (char *) &linger, &length); PR_ASSERT((-1 == rv) || (sizeof(linger) == length)); data->value.linger.polarity = (linger.l_onoff) ? PR_TRUE : PR_FALSE; data->value.linger.linger = PR_SecondsToInterval(linger.l_linger); break; } case PR_SockOpt_Reuseaddr: case PR_SockOpt_Keepalive: case PR_SockOpt_NoDelay: case PR_SockOpt_Broadcast: case PR_SockOpt_Reuseport: { PRIntn value; length = sizeof(PRIntn); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&value, &length); PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length)); data->value.reuse_addr = (0 == value) ? PR_FALSE : PR_TRUE; break; } case PR_SockOpt_McastLoopback: { PRUint8 xbool; length = sizeof(xbool); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&xbool, &length); PR_ASSERT((-1 == rv) || (sizeof(xbool) == length)); data->value.mcast_loopback = (0 == xbool) ? PR_FALSE : PR_TRUE; break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value; length = sizeof(PRIntn); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&value, &length); PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length)); data->value.recv_buffer_size = value; break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { length = sizeof(PRUintn); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&data->value.ip_ttl, &length); PR_ASSERT((-1 == rv) || (sizeof(PRIntn) == length)); break; } case PR_SockOpt_McastTimeToLive: { PRUint8 ttl; length = sizeof(ttl); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&ttl, &length); PR_ASSERT((-1 == rv) || (sizeof(ttl) == length)); data->value.mcast_ttl = ttl; break; } case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; length = sizeof(mreq); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&mreq, &length); PR_ASSERT((-1 == rv) || (sizeof(mreq) == length)); data->value.add_member.mcaddr.inet.ip = mreq.imr_multiaddr.s_addr; data->value.add_member.ifaddr.inet.ip = mreq.imr_interface.s_addr; break; } case PR_SockOpt_McastInterface: { length = sizeof(data->value.mcast_if.inet.ip); rv = getsockopt( fd->secret->md.osfd, level, name, (char*)&data->value.mcast_if.inet.ip, &length); PR_ASSERT((-1 == rv) || (sizeof(data->value.mcast_if.inet.ip) == length)); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } if (-1 == rv) _PR_MD_MAP_GETSOCKOPT_ERROR(errno); } return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; } /* pt_GetSocketOption */ static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data) { PRIntn rv; PRInt32 level, name; /* * PR_SockOpt_Nonblocking is a special case that does not * translate to a setsockopt call. */ if (PR_SockOpt_Nonblocking == data->option) { fd->secret->nonblocking = data->value.non_blocking; return PR_SUCCESS; } rv = _PR_MapOptionName(data->option, &level, &name); if (PR_SUCCESS == rv) { switch (data->option) { case PR_SockOpt_Linger: { struct linger linger; linger.l_onoff = data->value.linger.polarity; linger.l_linger = PR_IntervalToSeconds(data->value.linger.linger); rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&linger, sizeof(linger)); break; } case PR_SockOpt_Reuseaddr: case PR_SockOpt_Keepalive: case PR_SockOpt_NoDelay: case PR_SockOpt_Broadcast: case PR_SockOpt_Reuseport: { PRIntn value = (data->value.reuse_addr) ? 1 : 0; rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&value, sizeof(PRIntn)); #ifdef LINUX /* for pt_LinuxSendFile */ if (name == TCP_NODELAY && rv == 0) { fd->secret->md.tcp_nodelay = value; } #endif break; } case PR_SockOpt_McastLoopback: { PRUint8 xbool = data->value.mcast_loopback ? 1 : 0; rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&xbool, sizeof(xbool)); break; } case PR_SockOpt_RecvBufferSize: case PR_SockOpt_SendBufferSize: case PR_SockOpt_MaxSegment: { PRIntn value = data->value.recv_buffer_size; rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&value, sizeof(PRIntn)); break; } case PR_SockOpt_IpTimeToLive: case PR_SockOpt_IpTypeOfService: { rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&data->value.ip_ttl, sizeof(PRUintn)); break; } case PR_SockOpt_McastTimeToLive: { PRUint8 ttl = data->value.mcast_ttl; rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&ttl, sizeof(ttl)); break; } case PR_SockOpt_AddMember: case PR_SockOpt_DropMember: { struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = data->value.add_member.mcaddr.inet.ip; mreq.imr_interface.s_addr = data->value.add_member.ifaddr.inet.ip; rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&mreq, sizeof(mreq)); break; } case PR_SockOpt_McastInterface: { rv = setsockopt( fd->secret->md.osfd, level, name, (char*)&data->value.mcast_if.inet.ip, sizeof(data->value.mcast_if.inet.ip)); break; } default: PR_NOT_REACHED("Unknown socket option"); break; } if (-1 == rv) _PR_MD_MAP_SETSOCKOPT_ERROR(errno); } return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; } /* pt_SetSocketOption */ /*****************************************************************************/ /****************************** I/O method objects ***************************/ /*****************************************************************************/ static PRIOMethods _pr_file_methods = { PR_DESC_FILE, pt_Close, pt_Read, pt_Write, pt_Available_f, pt_Available64_f, pt_Fsync, pt_Seek, pt_Seek64, pt_FileInfo, pt_FileInfo64, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, pt_Poll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRIOMethods _pr_pipe_methods = { PR_DESC_PIPE, pt_Close, pt_Read, pt_Write, pt_Available_s, pt_Available64_s, pt_Synch, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, pt_Poll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRIOMethods _pr_tcp_methods = { PR_DESC_SOCKET_TCP, pt_Close, pt_SocketRead, pt_SocketWrite, pt_Available_s, pt_Available64_s, pt_Synch, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, pt_Writev, pt_Connect, pt_Accept, pt_Bind, pt_Listen, pt_Shutdown, pt_Recv, pt_Send, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, pt_Poll, pt_AcceptRead, pt_TransmitFile, pt_GetSockName, pt_GetPeerName, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, pt_GetSocketOption, pt_SetSocketOption, pt_SendFile, pt_ConnectContinue, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRIOMethods _pr_udp_methods = { PR_DESC_SOCKET_UDP, pt_Close, pt_SocketRead, pt_SocketWrite, pt_Available_s, pt_Available64_s, pt_Synch, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, pt_Writev, pt_Connect, (PRAcceptFN)_PR_InvalidDesc, pt_Bind, pt_Listen, pt_Shutdown, pt_Recv, pt_Send, pt_RecvFrom, pt_SendTo, pt_Poll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, pt_GetSockName, pt_GetPeerName, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, pt_GetSocketOption, pt_SetSocketOption, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; static PRIOMethods _pr_socketpollfd_methods = { (PRDescType) 0, (PRCloseFN)_PR_InvalidStatus, (PRReadFN)_PR_InvalidInt, (PRWriteFN)_PR_InvalidInt, (PRAvailableFN)_PR_InvalidInt, (PRAvailable64FN)_PR_InvalidInt64, (PRFsyncFN)_PR_InvalidStatus, (PRSeekFN)_PR_InvalidInt, (PRSeek64FN)_PR_InvalidInt64, (PRFileInfoFN)_PR_InvalidStatus, (PRFileInfo64FN)_PR_InvalidStatus, (PRWritevFN)_PR_InvalidInt, (PRConnectFN)_PR_InvalidStatus, (PRAcceptFN)_PR_InvalidDesc, (PRBindFN)_PR_InvalidStatus, (PRListenFN)_PR_InvalidStatus, (PRShutdownFN)_PR_InvalidStatus, (PRRecvFN)_PR_InvalidInt, (PRSendFN)_PR_InvalidInt, (PRRecvfromFN)_PR_InvalidInt, (PRSendtoFN)_PR_InvalidInt, pt_Poll, (PRAcceptreadFN)_PR_InvalidInt, (PRTransmitfileFN)_PR_InvalidInt, (PRGetsocknameFN)_PR_InvalidStatus, (PRGetpeernameFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRGetsocketoptionFN)_PR_InvalidStatus, (PRSetsocketoptionFN)_PR_InvalidStatus, (PRSendfileFN)_PR_InvalidInt, (PRConnectcontinueFN)_PR_InvalidStatus, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt, (PRReservedFN)_PR_InvalidInt }; #if defined(HPUX) || defined(OSF1) || defined(SOLARIS) || defined (IRIX) \ || defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \ || defined(AIX) || defined(FREEBSD) || defined(NETBSD) \ || defined(OPENBSD) || defined(BSDI) || defined(NTO) \ || defined(DARWIN) || defined(UNIXWARE) || defined(RISCOS) \ || defined(SYMBIAN) #define _PR_FCNTL_FLAGS O_NONBLOCK #else #error "Can't determine architecture" #endif /* * Put a Unix file descriptor in non-blocking mode. */ static void pt_MakeFdNonblock(PRIntn osfd) { PRIntn flags; flags = fcntl(osfd, F_GETFL, 0); flags |= _PR_FCNTL_FLAGS; (void)fcntl(osfd, F_SETFL, flags); } /* * Put a Unix socket fd in non-blocking mode that can * ideally be inherited by an accepted socket. * * Why doesn't pt_MakeFdNonblock do? This is to deal with * the special case of HP-UX. HP-UX has three kinds of * non-blocking modes for sockets: the fcntl() O_NONBLOCK * and O_NDELAY flags and ioctl() FIOSNBIO request. Only * the ioctl() FIOSNBIO form of non-blocking mode is * inherited by an accepted socket. * * Other platforms just use the generic pt_MakeFdNonblock * to put a socket in non-blocking mode. */ #ifdef HPUX static void pt_MakeSocketNonblock(PRIntn osfd) { PRIntn one = 1; (void)ioctl(osfd, FIOSNBIO, &one); } #else #define pt_MakeSocketNonblock pt_MakeFdNonblock #endif static PRFileDesc *pt_SetMethods( PRIntn osfd, PRDescType type, PRBool isAcceptedSocket, PRBool imported) { PRFileDesc *fd = _PR_Getfd(); if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); else { fd->secret->md.osfd = osfd; fd->secret->state = _PR_FILEDESC_OPEN; if (imported) fd->secret->inheritable = _PR_TRI_UNKNOWN; else { /* By default, a Unix fd is not closed on exec. */ #ifdef DEBUG PRIntn flags; flags = fcntl(osfd, F_GETFD, 0); PR_ASSERT(0 == flags); #endif fd->secret->inheritable = _PR_TRI_TRUE; } switch (type) { case PR_DESC_FILE: fd->methods = PR_GetFileMethods(); break; case PR_DESC_SOCKET_TCP: fd->methods = PR_GetTCPMethods(); #ifdef _PR_ACCEPT_INHERIT_NONBLOCK if (!isAcceptedSocket) pt_MakeSocketNonblock(osfd); #else pt_MakeSocketNonblock(osfd); #endif break; case PR_DESC_SOCKET_UDP: fd->methods = PR_GetUDPMethods(); pt_MakeFdNonblock(osfd); break; case PR_DESC_PIPE: fd->methods = PR_GetPipeMethods(); pt_MakeFdNonblock(osfd); break; default: break; } } return fd; } /* pt_SetMethods */ PR_IMPLEMENT(const PRIOMethods*) PR_GetFileMethods(void) { return &_pr_file_methods; } /* PR_GetFileMethods */ PR_IMPLEMENT(const PRIOMethods*) PR_GetPipeMethods(void) { return &_pr_pipe_methods; } /* PR_GetPipeMethods */ PR_IMPLEMENT(const PRIOMethods*) PR_GetTCPMethods(void) { return &_pr_tcp_methods; } /* PR_GetTCPMethods */ PR_IMPLEMENT(const PRIOMethods*) PR_GetUDPMethods(void) { return &_pr_udp_methods; } /* PR_GetUDPMethods */ static const PRIOMethods* PR_GetSocketPollFdMethods(void) { return &_pr_socketpollfd_methods; } /* PR_GetSocketPollFdMethods */ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDesc( PRInt32 osfd, const PRIOMethods *methods) { PRFileDesc *fd = _PR_Getfd(); if (NULL == fd) goto failed; fd->methods = methods; fd->secret->md.osfd = osfd; /* Make fd non-blocking */ if (osfd > 2) { /* Don't mess around with stdin, stdout or stderr */ if (&_pr_tcp_methods == methods) pt_MakeSocketNonblock(osfd); else pt_MakeFdNonblock(osfd); } fd->secret->state = _PR_FILEDESC_OPEN; fd->secret->inheritable = _PR_TRI_UNKNOWN; return fd; failed: PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return fd; } /* PR_AllocFileDesc */ #if !defined(_PR_INET6) || defined(_PR_INET6_PROBE) PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd); #if defined(_PR_INET6_PROBE) extern PRBool _pr_ipv6_is_present(void); PR_IMPLEMENT(PRBool) _pr_test_ipv6_socket() { int osfd; #if defined(DARWIN) /* * Disable IPv6 if Darwin version is less than 7.0.0 (OS X 10.3). IPv6 on * lesser versions is not ready for general use (see bug 222031). */ { struct utsname u; if (uname(&u) != 0 || atoi(u.release) < 7) return PR_FALSE; } #endif /* * HP-UX only: HP-UX IPv6 Porting Guide (dated February 2001) * suggests that we call open("/dev/ip6", O_RDWR) to determine * whether IPv6 APIs and the IPv6 stack are on the system. * Our portable test below seems to work fine, so I am using it. */ osfd = socket(AF_INET6, SOCK_STREAM, 0); if (osfd != -1) { close(osfd); return PR_TRUE; } return PR_FALSE; } #endif /* _PR_INET6_PROBE */ #endif PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto) { PRIntn osfd; PRDescType ftype; PRFileDesc *fd = NULL; #if defined(_PR_INET6_PROBE) || !defined(_PR_INET6) PRInt32 tmp_domain = domain; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); if (pt_TestAbort()) return NULL; if (PF_INET != domain && PR_AF_INET6 != domain #if defined(_PR_HAVE_SDP) && PR_AF_INET_SDP != domain #if defined(SOLARIS) && PR_AF_INET6_SDP != domain #endif /* SOLARIS */ #endif /* _PR_HAVE_SDP */ && PF_UNIX != domain) { PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return fd; } if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP; else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP; else { (void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0); return fd; } #if defined(_PR_HAVE_SDP) #if defined(LINUX) if (PR_AF_INET_SDP == domain) domain = AF_INET_SDP; #elif defined(SOLARIS) if (PR_AF_INET_SDP == domain) { domain = AF_INET; proto = PROTO_SDP; } else if(PR_AF_INET6_SDP == domain) { domain = AF_INET6; proto = PROTO_SDP; } #endif /* SOLARIS */ #endif /* _PR_HAVE_SDP */ #if defined(_PR_INET6_PROBE) if (PR_AF_INET6 == domain) domain = _pr_ipv6_is_present() ? AF_INET6 : AF_INET; #elif defined(_PR_INET6) if (PR_AF_INET6 == domain) domain = AF_INET6; #else if (PR_AF_INET6 == domain) domain = AF_INET; #endif osfd = socket(domain, type, proto); if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno); else { #ifdef _PR_IPV6_V6ONLY_PROBE if ((domain == AF_INET6) && _pr_ipv6_v6only_on_by_default) { int on = 0; (void)setsockopt(osfd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); } #endif fd = pt_SetMethods(osfd, ftype, PR_FALSE, PR_FALSE); if (fd == NULL) close(osfd); } #ifdef _PR_NEED_SECRET_AF if (fd != NULL) fd->secret->af = domain; #endif #if defined(_PR_INET6_PROBE) || !defined(_PR_INET6) if (fd != NULL) { /* * For platforms with no support for IPv6 * create layered socket for IPv4-mapped IPv6 addresses */ if (PR_AF_INET6 == tmp_domain && PR_AF_INET == domain) { if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) { PR_Close(fd); fd = NULL; } } } #endif return fd; } /* PR_Socket */ /*****************************************************************************/ /****************************** I/O public methods ***************************/ /*****************************************************************************/ PR_IMPLEMENT(PRFileDesc*) PR_OpenFile( const char *name, PRIntn flags, PRIntn mode) { PRFileDesc *fd = NULL; PRIntn syserrno, osfd = -1, osflags = 0;; if (!_pr_initialized) _PR_ImplicitInitialization(); if (pt_TestAbort()) return NULL; if (flags & PR_RDONLY) osflags |= O_RDONLY; if (flags & PR_WRONLY) osflags |= O_WRONLY; if (flags & PR_RDWR) osflags |= O_RDWR; if (flags & PR_APPEND) osflags |= O_APPEND; if (flags & PR_TRUNCATE) osflags |= O_TRUNC; if (flags & PR_EXCL) osflags |= O_EXCL; if (flags & PR_SYNC) { #if defined(O_SYNC) osflags |= O_SYNC; #elif defined(O_FSYNC) osflags |= O_FSYNC; #else #error "Neither O_SYNC nor O_FSYNC is defined on this platform" #endif } /* ** We have to hold the lock across the creation in order to ** enforce the sematics of PR_Rename(). (see the latter for ** more details) */ if (flags & PR_CREATE_FILE) { osflags |= O_CREAT; if (NULL !=_pr_rename_lock) PR_Lock(_pr_rename_lock); } osfd = _md_iovector._open64(name, osflags, mode); syserrno = errno; if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock)) PR_Unlock(_pr_rename_lock); if (osfd == -1) pt_MapError(_PR_MD_MAP_OPEN_ERROR, syserrno); else { fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_FALSE); if (fd == NULL) close(osfd); /* $$$ whoops! this is bad $$$ */ } return fd; } /* PR_OpenFile */ PR_IMPLEMENT(PRFileDesc*) PR_Open(const char *name, PRIntn flags, PRIntn mode) { return PR_OpenFile(name, flags, mode); } /* PR_Open */ PR_IMPLEMENT(PRStatus) PR_Delete(const char *name) { PRIntn rv = -1; if (!_pr_initialized) _PR_ImplicitInitialization(); if (pt_TestAbort()) return PR_FAILURE; rv = unlink(name); if (rv == -1) { pt_MapError(_PR_MD_MAP_UNLINK_ERROR, errno); return PR_FAILURE; } else return PR_SUCCESS; } /* PR_Delete */ PR_IMPLEMENT(PRStatus) PR_Access(const char *name, PRAccessHow how) { PRIntn rv; if (pt_TestAbort()) return PR_FAILURE; switch (how) { case PR_ACCESS_READ_OK: rv = access(name, R_OK); break; case PR_ACCESS_WRITE_OK: rv = access(name, W_OK); break; case PR_ACCESS_EXISTS: default: rv = access(name, F_OK); } if (0 == rv) return PR_SUCCESS; pt_MapError(_PR_MD_MAP_ACCESS_ERROR, errno); return PR_FAILURE; } /* PR_Access */ PR_IMPLEMENT(PRStatus) PR_GetFileInfo(const char *fn, PRFileInfo *info) { PRInt32 rv = _PR_MD_GETFILEINFO(fn, info); return (0 == rv) ? PR_SUCCESS : PR_FAILURE; } /* PR_GetFileInfo */ PR_IMPLEMENT(PRStatus) PR_GetFileInfo64(const char *fn, PRFileInfo64 *info) { PRInt32 rv; if (!_pr_initialized) _PR_ImplicitInitialization(); rv = _PR_MD_GETFILEINFO64(fn, info); return (0 == rv) ? PR_SUCCESS : PR_FAILURE; } /* PR_GetFileInfo64 */ PR_IMPLEMENT(PRStatus) PR_Rename(const char *from, const char *to) { PRIntn rv = -1; if (pt_TestAbort()) return PR_FAILURE; /* ** We have to acquire a lock here to stiffle anybody trying to create ** a new file at the same time. And we have to hold that lock while we ** test to see if the file exists and do the rename. The other place ** where the lock is held is in PR_Open() when possibly creating a ** new file. */ PR_Lock(_pr_rename_lock); rv = access(to, F_OK); if (0 == rv) { PR_SetError(PR_FILE_EXISTS_ERROR, 0); rv = -1; } else { rv = rename(from, to); if (rv == -1) pt_MapError(_PR_MD_MAP_RENAME_ERROR, errno); } PR_Unlock(_pr_rename_lock); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; } /* PR_Rename */ PR_IMPLEMENT(PRStatus) PR_CloseDir(PRDir *dir) { if (pt_TestAbort()) return PR_FAILURE; if (NULL != dir->md.d) { if (closedir(dir->md.d) == -1) { _PR_MD_MAP_CLOSEDIR_ERROR(errno); return PR_FAILURE; } dir->md.d = NULL; PR_DELETE(dir); } return PR_SUCCESS; } /* PR_CloseDir */ PR_IMPLEMENT(PRStatus) PR_MakeDir(const char *name, PRIntn mode) { PRInt32 rv = -1; if (pt_TestAbort()) return PR_FAILURE; /* ** This lock is used to enforce rename semantics as described ** in PR_Rename. */ if (NULL !=_pr_rename_lock) PR_Lock(_pr_rename_lock); rv = mkdir(name, mode); if (-1 == rv) pt_MapError(_PR_MD_MAP_MKDIR_ERROR, errno); if (NULL !=_pr_rename_lock) PR_Unlock(_pr_rename_lock); return (-1 == rv) ? PR_FAILURE : PR_SUCCESS; } /* PR_Makedir */ PR_IMPLEMENT(PRStatus) PR_MkDir(const char *name, PRIntn mode) { return PR_MakeDir(name, mode); } /* PR_Mkdir */ PR_IMPLEMENT(PRStatus) PR_RmDir(const char *name) { PRInt32 rv; if (pt_TestAbort()) return PR_FAILURE; rv = rmdir(name); if (0 == rv) { return PR_SUCCESS; } else { pt_MapError(_PR_MD_MAP_RMDIR_ERROR, errno); return PR_FAILURE; } } /* PR_Rmdir */ PR_IMPLEMENT(PRDir*) PR_OpenDir(const char *name) { DIR *osdir; PRDir *dir = NULL; if (pt_TestAbort()) return dir; osdir = opendir(name); if (osdir == NULL) pt_MapError(_PR_MD_MAP_OPENDIR_ERROR, errno); else { dir = PR_NEWZAP(PRDir); if (dir) dir->md.d = osdir; else (void)closedir(osdir); } return dir; } /* PR_OpenDir */ static PRInt32 _pr_poll_with_poll( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { PRInt32 ready = 0; /* * For restarting poll() if it is interrupted by a signal. * We use these variables to figure out how much time has * elapsed and how much of the timeout still remains. */ PRIntervalTime start, elapsed, remaining; if (pt_TestAbort()) return -1; if (0 == npds) PR_Sleep(timeout); else { #define STACK_POLL_DESC_COUNT 64 struct pollfd stack_syspoll[STACK_POLL_DESC_COUNT]; struct pollfd *syspoll; PRIntn index, msecs; if (npds <= STACK_POLL_DESC_COUNT) { syspoll = stack_syspoll; } else { PRThread *me = PR_GetCurrentThread(); if (npds > me->syspoll_count) { PR_Free(me->syspoll_list); me->syspoll_list = (struct pollfd*)PR_MALLOC(npds * sizeof(struct pollfd)); if (NULL == me->syspoll_list) { me->syspoll_count = 0; PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } me->syspoll_count = npds; } syspoll = me->syspoll_list; } for (index = 0; index < npds; ++index) { PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (pds[index].in_flags & PR_POLL_READ) { in_flags_read = (pds[index].fd->methods->poll)( pds[index].fd, pds[index].in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pds[index].in_flags & PR_POLL_WRITE) { in_flags_write = (pds[index].fd->methods->poll)( pds[index].fd, pds[index].in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one is ready right now */ if (0 == ready) { /* * We will return without calling the system * poll function. So zero the out_flags * fields of all the poll descriptors before * this one. */ int i; for (i = 0; i < index; i++) { pds[i].out_flags = 0; } } ready += 1; pds[index].out_flags = out_flags_read | out_flags_write; } else { /* now locate the NSPR layer at the bottom of the stack */ PRFileDesc *bottom = PR_GetIdentitiesLayer( pds[index].fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ pds[index].out_flags = 0; /* pre-condition */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { syspoll[index].fd = bottom->secret->md.osfd; syspoll[index].events = 0; if (in_flags_read & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_READ_SYS_READ; syspoll[index].events |= POLLIN; } if (in_flags_read & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_READ_SYS_WRITE; syspoll[index].events |= POLLOUT; } if (in_flags_write & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_READ; syspoll[index].events |= POLLIN; } if (in_flags_write & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_WRITE; syspoll[index].events |= POLLOUT; } if (pds[index].in_flags & PR_POLL_EXCEPT) syspoll[index].events |= POLLPRI; } } else { if (0 == ready) { int i; for (i = 0; i < index; i++) { pds[i].out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pds[index].out_flags = PR_POLL_NVAL; /* bogii */ } } } else { /* make poll() ignore this entry */ syspoll[index].fd = -1; syspoll[index].events = 0; pds[index].out_flags = 0; } } if (0 == ready) { switch (timeout) { case PR_INTERVAL_NO_WAIT: msecs = 0; break; case PR_INTERVAL_NO_TIMEOUT: msecs = -1; break; default: msecs = PR_IntervalToMilliseconds(timeout); start = PR_IntervalNow(); } retry: ready = poll(syspoll, npds, msecs); if (-1 == ready) { PRIntn oserror = errno; if (EINTR == oserror) { if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0; /* don't retry, just time out */ else { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) ready = 0; /* timed out */ else { remaining = timeout - elapsed; msecs = PR_IntervalToMilliseconds(remaining); goto retry; } } } else { _PR_MD_MAP_POLL_ERROR(oserror); } } else if (ready > 0) { for (index = 0; index < npds; ++index) { PRInt16 out_flags = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (0 != syspoll[index].revents) { if (syspoll[index].revents & POLLIN) { if (pds[index].out_flags & _PR_POLL_READ_SYS_READ) { out_flags |= PR_POLL_READ; } if (pds[index].out_flags & _PR_POLL_WRITE_SYS_READ) { out_flags |= PR_POLL_WRITE; } } if (syspoll[index].revents & POLLOUT) { if (pds[index].out_flags & _PR_POLL_READ_SYS_WRITE) { out_flags |= PR_POLL_READ; } if (pds[index].out_flags & _PR_POLL_WRITE_SYS_WRITE) { out_flags |= PR_POLL_WRITE; } } if (syspoll[index].revents & POLLPRI) out_flags |= PR_POLL_EXCEPT; if (syspoll[index].revents & POLLERR) out_flags |= PR_POLL_ERR; if (syspoll[index].revents & POLLNVAL) out_flags |= PR_POLL_NVAL; if (syspoll[index].revents & POLLHUP) out_flags |= PR_POLL_HUP; } } pds[index].out_flags = out_flags; } } } } return ready; } /* _pr_poll_with_poll */ #if defined(_PR_POLL_WITH_SELECT) /* * OSF1 and HPUX report the POLLHUP event for a socket when the * shutdown(SHUT_WR) operation is called for the remote end, even though * the socket is still writeable. Use select(), instead of poll(), to * workaround this problem. */ static PRInt32 _pr_poll_with_select( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { PRInt32 ready = 0; /* * For restarting select() if it is interrupted by a signal. * We use these variables to figure out how much time has * elapsed and how much of the timeout still remains. */ PRIntervalTime start, elapsed, remaining; if (pt_TestAbort()) return -1; if (0 == npds) PR_Sleep(timeout); else { #define STACK_POLL_DESC_COUNT 64 int stack_selectfd[STACK_POLL_DESC_COUNT]; int *selectfd; fd_set rd, wr, ex, *rdp = NULL, *wrp = NULL, *exp = NULL; struct timeval tv, *tvp; PRIntn index, msecs, maxfd = 0; if (npds <= STACK_POLL_DESC_COUNT) { selectfd = stack_selectfd; } else { PRThread *me = PR_GetCurrentThread(); if (npds > me->selectfd_count) { PR_Free(me->selectfd_list); me->selectfd_list = (int *)PR_MALLOC(npds * sizeof(int)); if (NULL == me->selectfd_list) { me->selectfd_count = 0; PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return -1; } me->selectfd_count = npds; } selectfd = me->selectfd_list; } FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); for (index = 0; index < npds; ++index) { PRInt16 in_flags_read = 0, in_flags_write = 0; PRInt16 out_flags_read = 0, out_flags_write = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (pds[index].in_flags & PR_POLL_READ) { in_flags_read = (pds[index].fd->methods->poll)( pds[index].fd, pds[index].in_flags & ~PR_POLL_WRITE, &out_flags_read); } if (pds[index].in_flags & PR_POLL_WRITE) { in_flags_write = (pds[index].fd->methods->poll)( pds[index].fd, pds[index].in_flags & ~PR_POLL_READ, &out_flags_write); } if ((0 != (in_flags_read & out_flags_read)) || (0 != (in_flags_write & out_flags_write))) { /* this one is ready right now */ if (0 == ready) { /* * We will return without calling the system * poll function. So zero the out_flags * fields of all the poll descriptors before * this one. */ int i; for (i = 0; i < index; i++) { pds[i].out_flags = 0; } } ready += 1; pds[index].out_flags = out_flags_read | out_flags_write; } else { /* now locate the NSPR layer at the bottom of the stack */ PRFileDesc *bottom = PR_GetIdentitiesLayer( pds[index].fd, PR_NSPR_IO_LAYER); PR_ASSERT(NULL != bottom); /* what to do about that? */ pds[index].out_flags = 0; /* pre-condition */ if ((NULL != bottom) && (_PR_FILEDESC_OPEN == bottom->secret->state)) { if (0 == ready) { PRBool add_to_rd = PR_FALSE; PRBool add_to_wr = PR_FALSE; PRBool add_to_ex = PR_FALSE; selectfd[index] = bottom->secret->md.osfd; if (in_flags_read & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_READ_SYS_READ; add_to_rd = PR_TRUE; } if (in_flags_read & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_READ_SYS_WRITE; add_to_wr = PR_TRUE; } if (in_flags_write & PR_POLL_READ) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_READ; add_to_rd = PR_TRUE; } if (in_flags_write & PR_POLL_WRITE) { pds[index].out_flags |= _PR_POLL_WRITE_SYS_WRITE; add_to_wr = PR_TRUE; } if (pds[index].in_flags & PR_POLL_EXCEPT) { add_to_ex = PR_TRUE; } if ((selectfd[index] > maxfd) && (add_to_rd || add_to_wr || add_to_ex)) { maxfd = selectfd[index]; /* * If maxfd is too large to be used with * select, fall back to calling poll. */ if (maxfd >= FD_SETSIZE) break; } if (add_to_rd) { FD_SET(bottom->secret->md.osfd, &rd); rdp = &rd; } if (add_to_wr) { FD_SET(bottom->secret->md.osfd, &wr); wrp = ≀ } if (add_to_ex) { FD_SET(bottom->secret->md.osfd, &ex); exp = &ex; } } } else { if (0 == ready) { int i; for (i = 0; i < index; i++) { pds[i].out_flags = 0; } } ready += 1; /* this will cause an abrupt return */ pds[index].out_flags = PR_POLL_NVAL; /* bogii */ } } } else { pds[index].out_flags = 0; } } if (0 == ready) { if (maxfd >= FD_SETSIZE) { /* * maxfd too large to be used with select, fall back to * calling poll */ return(_pr_poll_with_poll(pds, npds, timeout)); } switch (timeout) { case PR_INTERVAL_NO_WAIT: tv.tv_sec = 0; tv.tv_usec = 0; tvp = &tv; break; case PR_INTERVAL_NO_TIMEOUT: tvp = NULL; break; default: msecs = PR_IntervalToMilliseconds(timeout); tv.tv_sec = msecs/PR_MSEC_PER_SEC; tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC; tvp = &tv; start = PR_IntervalNow(); } retry: ready = select(maxfd + 1, rdp, wrp, exp, tvp); if (-1 == ready) { PRIntn oserror = errno; if ((EINTR == oserror) || (EAGAIN == oserror)) { if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry; else if (timeout == PR_INTERVAL_NO_WAIT) ready = 0; /* don't retry, just time out */ else { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) ready = 0; /* timed out */ else { remaining = timeout - elapsed; msecs = PR_IntervalToMilliseconds(remaining); tv.tv_sec = msecs/PR_MSEC_PER_SEC; tv.tv_usec = (msecs % PR_MSEC_PER_SEC) * PR_USEC_PER_MSEC; goto retry; } } } else if (EBADF == oserror) { /* find all the bad fds */ ready = 0; for (index = 0; index < npds; ++index) { pds[index].out_flags = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (fcntl(selectfd[index], F_GETFL, 0) == -1) { pds[index].out_flags = PR_POLL_NVAL; ready++; } } } } else _PR_MD_MAP_SELECT_ERROR(oserror); } else if (ready > 0) { for (index = 0; index < npds; ++index) { PRInt16 out_flags = 0; if ((NULL != pds[index].fd) && (0 != pds[index].in_flags)) { if (FD_ISSET(selectfd[index], &rd)) { if (pds[index].out_flags & _PR_POLL_READ_SYS_READ) { out_flags |= PR_POLL_READ; } if (pds[index].out_flags & _PR_POLL_WRITE_SYS_READ) { out_flags |= PR_POLL_WRITE; } } if (FD_ISSET(selectfd[index], &wr)) { if (pds[index].out_flags & _PR_POLL_READ_SYS_WRITE) { out_flags |= PR_POLL_READ; } if (pds[index].out_flags & _PR_POLL_WRITE_SYS_WRITE) { out_flags |= PR_POLL_WRITE; } } if (FD_ISSET(selectfd[index], &ex)) out_flags |= PR_POLL_EXCEPT; } pds[index].out_flags = out_flags; } } } } return ready; } /* _pr_poll_with_select */ #endif /* _PR_POLL_WITH_SELECT */ PR_IMPLEMENT(PRInt32) PR_Poll( PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout) { #if defined(_PR_POLL_WITH_SELECT) return(_pr_poll_with_select(pds, npds, timeout)); #else return(_pr_poll_with_poll(pds, npds, timeout)); #endif } PR_IMPLEMENT(PRDirEntry*) PR_ReadDir(PRDir *dir, PRDirFlags flags) { struct dirent *dp; if (pt_TestAbort()) return NULL; for (;;) { errno = 0; dp = readdir(dir->md.d); if (NULL == dp) { pt_MapError(_PR_MD_MAP_READDIR_ERROR, errno); return NULL; } if ((flags & PR_SKIP_DOT) && ('.' == dp->d_name[0]) && (0 == dp->d_name[1])) continue; if ((flags & PR_SKIP_DOT_DOT) && ('.' == dp->d_name[0]) && ('.' == dp->d_name[1]) && (0 == dp->d_name[2])) continue; if ((flags & PR_SKIP_HIDDEN) && ('.' == dp->d_name[0])) continue; break; } dir->d.name = dp->d_name; return &dir->d; } /* PR_ReadDir */ PR_IMPLEMENT(PRFileDesc*) PR_NewUDPSocket(void) { PRIntn domain = PF_INET; return PR_Socket(domain, SOCK_DGRAM, 0); } /* PR_NewUDPSocket */ PR_IMPLEMENT(PRFileDesc*) PR_NewTCPSocket(void) { PRIntn domain = PF_INET; return PR_Socket(domain, SOCK_STREAM, 0); } /* PR_NewTCPSocket */ PR_IMPLEMENT(PRFileDesc*) PR_OpenUDPSocket(PRIntn af) { return PR_Socket(af, SOCK_DGRAM, 0); } /* PR_NewUDPSocket */ PR_IMPLEMENT(PRFileDesc*) PR_OpenTCPSocket(PRIntn af) { return PR_Socket(af, SOCK_STREAM, 0); } /* PR_NewTCPSocket */ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPair(PRFileDesc *fds[2]) { #ifdef SYMBIAN /* * For the platforms that don't have socketpair. * * Copied from prsocket.c, with the parameter f[] renamed fds[] and the * _PR_CONNECT_DOES_NOT_BIND code removed. */ PRFileDesc *listenSock; PRNetAddr selfAddr, peerAddr; PRUint16 port; fds[0] = fds[1] = NULL; listenSock = PR_NewTCPSocket(); if (listenSock == NULL) { goto failed; } PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &selfAddr); /* BugZilla: 35408 */ if (PR_Bind(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } if (PR_GetSockName(listenSock, &selfAddr) == PR_FAILURE) { goto failed; } port = ntohs(selfAddr.inet.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { goto failed; } fds[0] = PR_NewTCPSocket(); if (fds[0] == NULL) { goto failed; } PR_InitializeNetAddr(PR_IpAddrLoopback, port, &selfAddr); /* * Only a thread is used to do the connect and accept. * I am relying on the fact that PR_Connect returns * successfully as soon as the connect request is put * into the listen queue (but before PR_Accept is called). * This is the behavior of the BSD socket code. If * connect does not return until accept is called, we * will need to create another thread to call connect. */ if (PR_Connect(fds[0], &selfAddr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { goto failed; } /* * A malicious local process may connect to the listening * socket, so we need to verify that the accepted connection * is made from our own socket fds[0]. */ if (PR_GetSockName(fds[0], &selfAddr) == PR_FAILURE) { goto failed; } fds[1] = PR_Accept(listenSock, &peerAddr, PR_INTERVAL_NO_TIMEOUT); if (fds[1] == NULL) { goto failed; } if (peerAddr.inet.port != selfAddr.inet.port) { /* the connection we accepted is not from fds[0] */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); goto failed; } PR_Close(listenSock); return PR_SUCCESS; failed: if (listenSock) { PR_Close(listenSock); } if (fds[0]) { PR_Close(fds[0]); } if (fds[1]) { PR_Close(fds[1]); } return PR_FAILURE; #else PRInt32 osfd[2]; if (pt_TestAbort()) return PR_FAILURE; if (socketpair(AF_UNIX, SOCK_STREAM, 0, osfd) == -1) { pt_MapError(_PR_MD_MAP_SOCKETPAIR_ERROR, errno); return PR_FAILURE; } fds[0] = pt_SetMethods(osfd[0], PR_DESC_SOCKET_TCP, PR_FALSE, PR_FALSE); if (fds[0] == NULL) { close(osfd[0]); close(osfd[1]); return PR_FAILURE; } fds[1] = pt_SetMethods(osfd[1], PR_DESC_SOCKET_TCP, PR_FALSE, PR_FALSE); if (fds[1] == NULL) { PR_Close(fds[0]); close(osfd[1]); return PR_FAILURE; } return PR_SUCCESS; #endif } /* PR_NewTCPSocketPair */ PR_IMPLEMENT(PRStatus) PR_CreatePipe( PRFileDesc **readPipe, PRFileDesc **writePipe ) { int pipefd[2]; if (pt_TestAbort()) return PR_FAILURE; if (pipe(pipefd) == -1) { /* XXX map pipe error */ PR_SetError(PR_UNKNOWN_ERROR, errno); return PR_FAILURE; } *readPipe = pt_SetMethods(pipefd[0], PR_DESC_PIPE, PR_FALSE, PR_FALSE); if (NULL == *readPipe) { close(pipefd[0]); close(pipefd[1]); return PR_FAILURE; } *writePipe = pt_SetMethods(pipefd[1], PR_DESC_PIPE, PR_FALSE, PR_FALSE); if (NULL == *writePipe) { PR_Close(*readPipe); close(pipefd[1]); return PR_FAILURE; } return PR_SUCCESS; } /* ** Set the inheritance attribute of a file descriptor. */ PR_IMPLEMENT(PRStatus) PR_SetFDInheritable( PRFileDesc *fd, PRBool inheritable) { /* * Only a non-layered, NSPR file descriptor can be inherited * by a child process. */ if (fd->identity != PR_NSPR_IO_LAYER) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } if (fd->secret->inheritable != inheritable) { if (fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } fd->secret->inheritable = (_PRTriStateBool) inheritable; } return PR_SUCCESS; } /*****************************************************************************/ /***************************** I/O friends methods ***************************/ /*****************************************************************************/ PR_IMPLEMENT(PRFileDesc*) PR_ImportFile(PRInt32 osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = pt_SetMethods(osfd, PR_DESC_FILE, PR_FALSE, PR_TRUE); if (NULL == fd) close(osfd); return fd; } /* PR_ImportFile */ PR_IMPLEMENT(PRFileDesc*) PR_ImportPipe(PRInt32 osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = pt_SetMethods(osfd, PR_DESC_PIPE, PR_FALSE, PR_TRUE); if (NULL == fd) close(osfd); return fd; } /* PR_ImportPipe */ PR_IMPLEMENT(PRFileDesc*) PR_ImportTCPSocket(PRInt32 osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_FALSE, PR_TRUE); if (NULL == fd) close(osfd); #ifdef _PR_NEED_SECRET_AF if (NULL != fd) fd->secret->af = PF_INET; #endif return fd; } /* PR_ImportTCPSocket */ PR_IMPLEMENT(PRFileDesc*) PR_ImportUDPSocket(PRInt32 osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = pt_SetMethods(osfd, PR_DESC_SOCKET_UDP, PR_FALSE, PR_TRUE); if (NULL == fd) close(osfd); return fd; } /* PR_ImportUDPSocket */ PR_IMPLEMENT(PRFileDesc*) PR_CreateSocketPollFd(PRInt32 osfd) { PRFileDesc *fd; if (!_pr_initialized) _PR_ImplicitInitialization(); fd = _PR_Getfd(); if (fd == NULL) PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); else { fd->secret->md.osfd = osfd; fd->secret->inheritable = _PR_TRI_FALSE; fd->secret->state = _PR_FILEDESC_OPEN; fd->methods = PR_GetSocketPollFdMethods(); } return fd; } /* PR_CreateSocketPollFD */ PR_IMPLEMENT(PRStatus) PR_DestroySocketPollFd(PRFileDesc *fd) { if (NULL == fd) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } fd->secret->state = _PR_FILEDESC_CLOSED; _PR_Putfd(fd); return PR_SUCCESS; } /* PR_DestroySocketPollFd */ PR_IMPLEMENT(PRInt32) PR_FileDesc2NativeHandle(PRFileDesc *bottom) { PRInt32 osfd = -1; bottom = (NULL == bottom) ? NULL : PR_GetIdentitiesLayer(bottom, PR_NSPR_IO_LAYER); if (NULL == bottom) PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); else osfd = bottom->secret->md.osfd; return osfd; } /* PR_FileDesc2NativeHandle */ PR_IMPLEMENT(void) PR_ChangeFileDescNativeHandle(PRFileDesc *fd, PRInt32 handle) { if (fd) fd->secret->md.osfd = handle; } /* PR_ChangeFileDescNativeHandle*/ PR_IMPLEMENT(PRStatus) PR_LockFile(PRFileDesc *fd) { PRStatus status = PR_SUCCESS; if (pt_TestAbort()) return PR_FAILURE; PR_Lock(_pr_flock_lock); while (-1 == fd->secret->lockCount) PR_WaitCondVar(_pr_flock_cv, PR_INTERVAL_NO_TIMEOUT); if (0 == fd->secret->lockCount) { fd->secret->lockCount = -1; PR_Unlock(_pr_flock_lock); status = _PR_MD_LOCKFILE(fd->secret->md.osfd); PR_Lock(_pr_flock_lock); fd->secret->lockCount = (PR_SUCCESS == status) ? 1 : 0; PR_NotifyAllCondVar(_pr_flock_cv); } else { fd->secret->lockCount += 1; } PR_Unlock(_pr_flock_lock); return status; } /* PR_LockFile */ PR_IMPLEMENT(PRStatus) PR_TLockFile(PRFileDesc *fd) { PRStatus status = PR_SUCCESS; if (pt_TestAbort()) return PR_FAILURE; PR_Lock(_pr_flock_lock); if (0 == fd->secret->lockCount) { status = _PR_MD_TLOCKFILE(fd->secret->md.osfd); if (PR_SUCCESS == status) fd->secret->lockCount = 1; } else fd->secret->lockCount += 1; PR_Unlock(_pr_flock_lock); return status; } /* PR_TLockFile */ PR_IMPLEMENT(PRStatus) PR_UnlockFile(PRFileDesc *fd) { PRStatus status = PR_SUCCESS; if (pt_TestAbort()) return PR_FAILURE; PR_Lock(_pr_flock_lock); if (fd->secret->lockCount == 1) { status = _PR_MD_UNLOCKFILE(fd->secret->md.osfd); if (PR_SUCCESS == status) fd->secret->lockCount = 0; } else fd->secret->lockCount -= 1; PR_Unlock(_pr_flock_lock); return status; } /* * The next two entry points should not be in the API, but they are * defined here for historical (or hysterical) reasons. */ PR_IMPLEMENT(PRInt32) PR_GetSysfdTableMax(void) { #if defined(AIX) || defined(SYMBIAN) return sysconf(_SC_OPEN_MAX); #else struct rlimit rlim; if ( getrlimit(RLIMIT_NOFILE, &rlim) < 0) return -1; return rlim.rlim_max; #endif } PR_IMPLEMENT(PRInt32) PR_SetSysfdTableSize(PRIntn table_size) { #if defined(AIX) || defined(SYMBIAN) return -1; #else struct rlimit rlim; PRInt32 tableMax = PR_GetSysfdTableMax(); if (tableMax < 0) return -1; rlim.rlim_max = tableMax; /* Grow as much as we can; even if too big */ if ( rlim.rlim_max < table_size ) rlim.rlim_cur = rlim.rlim_max; else rlim.rlim_cur = table_size; if ( setrlimit(RLIMIT_NOFILE, &rlim) < 0) return -1; return rlim.rlim_cur; #endif } /* * PR_Stat is supported for backward compatibility; some existing Java * code uses it. New code should use PR_GetFileInfo. */ #ifndef NO_NSPR_10_SUPPORT PR_IMPLEMENT(PRInt32) PR_Stat(const char *name, struct stat *buf) { static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_Stat", "PR_GetFileInfo"); if (pt_TestAbort()) return -1; if (-1 == stat(name, buf)) { pt_MapError(_PR_MD_MAP_STAT_ERROR, errno); return -1; } else { return 0; } } #endif /* ! NO_NSPR_10_SUPPORT */ PR_IMPLEMENT(void) PR_FD_ZERO(PR_fd_set *set) { static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_ZERO (PR_Select)", "PR_Poll"); memset(set, 0, sizeof(PR_fd_set)); } PR_IMPLEMENT(void) PR_FD_SET(PRFileDesc *fh, PR_fd_set *set) { static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_SET (PR_Select)", "PR_Poll"); PR_ASSERT( set->hsize < PR_MAX_SELECT_DESC ); set->harray[set->hsize++] = fh; } PR_IMPLEMENT(void) PR_FD_CLR(PRFileDesc *fh, PR_fd_set *set) { PRUint32 index, index2; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_CLR (PR_Select)", "PR_Poll"); for (index = 0; indexhsize; index++) if (set->harray[index] == fh) { for (index2=index; index2 < (set->hsize-1); index2++) { set->harray[index2] = set->harray[index2+1]; } set->hsize--; break; } } PR_IMPLEMENT(PRInt32) PR_FD_ISSET(PRFileDesc *fh, PR_fd_set *set) { PRUint32 index; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_ISSET (PR_Select)", "PR_Poll"); for (index = 0; indexhsize; index++) if (set->harray[index] == fh) { return 1; } return 0; } PR_IMPLEMENT(void) PR_FD_NSET(PRInt32 fd, PR_fd_set *set) { static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_NSET (PR_Select)", "PR_Poll"); PR_ASSERT( set->nsize < PR_MAX_SELECT_DESC ); set->narray[set->nsize++] = fd; } PR_IMPLEMENT(void) PR_FD_NCLR(PRInt32 fd, PR_fd_set *set) { PRUint32 index, index2; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_NCLR (PR_Select)", "PR_Poll"); for (index = 0; indexnsize; index++) if (set->narray[index] == fd) { for (index2=index; index2 < (set->nsize-1); index2++) { set->narray[index2] = set->narray[index2+1]; } set->nsize--; break; } } PR_IMPLEMENT(PRInt32) PR_FD_NISSET(PRInt32 fd, PR_fd_set *set) { PRUint32 index; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete("PR_FD_NISSET (PR_Select)", "PR_Poll"); for (index = 0; indexnsize; index++) if (set->narray[index] == fd) { return 1; } return 0; } #include #include #if !defined(HPUX) \ && !defined(LINUX) && !defined(__GNU__) && !defined(__GLIBC__) #include #endif static PRInt32 _PR_getset(PR_fd_set *pr_set, fd_set *set) { PRUint32 index; PRInt32 max = 0; if (!pr_set) return 0; FD_ZERO(set); /* First set the pr file handle osfds */ for (index=0; indexhsize; index++) { FD_SET(pr_set->harray[index]->secret->md.osfd, set); if (pr_set->harray[index]->secret->md.osfd > max) max = pr_set->harray[index]->secret->md.osfd; } /* Second set the native osfds */ for (index=0; indexnsize; index++) { FD_SET(pr_set->narray[index], set); if (pr_set->narray[index] > max) max = pr_set->narray[index]; } return max; } static void _PR_setset(PR_fd_set *pr_set, fd_set *set) { PRUint32 index, last_used; if (!pr_set) return; for (last_used=0, index=0; indexhsize; index++) { if ( FD_ISSET(pr_set->harray[index]->secret->md.osfd, set) ) { pr_set->harray[last_used++] = pr_set->harray[index]; } } pr_set->hsize = last_used; for (last_used=0, index=0; indexnsize; index++) { if ( FD_ISSET(pr_set->narray[index], set) ) { pr_set->narray[last_used++] = pr_set->narray[index]; } } pr_set->nsize = last_used; } PR_IMPLEMENT(PRInt32) PR_Select( PRInt32 unused, PR_fd_set *pr_rd, PR_fd_set *pr_wr, PR_fd_set *pr_ex, PRIntervalTime timeout) { fd_set rd, wr, ex; struct timeval tv, *tvp; PRInt32 max, max_fd; PRInt32 rv; /* * For restarting select() if it is interrupted by a Unix signal. * We use these variables to figure out how much time has elapsed * and how much of the timeout still remains. */ PRIntervalTime start, elapsed, remaining; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_Select", "PR_Poll"); FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); max_fd = _PR_getset(pr_rd, &rd); max_fd = (max = _PR_getset(pr_wr, &wr))>max_fd?max:max_fd; max_fd = (max = _PR_getset(pr_ex, &ex))>max_fd?max:max_fd; if (timeout == PR_INTERVAL_NO_TIMEOUT) { tvp = NULL; } else { tv.tv_sec = (PRInt32)PR_IntervalToSeconds(timeout); tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds( timeout - PR_SecondsToInterval(tv.tv_sec)); tvp = &tv; start = PR_IntervalNow(); } retry: rv = select(max_fd + 1, (_PRSelectFdSetArg_t) &rd, (_PRSelectFdSetArg_t) &wr, (_PRSelectFdSetArg_t) &ex, tvp); if (rv == -1 && errno == EINTR) { if (timeout == PR_INTERVAL_NO_TIMEOUT) { goto retry; } else { elapsed = (PRIntervalTime) (PR_IntervalNow() - start); if (elapsed > timeout) { rv = 0; /* timed out */ } else { remaining = timeout - elapsed; tv.tv_sec = (PRInt32)PR_IntervalToSeconds(remaining); tv.tv_usec = (PRInt32)PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); goto retry; } } } if (rv > 0) { _PR_setset(pr_rd, &rd); _PR_setset(pr_wr, &wr); _PR_setset(pr_ex, &ex); } else if (rv == -1) { pt_MapError(_PR_MD_MAP_SELECT_ERROR, errno); } return rv; } #endif /* defined(_PR_PTHREADS) */ #ifdef MOZ_UNICODE /* ================ UTF16 Interfaces ================================ */ PR_IMPLEMENT(PRFileDesc*) PR_OpenFileUTF16( const PRUnichar *name, PRIntn flags, PRIntn mode) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PR_IMPLEMENT(PRStatus) PR_CloseDirUTF16(PRDir *dir) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PR_IMPLEMENT(PRDirUTF16*) PR_OpenDirUTF16(const PRUnichar *name) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PR_IMPLEMENT(PRDirEntryUTF16*) PR_ReadDirUTF16(PRDirUTF16 *dir, PRDirFlags flags) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PR_IMPLEMENT(PRStatus) PR_GetFileInfo64UTF16(const PRUnichar *fn, PRFileInfo64 *info) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } /* ================ UTF16 Interfaces ================================ */ #endif /* MOZ_UNICODE */ /* ptio.c */ nspr-4.11/nspr/pr/src/pthreads/ptmisc.c0000644000000000000000000000162112623070344016217 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: ptmisc.c ** Descritpion: Implemenation of miscellaneous methods for pthreads */ #if defined(_PR_PTHREADS) #include "primpl.h" #include #ifdef SOLARIS #include #endif #define PT_LOG(f) void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")} void _PR_InitStacks(void) {PT_LOG("_PR_InitStacks")} PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs) { #ifdef SOLARIS thr_setconcurrency(numCPUs); #else PT_LOG("PR_SetConcurrency"); #endif } PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 flag) {PT_LOG("PR_SetThreadRecycleMode")} #endif /* defined(_PR_PTHREADS) */ /* ptmisc.c */ nspr-4.11/nspr/pr/src/pthreads/ptsynch.c0000644000000000000000000010241112623070344016407 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: ptsynch.c ** Descritpion: Implemenation for thread synchronization using pthreads ** Exports: prlock.h, prcvar.h, prmon.h, prcmon.h */ #if defined(_PR_PTHREADS) #include "primpl.h" #include "obsolete/prsem.h" #include #include #include static pthread_mutexattr_t _pt_mattr; static pthread_condattr_t _pt_cvar_attr; #if defined(DEBUG) extern PTDebug pt_debug; /* this is shared between several modules */ #if defined(_PR_DCETHREADS) static pthread_t pt_zero_tid; /* a null pthread_t (pthread_t is a struct * in DCE threads) to compare with */ #endif /* defined(_PR_DCETHREADS) */ #endif /* defined(DEBUG) */ #if defined(FREEBSD) /* * On older versions of FreeBSD, pthread_mutex_trylock returns EDEADLK. * Newer versions return EBUSY. We still need to support both. */ static int pt_pthread_mutex_is_locked(pthread_mutex_t *m) { int rv = pthread_mutex_trylock(m); return (EBUSY == rv || EDEADLK == rv); } #endif /**************************************************************/ /**************************************************************/ /*****************************LOCKS****************************/ /**************************************************************/ /**************************************************************/ void _PR_InitLocks(void) { int rv; rv = _PT_PTHREAD_MUTEXATTR_INIT(&_pt_mattr); PR_ASSERT(0 == rv); #ifdef LINUX #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) rv = pthread_mutexattr_settype(&_pt_mattr, PTHREAD_MUTEX_ADAPTIVE_NP); PR_ASSERT(0 == rv); #endif #endif rv = _PT_PTHREAD_CONDATTR_INIT(&_pt_cvar_attr); PR_ASSERT(0 == rv); } static void pt_PostNotifies(PRLock *lock, PRBool unlock) { PRIntn index, rv; _PT_Notified post; _PT_Notified *notified, *prev = NULL; /* * Time to actually notify any conditions that were affected * while the lock was held. Get a copy of the list that's in * the lock structure and then zero the original. If it's * linked to other such structures, we own that storage. */ post = lock->notified; /* a safe copy; we own the lock */ #if defined(DEBUG) memset(&lock->notified, 0, sizeof(_PT_Notified)); /* reset */ #else lock->notified.length = 0; /* these are really sufficient */ lock->notified.link = NULL; #endif /* should (may) we release lock before notifying? */ if (unlock) { rv = pthread_mutex_unlock(&lock->mutex); PR_ASSERT(0 == rv); } notified = &post; /* this is where we start */ do { for (index = 0; index < notified->length; ++index) { PRCondVar *cv = notified->cv[index].cv; PR_ASSERT(NULL != cv); PR_ASSERT(0 != notified->cv[index].times); if (-1 == notified->cv[index].times) { rv = pthread_cond_broadcast(&cv->cv); PR_ASSERT(0 == rv); } else { while (notified->cv[index].times-- > 0) { rv = pthread_cond_signal(&cv->cv); PR_ASSERT(0 == rv); } } #if defined(DEBUG) pt_debug.cvars_notified += 1; if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending)) { pt_debug.delayed_cv_deletes += 1; PR_DestroyCondVar(cv); } #else /* defined(DEBUG) */ if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending)) PR_DestroyCondVar(cv); #endif /* defined(DEBUG) */ } prev = notified; notified = notified->link; if (&post != prev) PR_DELETE(prev); } while (NULL != notified); } /* pt_PostNotifies */ PR_IMPLEMENT(PRLock*) PR_NewLock(void) { PRIntn rv; PRLock *lock; if (!_pr_initialized) _PR_ImplicitInitialization(); lock = PR_NEWZAP(PRLock); if (lock != NULL) { rv = _PT_PTHREAD_MUTEX_INIT(lock->mutex, _pt_mattr); PR_ASSERT(0 == rv); } #if defined(DEBUG) pt_debug.locks_created += 1; #endif return lock; } /* PR_NewLock */ PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock) { PRIntn rv; PR_ASSERT(NULL != lock); PR_ASSERT(PR_FALSE == lock->locked); PR_ASSERT(0 == lock->notified.length); PR_ASSERT(NULL == lock->notified.link); rv = pthread_mutex_destroy(&lock->mutex); PR_ASSERT(0 == rv); #if defined(DEBUG) memset(lock, 0xaf, sizeof(PRLock)); pt_debug.locks_destroyed += 1; #endif PR_Free(lock); } /* PR_DestroyLock */ PR_IMPLEMENT(void) PR_Lock(PRLock *lock) { /* Nb: PR_Lock must not call PR_GetCurrentThread to access the |id| or * |tid| field of the current thread's PRThread structure because * _pt_root calls PR_Lock before setting thred->id and thred->tid. */ PRIntn rv; PR_ASSERT(lock != NULL); rv = pthread_mutex_lock(&lock->mutex); PR_ASSERT(0 == rv); PR_ASSERT(0 == lock->notified.length); PR_ASSERT(NULL == lock->notified.link); PR_ASSERT(PR_FALSE == lock->locked); /* Nb: the order of the next two statements is not critical to * the correctness of PR_AssertCurrentThreadOwnsLock(), but * this particular order makes the assertion more likely to * catch errors. */ lock->owner = pthread_self(); lock->locked = PR_TRUE; #if defined(DEBUG) pt_debug.locks_acquired += 1; #endif } /* PR_Lock */ PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock) { pthread_t self = pthread_self(); PRIntn rv; PR_ASSERT(lock != NULL); PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(lock->mutex)); PR_ASSERT(PR_TRUE == lock->locked); PR_ASSERT(pthread_equal(lock->owner, self)); if (!lock->locked || !pthread_equal(lock->owner, self)) return PR_FAILURE; lock->locked = PR_FALSE; if (0 == lock->notified.length) /* shortcut */ { rv = pthread_mutex_unlock(&lock->mutex); PR_ASSERT(0 == rv); } else pt_PostNotifies(lock, PR_TRUE); #if defined(DEBUG) pt_debug.locks_released += 1; #endif return PR_SUCCESS; } /* PR_Unlock */ PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock) { /* Nb: the order of the |locked| and |owner==me| checks is not critical * to the correctness of PR_AssertCurrentThreadOwnsLock(), but * this particular order makes the assertion more likely to * catch errors. */ PR_ASSERT(lock->locked && pthread_equal(lock->owner, pthread_self())); } /**************************************************************/ /**************************************************************/ /***************************CONDITIONS*************************/ /**************************************************************/ /**************************************************************/ /* * This code is used to compute the absolute time for the wakeup. * It's moderately ugly, so it's defined here and called in a * couple of places. */ #define PT_NANOPERMICRO 1000UL #define PT_BILLION 1000000000UL static PRIntn pt_TimedWait( pthread_cond_t *cv, pthread_mutex_t *ml, PRIntervalTime timeout) { int rv; struct timeval now; struct timespec tmo; PRUint32 ticks = PR_TicksPerSecond(); tmo.tv_sec = (PRInt32)(timeout / ticks); tmo.tv_nsec = (PRInt32)(timeout - (tmo.tv_sec * ticks)); tmo.tv_nsec = (PRInt32)PR_IntervalToMicroseconds(PT_NANOPERMICRO * tmo.tv_nsec); /* pthreads wants this in absolute time, off we go ... */ (void)GETTIMEOFDAY(&now); /* that one's usecs, this one's nsecs - grrrr! */ tmo.tv_sec += now.tv_sec; tmo.tv_nsec += (PT_NANOPERMICRO * now.tv_usec); tmo.tv_sec += tmo.tv_nsec / PT_BILLION; tmo.tv_nsec %= PT_BILLION; rv = pthread_cond_timedwait(cv, ml, &tmo); /* NSPR doesn't report timeouts */ #ifdef _PR_DCETHREADS if (rv == -1) return (errno == EAGAIN) ? 0 : errno; else return rv; #else return (rv == ETIMEDOUT) ? 0 : rv; #endif } /* pt_TimedWait */ /* * Notifies just get posted to the protecting mutex. The * actual notification is done when the lock is released so that * MP systems don't contend for a lock that they can't have. */ static void pt_PostNotifyToCvar(PRCondVar *cvar, PRBool broadcast) { PRIntn index = 0; _PT_Notified *notified = &cvar->lock->notified; PR_ASSERT(PR_TRUE == cvar->lock->locked); PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self())); PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex)); while (1) { for (index = 0; index < notified->length; ++index) { if (notified->cv[index].cv == cvar) { if (broadcast) notified->cv[index].times = -1; else if (-1 != notified->cv[index].times) notified->cv[index].times += 1; return; /* we're finished */ } } /* if not full, enter new CV in this array */ if (notified->length < PT_CV_NOTIFIED_LENGTH) break; /* if there's no link, create an empty array and link it */ if (NULL == notified->link) notified->link = PR_NEWZAP(_PT_Notified); notified = notified->link; } /* A brand new entry in the array */ (void)PR_ATOMIC_INCREMENT(&cvar->notify_pending); notified->cv[index].times = (broadcast) ? -1 : 1; notified->cv[index].cv = cvar; notified->length += 1; } /* pt_PostNotifyToCvar */ PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock) { PRCondVar *cv = PR_NEW(PRCondVar); PR_ASSERT(lock != NULL); if (cv != NULL) { int rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); PR_ASSERT(0 == rv); if (0 == rv) { cv->lock = lock; cv->notify_pending = 0; #if defined(DEBUG) pt_debug.cvars_created += 1; #endif } else { PR_DELETE(cv); cv = NULL; } } return cv; } /* PR_NewCondVar */ PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar) { if (0 > PR_ATOMIC_DECREMENT(&cvar->notify_pending)) { PRIntn rv = pthread_cond_destroy(&cvar->cv); #if defined(DEBUG) PR_ASSERT(0 == rv); memset(cvar, 0xaf, sizeof(PRCondVar)); pt_debug.cvars_destroyed += 1; #else (void)rv; #endif PR_Free(cvar); } } /* PR_DestroyCondVar */ PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout) { PRIntn rv; PRThread *thred = PR_GetCurrentThread(); PR_ASSERT(cvar != NULL); /* We'd better be locked */ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(cvar->lock->mutex)); PR_ASSERT(PR_TRUE == cvar->lock->locked); /* and it better be by us */ PR_ASSERT(pthread_equal(cvar->lock->owner, pthread_self())); if (_PT_THREAD_INTERRUPTED(thred)) goto aborted; /* * The thread waiting is used for PR_Interrupt */ thred->waiting = cvar; /* this is where we're waiting */ /* * If we have pending notifies, post them now. * * This is not optimal. We're going to post these notifies * while we're holding the lock. That means on MP systems * that they are going to collide for the lock that we will * hold until we actually wait. */ if (0 != cvar->lock->notified.length) pt_PostNotifies(cvar->lock, PR_FALSE); /* * We're surrendering the lock, so clear out the locked field. */ cvar->lock->locked = PR_FALSE; if (timeout == PR_INTERVAL_NO_TIMEOUT) rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex); else rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout); /* We just got the lock back - this better be empty */ PR_ASSERT(PR_FALSE == cvar->lock->locked); cvar->lock->locked = PR_TRUE; cvar->lock->owner = pthread_self(); PR_ASSERT(0 == cvar->lock->notified.length); thred->waiting = NULL; /* and now we're not */ if (_PT_THREAD_INTERRUPTED(thred)) goto aborted; if (rv != 0) { _PR_MD_MAP_DEFAULT_ERROR(rv); return PR_FAILURE; } return PR_SUCCESS; aborted: PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); thred->state &= ~PT_THREAD_ABORTED; return PR_FAILURE; } /* PR_WaitCondVar */ PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar) { PR_ASSERT(cvar != NULL); pt_PostNotifyToCvar(cvar, PR_FALSE); return PR_SUCCESS; } /* PR_NotifyCondVar */ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar) { PR_ASSERT(cvar != NULL); pt_PostNotifyToCvar(cvar, PR_TRUE); return PR_SUCCESS; } /* PR_NotifyAllCondVar */ /**************************************************************/ /**************************************************************/ /***************************MONITORS***************************/ /**************************************************************/ /**************************************************************/ /* * Notifies just get posted to the monitor. The actual notification is done * when the monitor is fully exited so that MP systems don't contend for a * monitor that they can't enter. */ static void pt_PostNotifyToMonitor(PRMonitor *mon, PRBool broadcast) { PR_ASSERT(NULL != mon); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mon); /* mon->notifyTimes is protected by the monitor, so we don't need to * acquire mon->lock. */ if (broadcast) mon->notifyTimes = -1; else if (-1 != mon->notifyTimes) mon->notifyTimes += 1; } /* pt_PostNotifyToMonitor */ static void pt_PostNotifiesFromMonitor(pthread_cond_t *cv, PRIntn times) { PRIntn rv; /* * Time to actually notify any waits that were affected while the monitor * was entered. */ PR_ASSERT(NULL != cv); PR_ASSERT(0 != times); if (-1 == times) { rv = pthread_cond_broadcast(cv); PR_ASSERT(0 == rv); } else { while (times-- > 0) { rv = pthread_cond_signal(cv); PR_ASSERT(0 == rv); } } } /* pt_PostNotifiesFromMonitor */ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor(void) { PRMonitor *mon; int rv; if (!_pr_initialized) _PR_ImplicitInitialization(); mon = PR_NEWZAP(PRMonitor); if (mon == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } rv = _PT_PTHREAD_MUTEX_INIT(mon->lock, _pt_mattr); PR_ASSERT(0 == rv); if (0 != rv) goto error1; _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); rv = _PT_PTHREAD_COND_INIT(mon->entryCV, _pt_cvar_attr); PR_ASSERT(0 == rv); if (0 != rv) goto error2; rv = _PT_PTHREAD_COND_INIT(mon->waitCV, _pt_cvar_attr); PR_ASSERT(0 == rv); if (0 != rv) goto error3; mon->notifyTimes = 0; mon->entryCount = 0; mon->refCount = 1; mon->name = NULL; return mon; error3: pthread_cond_destroy(&mon->entryCV); error2: pthread_mutex_destroy(&mon->lock); error1: PR_Free(mon); _PR_MD_MAP_DEFAULT_ERROR(rv); return NULL; } /* PR_NewMonitor */ PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) { PRMonitor* mon = PR_NewMonitor(); if (mon) mon->name = name; return mon; } PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon) { int rv; PR_ASSERT(mon != NULL); if (PR_ATOMIC_DECREMENT(&mon->refCount) == 0) { rv = pthread_cond_destroy(&mon->waitCV); PR_ASSERT(0 == rv); rv = pthread_cond_destroy(&mon->entryCV); PR_ASSERT(0 == rv); rv = pthread_mutex_destroy(&mon->lock); PR_ASSERT(0 == rv); #if defined(DEBUG) memset(mon, 0xaf, sizeof(PRMonitor)); #endif PR_Free(mon); } } /* PR_DestroyMonitor */ /* The GC uses this; it is quite arguably a bad interface. I'm just * duplicating it for now - XXXMB */ PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon) { pthread_t self = pthread_self(); PRIntn rv; PRIntn count = 0; rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); if (pthread_equal(mon->owner, self)) count = mon->entryCount; rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); return count; } PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon) { #if defined(DEBUG) || defined(FORCE_PR_ASSERT) PRIntn rv; rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); PR_ASSERT(mon->entryCount != 0 && pthread_equal(mon->owner, pthread_self())); rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); #endif } PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon) { pthread_t self = pthread_self(); PRIntn rv; PR_ASSERT(mon != NULL); rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); if (mon->entryCount != 0) { if (pthread_equal(mon->owner, self)) goto done; while (mon->entryCount != 0) { rv = pthread_cond_wait(&mon->entryCV, &mon->lock); PR_ASSERT(0 == rv); } } /* and now I have the monitor */ PR_ASSERT(0 == mon->notifyTimes); PR_ASSERT(_PT_PTHREAD_THR_HANDLE_IS_INVALID(mon->owner)); _PT_PTHREAD_COPY_THR_HANDLE(self, mon->owner); done: mon->entryCount += 1; rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); } /* PR_EnterMonitor */ PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon) { pthread_t self = pthread_self(); PRIntn rv; PRBool notifyEntryWaiter = PR_FALSE; PRIntn notifyTimes = 0; PR_ASSERT(mon != NULL); rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); /* the entries should be > 0 and we'd better be the owner */ PR_ASSERT(mon->entryCount > 0); PR_ASSERT(pthread_equal(mon->owner, self)); if (mon->entryCount == 0 || !pthread_equal(mon->owner, self)) { rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); return PR_FAILURE; } mon->entryCount -= 1; /* reduce by one */ if (mon->entryCount == 0) { /* and if it transitioned to zero - notify an entry waiter */ /* make the owner unknown */ _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); notifyEntryWaiter = PR_TRUE; notifyTimes = mon->notifyTimes; mon->notifyTimes = 0; /* We will access the members of 'mon' after unlocking mon->lock. * Add a reference. */ PR_ATOMIC_INCREMENT(&mon->refCount); } rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); if (notifyEntryWaiter) { if (notifyTimes) pt_PostNotifiesFromMonitor(&mon->waitCV, notifyTimes); rv = pthread_cond_signal(&mon->entryCV); PR_ASSERT(0 == rv); /* We are done accessing the members of 'mon'. Release the * reference. */ PR_DestroyMonitor(mon); } return PR_SUCCESS; } /* PR_ExitMonitor */ PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime timeout) { PRStatus rv; PRUint32 saved_entries; pthread_t saved_owner; PR_ASSERT(mon != NULL); rv = pthread_mutex_lock(&mon->lock); PR_ASSERT(0 == rv); /* the entries better be positive */ PR_ASSERT(mon->entryCount > 0); /* and it better be owned by us */ PR_ASSERT(pthread_equal(mon->owner, pthread_self())); /* tuck these away 'till later */ saved_entries = mon->entryCount; mon->entryCount = 0; _PT_PTHREAD_COPY_THR_HANDLE(mon->owner, saved_owner); _PT_PTHREAD_INVALIDATE_THR_HANDLE(mon->owner); /* * If we have pending notifies, post them now. * * This is not optimal. We're going to post these notifies * while we're holding the lock. That means on MP systems * that they are going to collide for the lock that we will * hold until we actually wait. */ if (0 != mon->notifyTimes) { pt_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes); mon->notifyTimes = 0; } rv = pthread_cond_signal(&mon->entryCV); PR_ASSERT(0 == rv); if (timeout == PR_INTERVAL_NO_TIMEOUT) rv = pthread_cond_wait(&mon->waitCV, &mon->lock); else rv = pt_TimedWait(&mon->waitCV, &mon->lock, timeout); PR_ASSERT(0 == rv); while (mon->entryCount != 0) { rv = pthread_cond_wait(&mon->entryCV, &mon->lock); PR_ASSERT(0 == rv); } PR_ASSERT(0 == mon->notifyTimes); /* reinstate the interesting information */ mon->entryCount = saved_entries; _PT_PTHREAD_COPY_THR_HANDLE(saved_owner, mon->owner); rv = pthread_mutex_unlock(&mon->lock); PR_ASSERT(0 == rv); return rv; } /* PR_Wait */ PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon) { pt_PostNotifyToMonitor(mon, PR_FALSE); return PR_SUCCESS; } /* PR_Notify */ PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon) { pt_PostNotifyToMonitor(mon, PR_TRUE); return PR_SUCCESS; } /* PR_NotifyAll */ /**************************************************************/ /**************************************************************/ /**************************SEMAPHORES**************************/ /**************************************************************/ /**************************************************************/ PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *semaphore) { static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_PostSem", "locks & condition variables"); PR_Lock(semaphore->cvar->lock); PR_NotifyCondVar(semaphore->cvar); semaphore->count += 1; PR_Unlock(semaphore->cvar->lock); } /* PR_PostSem */ PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *semaphore) { PRStatus status = PR_SUCCESS; static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_WaitSem", "locks & condition variables"); PR_Lock(semaphore->cvar->lock); while ((semaphore->count == 0) && (PR_SUCCESS == status)) status = PR_WaitCondVar(semaphore->cvar, PR_INTERVAL_NO_TIMEOUT); if (PR_SUCCESS == status) semaphore->count -= 1; PR_Unlock(semaphore->cvar->lock); return status; } /* PR_WaitSem */ PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *semaphore) { static PRBool unwarned = PR_TRUE; if (unwarned) unwarned = _PR_Obsolete( "PR_DestroySem", "locks & condition variables"); PR_DestroyLock(semaphore->cvar->lock); PR_DestroyCondVar(semaphore->cvar); PR_Free(semaphore); } /* PR_DestroySem */ PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value) { PRSemaphore *semaphore; static PRBool unwarned = PR_TRUE; if (!_pr_initialized) _PR_ImplicitInitialization(); if (unwarned) unwarned = _PR_Obsolete( "PR_NewSem", "locks & condition variables"); semaphore = PR_NEWZAP(PRSemaphore); if (NULL != semaphore) { PRLock *lock = PR_NewLock(); if (NULL != lock) { semaphore->cvar = PR_NewCondVar(lock); if (NULL != semaphore->cvar) { semaphore->count = value; return semaphore; } PR_DestroyLock(lock); } PR_Free(semaphore); } return NULL; } /* * Define the interprocess named semaphore functions. * There are three implementations: * 1. POSIX semaphore based; * 2. System V semaphore based; * 3. unsupported (fails with PR_NOT_IMPLEMENTED_ERROR). */ #ifdef _PR_HAVE_POSIX_SEMAPHORES #include PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value) { PRSem *sem; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return NULL; } sem = PR_NEW(PRSem); if (NULL == sem) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } if (flags & PR_SEM_CREATE) { int oflag = O_CREAT; if (flags & PR_SEM_EXCL) oflag |= O_EXCL; sem->sem = sem_open(osname, oflag, mode, value); } else { #ifdef HPUX /* Pass 0 as the mode and value arguments to work around a bug. */ sem->sem = sem_open(osname, 0, 0, 0); #else sem->sem = sem_open(osname, 0); #endif } if ((sem_t *) -1 == sem->sem) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_Free(sem); return NULL; } return sem; } PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem) { int rv; rv = sem_wait(sem->sem); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem) { int rv; rv = sem_post(sem->sem); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem) { int rv; rv = sem_close(sem->sem); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } PR_Free(sem); return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name) { int rv; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return PR_FAILURE; } rv = sem_unlink(osname); if (0 != rv) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS; } #elif defined(_PR_HAVE_SYSV_SEMAPHORES) #include #include /* * From the semctl(2) man page in glibc 2.0 */ #if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \ || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI) \ || defined(DARWIN) || defined(SYMBIAN) /* union semun is defined by including */ #else /* according to X/OPEN we have to define it ourselves */ union semun { int val; struct semid_ds *buf; unsigned short *array; }; #endif /* * 'a' (97) is the final closing price of NSCP stock. */ #define NSPR_IPC_KEY_ID 'a' /* the id argument for ftok() */ #define NSPR_SEM_MODE 0666 PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value) { PRSem *sem; key_t key; union semun arg; struct sembuf sop; struct semid_ds seminfo; #define MAX_TRIES 60 PRIntn i; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return NULL; } /* Make sure the file exists before calling ftok. */ if (flags & PR_SEM_CREATE) { int osfd = open(osname, O_RDWR|O_CREAT, mode); if (-1 == osfd) { _PR_MD_MAP_OPEN_ERROR(errno); return NULL; } if (close(osfd) == -1) { _PR_MD_MAP_CLOSE_ERROR(errno); return NULL; } } key = ftok(osname, NSPR_IPC_KEY_ID); if ((key_t)-1 == key) { _PR_MD_MAP_DEFAULT_ERROR(errno); return NULL; } sem = PR_NEW(PRSem); if (NULL == sem) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } if (flags & PR_SEM_CREATE) { sem->semid = semget(key, 1, mode|IPC_CREAT|IPC_EXCL); if (sem->semid >= 0) { /* creator of a semaphore is responsible for initializing it */ arg.val = 0; if (semctl(sem->semid, 0, SETVAL, arg) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_Free(sem); return NULL; } /* call semop to set sem_otime to nonzero */ sop.sem_num = 0; sop.sem_op = value; sop.sem_flg = 0; if (semop(sem->semid, &sop, 1) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_Free(sem); return NULL; } return sem; } if (errno != EEXIST || flags & PR_SEM_EXCL) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_Free(sem); return NULL; } } sem->semid = semget(key, 1, NSPR_SEM_MODE); if (sem->semid == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); PR_Free(sem); return NULL; } for (i = 0; i < MAX_TRIES; i++) { arg.buf = &seminfo; semctl(sem->semid, 0, IPC_STAT, arg); if (seminfo.sem_otime != 0) break; sleep(1); } if (i == MAX_TRIES) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); PR_Free(sem); return NULL; } return sem; } PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem) { struct sembuf sop; sop.sem_num = 0; sop.sem_op = -1; sop.sem_flg = 0; if (semop(sem->semid, &sop, 1) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem) { struct sembuf sop; sop.sem_num = 0; sop.sem_op = 1; sop.sem_flg = 0; if (semop(sem->semid, &sop, 1) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem) { PR_Free(sem); return PR_SUCCESS; } PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name) { key_t key; int semid; /* On some systems (e.g., glibc 2.0) semctl requires a fourth argument */ union semun unused; char osname[PR_IPC_NAME_SIZE]; if (_PR_MakeNativeIPCName(name, osname, sizeof(osname), _PRIPCSem) == PR_FAILURE) { return PR_FAILURE; } key = ftok(osname, NSPR_IPC_KEY_ID); if ((key_t) -1 == key) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } if (unlink(osname) == -1) { _PR_MD_MAP_UNLINK_ERROR(errno); return PR_FAILURE; } semid = semget(key, 1, NSPR_SEM_MODE); if (-1 == semid) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } unused.val = 0; if (semctl(semid, 0, IPC_RMID, unused) == -1) { _PR_MD_MAP_DEFAULT_ERROR(errno); return PR_FAILURE; } return PR_SUCCESS; } #else /* neither POSIX nor System V semaphores are available */ PR_IMPLEMENT(PRSem *) PR_OpenSemaphore( const char *name, PRIntn flags, PRIntn mode, PRUintn value) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PR_IMPLEMENT(PRStatus) PR_WaitSemaphore(PRSem *sem) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) PR_PostSemaphore(PRSem *sem) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) PR_CloseSemaphore(PRSem *sem) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name) { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } #endif /* end of interprocess named semaphore functions */ /**************************************************************/ /**************************************************************/ /******************ROUTINES FOR DCE EMULATION******************/ /**************************************************************/ /**************************************************************/ #include "prpdce.h" PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock) { PRIntn rv = pthread_mutex_trylock(&lock->mutex); if (rv == PT_TRYLOCK_SUCCESS) { PR_ASSERT(PR_FALSE == lock->locked); lock->locked = PR_TRUE; lock->owner = pthread_self(); } /* XXX set error code? */ return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE; } /* PRP_TryLock */ PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void) { PRCondVar *cv; if (!_pr_initialized) _PR_ImplicitInitialization(); cv = PR_NEW(PRCondVar); if (cv != NULL) { int rv; rv = _PT_PTHREAD_COND_INIT(cv->cv, _pt_cvar_attr); PR_ASSERT(0 == rv); if (0 == rv) { cv->lock = _PR_NAKED_CV_LOCK; } else { PR_DELETE(cv); cv = NULL; } } return cv; } /* PRP_NewNakedCondVar */ PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar) { int rv; rv = pthread_cond_destroy(&cvar->cv); PR_ASSERT(0 == rv); #if defined(DEBUG) memset(cvar, 0xaf, sizeof(PRCondVar)); #endif PR_Free(cvar); } /* PRP_DestroyNakedCondVar */ PR_IMPLEMENT(PRStatus) PRP_NakedWait( PRCondVar *cvar, PRLock *ml, PRIntervalTime timeout) { PRIntn rv; PR_ASSERT(cvar != NULL); /* XXX do we really want to assert this in a naked wait? */ PR_ASSERT(_PT_PTHREAD_MUTEX_IS_LOCKED(ml->mutex)); if (timeout == PR_INTERVAL_NO_TIMEOUT) rv = pthread_cond_wait(&cvar->cv, &ml->mutex); else rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout); if (rv != 0) { _PR_MD_MAP_DEFAULT_ERROR(rv); return PR_FAILURE; } return PR_SUCCESS; } /* PRP_NakedWait */ PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar) { int rv; PR_ASSERT(cvar != NULL); rv = pthread_cond_signal(&cvar->cv); PR_ASSERT(0 == rv); return PR_SUCCESS; } /* PRP_NakedNotify */ PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar) { int rv; PR_ASSERT(cvar != NULL); rv = pthread_cond_broadcast(&cvar->cv); PR_ASSERT(0 == rv); return PR_SUCCESS; } /* PRP_NakedBroadcast */ #endif /* defined(_PR_PTHREADS) */ /* ptsynch.c */ nspr-4.11/nspr/pr/src/pthreads/ptthread.c0000644000000000000000000015051112623070344016536 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: ptthread.c ** Descritpion: Implemenation for threds using pthreds ** Exports: ptthread.h */ #if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) #include "prlog.h" #include "primpl.h" #include "prpdce.h" #include #include #include #include #include #ifdef SYMBIAN /* In Open C sched_get_priority_min/max do not work properly, so we undefine * _POSIX_THREAD_PRIORITY_SCHEDULING here. */ #undef _POSIX_THREAD_PRIORITY_SCHEDULING #endif #ifdef _PR_NICE_PRIORITY_SCHEDULING #undef _POSIX_THREAD_PRIORITY_SCHEDULING #include #ifndef HAVE_GETTID #define gettid() (syscall(SYS_gettid)) #endif #endif /* * Record whether or not we have the privilege to set the scheduling * policy and priority of threads. 0 means that privilege is available. * EPERM means that privilege is not available. */ static PRIntn pt_schedpriv = 0; extern PRLock *_pr_sleeplock; static struct _PT_Bookeeping { PRLock *ml; /* a lock to protect ourselves */ PRCondVar *cv; /* used to signal global things */ PRInt32 system, user; /* a count of the two different types */ PRUintn this_many; /* number of threads allowed for exit */ pthread_key_t key; /* thread private data key */ PRBool keyCreated; /* whether 'key' should be deleted */ PRThread *first, *last; /* list of threads we know about */ #if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0 PRInt32 minPrio, maxPrio; /* range of scheduling priorities */ #endif } pt_book = {0}; static void _pt_thread_death(void *arg); static void _pt_thread_death_internal(void *arg, PRBool callDestructors); static void init_pthread_gc_support(void); #if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0 static PRIntn pt_PriorityMap(PRThreadPriority pri) { #ifdef NTO /* This priority algorithm causes lots of problems on Neutrino * for now I have just hard coded everything to run at priority 10 * until I can come up with a new algorithm. * Jerry.Kirk@Nexwarecorp.com */ return 10; #else return pt_book.minPrio + pri * (pt_book.maxPrio - pt_book.minPrio) / PR_PRIORITY_LAST; #endif } #elif defined(_PR_NICE_PRIORITY_SCHEDULING) /* * This functions maps higher priorities to lower nice values relative to the * nice value specified in the |nice| parameter. The corresponding relative * adjustments are: * * PR_PRIORITY_LOW +1 * PR_PRIORITY_NORMAL 0 * PR_PRIORITY_HIGH -1 * PR_PRIORITY_URGENT -2 */ static int pt_RelativePriority(int nice, PRThreadPriority pri) { return nice + (1 - pri); } #endif /* ** Initialize a stack for a native pthread thread */ static void _PR_InitializeStack(PRThreadStack *ts) { if( ts && (ts->stackTop == 0) ) { ts->allocBase = (char *) &ts; ts->allocSize = ts->stackSize; /* ** Setup stackTop and stackBottom values. */ #ifdef HAVE_STACK_GROWING_UP ts->stackBottom = ts->allocBase + ts->stackSize; ts->stackTop = ts->allocBase; #else ts->stackTop = ts->allocBase; ts->stackBottom = ts->allocBase - ts->stackSize; #endif } } static void *_pt_root(void *arg) { PRIntn rv; PRThread *thred = (PRThread*)arg; PRBool detached = (thred->state & PT_THREAD_DETACHED) ? PR_TRUE : PR_FALSE; pthread_t id = pthread_self(); #ifdef _PR_NICE_PRIORITY_SCHEDULING pid_t tid; #endif #ifdef _PR_NICE_PRIORITY_SCHEDULING /* * We need to know the kernel thread ID of each thread in order to * set its nice value hence we do it here instead of at creation time. */ tid = gettid(); errno = 0; rv = getpriority(PRIO_PROCESS, 0); /* If we cannot read the main thread's nice value don't try to change the * new thread's nice value. */ if (errno == 0) { setpriority(PRIO_PROCESS, tid, pt_RelativePriority(rv, thred->priority)); } #endif /* ** DCE Threads can't detach during creation, so do it late. ** I would like to do it only here, but that doesn't seem ** to work. */ #if defined(_PR_DCETHREADS) if (detached) { /* pthread_detach() modifies its argument, so we must pass a copy */ pthread_t self = id; rv = pthread_detach(&self); PR_ASSERT(0 == rv); } #endif /* defined(_PR_DCETHREADS) */ /* Set up the thread stack information */ _PR_InitializeStack(thred->stack); /* * Set within the current thread the pointer to our object. * This object will be deleted when the thread termintates, * whether in a join or detached (see _PR_InitThreads()). */ rv = pthread_setspecific(pt_book.key, thred); PR_ASSERT(0 == rv); /* make the thread visible to the rest of the runtime */ PR_Lock(pt_book.ml); /* * Both the parent thread and this new thread set thred->id. * The new thread must ensure that thred->id is set before * it executes its startFunc. The parent thread must ensure * that thred->id is set before PR_CreateThread() returns. * Both threads set thred->id while holding pt_book.ml and * use thred->idSet to ensure thred->id is written only once. */ if (!thred->idSet) { thred->id = id; thred->idSet = PR_TRUE; } else { PR_ASSERT(pthread_equal(thred->id, id)); } #ifdef _PR_NICE_PRIORITY_SCHEDULING thred->tid = tid; PR_NotifyAllCondVar(pt_book.cv); #endif /* If this is a GCABLE thread, set its state appropriately */ if (thred->suspend & PT_THREAD_SETGCABLE) thred->state |= PT_THREAD_GCABLE; thred->suspend = 0; thred->prev = pt_book.last; if (pt_book.last) pt_book.last->next = thred; else pt_book.first = thred; thred->next = NULL; pt_book.last = thred; PR_Unlock(pt_book.ml); thred->startFunc(thred->arg); /* make visible to the client */ /* unhook the thread from the runtime */ PR_Lock(pt_book.ml); /* * At this moment, PR_CreateThread() may not have set thred->id yet. * It is safe for a detached thread to free thred only after * PR_CreateThread() has accessed thred->id and thred->idSet. */ if (detached) { while (!thred->okToDelete) PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); } if (thred->state & PT_THREAD_SYSTEM) pt_book.system -= 1; else if (--pt_book.user == pt_book.this_many) PR_NotifyAllCondVar(pt_book.cv); if (NULL == thred->prev) pt_book.first = thred->next; else thred->prev->next = thred->next; if (NULL == thred->next) pt_book.last = thred->prev; else thred->next->prev = thred->prev; PR_Unlock(pt_book.ml); /* * Here we set the pthread's backpointer to the PRThread to NULL. * Otherwise the destructor would get called eagerly as the thread * returns to the pthread runtime. The joining thread would them be * the proud possessor of a dangling reference. However, this is the * last chance to delete the object if the thread is detached, so * just let the destructor do the work. */ if (PR_FALSE == detached) { /* Call TPD destructors on this thread. */ _PR_DestroyThreadPrivate(thred); rv = pthread_setspecific(pt_book.key, NULL); PR_ASSERT(0 == rv); } return NULL; } /* _pt_root */ static PRThread* pt_AttachThread(void) { PRThread *thred = NULL; /* * NSPR must have been initialized when PR_AttachThread is called. * We cannot have PR_AttachThread call implicit initialization * because if multiple threads call PR_AttachThread simultaneously, * NSPR may be initialized more than once. * We can't call any function that calls PR_GetCurrentThread() * either (e.g., PR_SetError()) as that will result in infinite * recursion. */ if (!_pr_initialized) return NULL; /* PR_NEWZAP must not call PR_GetCurrentThread() */ thred = PR_NEWZAP(PRThread); if (NULL != thred) { int rv; thred->priority = PR_PRIORITY_NORMAL; thred->id = pthread_self(); thred->idSet = PR_TRUE; #ifdef _PR_NICE_PRIORITY_SCHEDULING thred->tid = gettid(); #endif rv = pthread_setspecific(pt_book.key, thred); PR_ASSERT(0 == rv); thred->state = PT_THREAD_GLOBAL | PT_THREAD_FOREIGN; PR_Lock(pt_book.ml); /* then put it into the list */ thred->prev = pt_book.last; if (pt_book.last) pt_book.last->next = thred; else pt_book.first = thred; thred->next = NULL; pt_book.last = thred; PR_Unlock(pt_book.ml); } return thred; /* may be NULL */ } /* pt_AttachThread */ static PRThread* _PR_CreateThread( PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize, PRBool isGCAble) { int rv; PRThread *thred; pthread_attr_t tattr; if (!_pr_initialized) _PR_ImplicitInitialization(); if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)priority) priority = PR_PRIORITY_FIRST; else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)priority) priority = PR_PRIORITY_LAST; rv = _PT_PTHREAD_ATTR_INIT(&tattr); PR_ASSERT(0 == rv); if (EPERM != pt_schedpriv) { #if !defined(_PR_DCETHREADS) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 struct sched_param schedule; #endif #if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 rv = pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED); PR_ASSERT(0 == rv); #endif /* Use the default scheduling policy */ #if defined(_PR_DCETHREADS) rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority)); PR_ASSERT(0 == rv); #elif _POSIX_THREAD_PRIORITY_SCHEDULING > 0 rv = pthread_attr_getschedparam(&tattr, &schedule); PR_ASSERT(0 == rv); schedule.sched_priority = pt_PriorityMap(priority); rv = pthread_attr_setschedparam(&tattr, &schedule); PR_ASSERT(0 == rv); #ifdef NTO rv = pthread_attr_setschedpolicy(&tattr, SCHED_RR); /* Round Robin */ PR_ASSERT(0 == rv); #endif #endif /* !defined(_PR_DCETHREADS) */ } /* * DCE threads can't set detach state before creating the thread. * AIX can't set detach late. Why can't we all just get along? */ #if !defined(_PR_DCETHREADS) rv = pthread_attr_setdetachstate(&tattr, ((PR_JOINABLE_THREAD == state) ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED)); PR_ASSERT(0 == rv); #endif /* !defined(_PR_DCETHREADS) */ /* * If stackSize is 0, we use the default pthread stack size. */ if (stackSize) { #ifdef _MD_MINIMUM_STACK_SIZE if (stackSize < _MD_MINIMUM_STACK_SIZE) stackSize = _MD_MINIMUM_STACK_SIZE; #endif rv = pthread_attr_setstacksize(&tattr, stackSize); PR_ASSERT(0 == rv); } thred = PR_NEWZAP(PRThread); if (NULL == thred) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, errno); goto done; } else { pthread_t id; thred->arg = arg; thred->startFunc = start; thred->priority = priority; if (PR_UNJOINABLE_THREAD == state) thred->state |= PT_THREAD_DETACHED; if (PR_LOCAL_THREAD == scope) scope = PR_GLOBAL_THREAD; if (PR_GLOBAL_BOUND_THREAD == scope) { #if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); if (rv) { /* * system scope not supported */ scope = PR_GLOBAL_THREAD; /* * reset scope */ rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS); PR_ASSERT(0 == rv); } #endif } if (PR_GLOBAL_THREAD == scope) thred->state |= PT_THREAD_GLOBAL; else if (PR_GLOBAL_BOUND_THREAD == scope) thred->state |= (PT_THREAD_GLOBAL | PT_THREAD_BOUND); else /* force it global */ thred->state |= PT_THREAD_GLOBAL; if (PR_SYSTEM_THREAD == type) thred->state |= PT_THREAD_SYSTEM; thred->suspend =(isGCAble) ? PT_THREAD_SETGCABLE : 0; thred->stack = PR_NEWZAP(PRThreadStack); if (thred->stack == NULL) { PRIntn oserr = errno; PR_Free(thred); /* all that work ... poof! */ PR_SetError(PR_OUT_OF_MEMORY_ERROR, oserr); thred = NULL; /* and for what? */ goto done; } thred->stack->stackSize = stackSize; thred->stack->thr = thred; #ifdef PT_NO_SIGTIMEDWAIT pthread_mutex_init(&thred->suspendResumeMutex,NULL); pthread_cond_init(&thred->suspendResumeCV,NULL); #endif /* make the thread counted to the rest of the runtime */ PR_Lock(pt_book.ml); if (PR_SYSTEM_THREAD == type) pt_book.system += 1; else pt_book.user += 1; PR_Unlock(pt_book.ml); /* * We pass a pointer to a local copy (instead of thred->id) * to pthread_create() because who knows what wacky things * pthread_create() may be doing to its argument. */ rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred); #if !defined(_PR_DCETHREADS) if (EPERM == rv) { #if defined(IRIX) if (PR_GLOBAL_BOUND_THREAD == scope) { /* * SCOPE_SYSTEM requires appropriate privilege * reset to process scope and try again */ rv = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_PROCESS); PR_ASSERT(0 == rv); thred->state &= ~PT_THREAD_BOUND; } #else /* Remember that we don't have thread scheduling privilege. */ pt_schedpriv = EPERM; PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("_PR_CreateThread: no thread scheduling privilege")); /* Try creating the thread again without setting priority. */ #if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 rv = pthread_attr_setinheritsched(&tattr, PTHREAD_INHERIT_SCHED); PR_ASSERT(0 == rv); #endif #endif /* IRIX */ rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred); } #endif if (0 != rv) { #if defined(_PR_DCETHREADS) PRIntn oserr = errno; #else PRIntn oserr = rv; #endif PR_Lock(pt_book.ml); if (thred->state & PT_THREAD_SYSTEM) pt_book.system -= 1; else if (--pt_book.user == pt_book.this_many) PR_NotifyAllCondVar(pt_book.cv); PR_Unlock(pt_book.ml); PR_Free(thred->stack); PR_Free(thred); /* all that work ... poof! */ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, oserr); thred = NULL; /* and for what? */ goto done; } PR_Lock(pt_book.ml); /* * Both the parent thread and this new thread set thred->id. * The parent thread must ensure that thred->id is set before * PR_CreateThread() returns. (See comments in _pt_root().) */ if (!thred->idSet) { thred->id = id; thred->idSet = PR_TRUE; } else { PR_ASSERT(pthread_equal(thred->id, id)); } /* * If the new thread is detached, tell it that PR_CreateThread() has * accessed thred->id and thred->idSet so it's ok to delete thred. */ if (PR_UNJOINABLE_THREAD == state) { thred->okToDelete = PR_TRUE; PR_NotifyAllCondVar(pt_book.cv); } PR_Unlock(pt_book.ml); } done: rv = _PT_PTHREAD_ATTR_DESTROY(&tattr); PR_ASSERT(0 == rv); return thred; } /* _PR_CreateThread */ PR_IMPLEMENT(PRThread*) PR_CreateThread( PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { return _PR_CreateThread( type, start, arg, priority, scope, state, stackSize, PR_FALSE); } /* PR_CreateThread */ PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble( PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { return _PR_CreateThread( type, start, arg, priority, scope, state, stackSize, PR_TRUE); } /* PR_CreateThreadGCAble */ PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thred) { return thred->environment; } /* GetExecutionEnvironment */ PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thred, void *env) { thred->environment = env; } /* SetExecutionEnvironment */ PR_IMPLEMENT(PRThread*) PR_AttachThread( PRThreadType type, PRThreadPriority priority, PRThreadStack *stack) { return PR_GetCurrentThread(); } /* PR_AttachThread */ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred) { int rv = -1; void *result = NULL; PR_ASSERT(thred != NULL); if ((0xafafafaf == thred->state) || (PT_THREAD_DETACHED == (PT_THREAD_DETACHED & thred->state)) || (PT_THREAD_FOREIGN == (PT_THREAD_FOREIGN & thred->state))) { /* * This might be a bad address, but if it isn't, the state should * either be an unjoinable thread or it's already had the object * deleted. However, the client that called join on a detached * thread deserves all the rath I can muster.... */ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); PR_LogPrint( "PR_JoinThread: %p not joinable | already smashed\n", thred); } else { pthread_t id = thred->id; rv = pthread_join(id, &result); PR_ASSERT(rv == 0 && result == NULL); if (0 == rv) { #ifdef _PR_DCETHREADS rv = pthread_detach(&id); PR_ASSERT(0 == rv); #endif /* * PR_FALSE, because the thread already called the TPD * destructors before exiting _pt_root. */ _pt_thread_death_internal(thred, PR_FALSE); } else { PRErrorCode prerror; switch (rv) { case EINVAL: /* not a joinable thread */ case ESRCH: /* no thread with given ID */ prerror = PR_INVALID_ARGUMENT_ERROR; break; case EDEADLK: /* a thread joining with itself */ prerror = PR_DEADLOCK_ERROR; break; default: prerror = PR_UNKNOWN_ERROR; break; } PR_SetError(prerror, rv); } } return (0 == rv) ? PR_SUCCESS : PR_FAILURE; } /* PR_JoinThread */ PR_IMPLEMENT(void) PR_DetachThread(void) { void *thred; int rv; _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred); if (NULL == thred) return; _pt_thread_death(thred); rv = pthread_setspecific(pt_book.key, NULL); PR_ASSERT(0 == rv); } /* PR_DetachThread */ PR_IMPLEMENT(PRThread*) PR_GetCurrentThread(void) { void *thred; if (!_pr_initialized) _PR_ImplicitInitialization(); _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred); if (NULL == thred) thred = pt_AttachThread(); PR_ASSERT(NULL != thred); return (PRThread*)thred; } /* PR_GetCurrentThread */ PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thred) { return (thred->state & PT_THREAD_BOUND) ? PR_GLOBAL_BOUND_THREAD : PR_GLOBAL_THREAD; } /* PR_GetThreadScope() */ PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thred) { return (thred->state & PT_THREAD_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD; } PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thred) { return (thred->state & PT_THREAD_DETACHED) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD; } /* PR_GetThreadState */ PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thred) { PR_ASSERT(thred != NULL); return thred->priority; } /* PR_GetThreadPriority */ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri) { PRIntn rv; PR_ASSERT(NULL != thred); if ((PRIntn)PR_PRIORITY_FIRST > (PRIntn)newPri) newPri = PR_PRIORITY_FIRST; else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)newPri) newPri = PR_PRIORITY_LAST; #if defined(_PR_DCETHREADS) rv = pthread_setprio(thred->id, pt_PriorityMap(newPri)); /* pthread_setprio returns the old priority */ #elif _POSIX_THREAD_PRIORITY_SCHEDULING > 0 if (EPERM != pt_schedpriv) { int policy; struct sched_param schedule; rv = pthread_getschedparam(thred->id, &policy, &schedule); if(0 == rv) { schedule.sched_priority = pt_PriorityMap(newPri); rv = pthread_setschedparam(thred->id, policy, &schedule); if (EPERM == rv) { pt_schedpriv = EPERM; PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_SetThreadPriority: no thread scheduling privilege")); } } if (rv != 0) rv = -1; } #elif defined(_PR_NICE_PRIORITY_SCHEDULING) PR_Lock(pt_book.ml); while (thred->tid == 0) PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(pt_book.ml); errno = 0; rv = getpriority(PRIO_PROCESS, 0); /* Do not proceed unless we know the main thread's nice value. */ if (errno == 0) { rv = setpriority(PRIO_PROCESS, thred->tid, pt_RelativePriority(rv, newPri)); if (rv == -1) { /* We don't set pt_schedpriv to EPERM in case errno == EPERM * because adjusting the nice value might be permitted for certain * ranges but not for others. */ PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_SetThreadPriority: setpriority failed with error %d", errno)); } } #else (void)rv; /* rv is unused */ #endif thred->priority = newPri; } /* PR_SetThreadPriority */ PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thred) { /* ** If the target thread indicates that it's waiting, ** find the condition and broadcast to it. Broadcast ** since we don't know which thread (if there are more ** than one). This sounds risky, but clients must ** test their invariants when resumed from a wait and ** I don't expect very many threads to be waiting on ** a single condition and I don't expect interrupt to ** be used very often. ** ** I don't know why I thought this would work. Must have ** been one of those weaker momements after I'd been ** smelling the vapors. ** ** Even with the followng changes it is possible that ** the pointer to the condition variable is pointing ** at a bogus value. Will the unerlying code detect ** that? */ PRCondVar *cv; PR_ASSERT(NULL != thred); if (NULL == thred) return PR_FAILURE; thred->state |= PT_THREAD_ABORTED; cv = thred->waiting; if ((NULL != cv) && !thred->interrupt_blocked) { PRIntn rv; (void)PR_ATOMIC_INCREMENT(&cv->notify_pending); rv = pthread_cond_broadcast(&cv->cv); PR_ASSERT(0 == rv); if (0 > PR_ATOMIC_DECREMENT(&cv->notify_pending)) PR_DestroyCondVar(cv); } return PR_SUCCESS; } /* PR_Interrupt */ PR_IMPLEMENT(void) PR_ClearInterrupt(void) { PRThread *me = PR_GetCurrentThread(); me->state &= ~PT_THREAD_ABORTED; } /* PR_ClearInterrupt */ PR_IMPLEMENT(void) PR_BlockInterrupt(void) { PRThread *me = PR_GetCurrentThread(); _PT_THREAD_BLOCK_INTERRUPT(me); } /* PR_BlockInterrupt */ PR_IMPLEMENT(void) PR_UnblockInterrupt(void) { PRThread *me = PR_GetCurrentThread(); _PT_THREAD_UNBLOCK_INTERRUPT(me); } /* PR_UnblockInterrupt */ PR_IMPLEMENT(PRStatus) PR_Yield(void) { static PRBool warning = PR_TRUE; if (warning) warning = _PR_Obsolete( "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)"); return PR_Sleep(PR_INTERVAL_NO_WAIT); } PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime ticks) { PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); if (PR_INTERVAL_NO_WAIT == ticks) { _PT_PTHREAD_YIELD(); } else { PRCondVar *cv; PRIntervalTime timein; timein = PR_IntervalNow(); cv = PR_NewCondVar(_pr_sleeplock); PR_ASSERT(cv != NULL); PR_Lock(_pr_sleeplock); do { PRIntervalTime now = PR_IntervalNow(); PRIntervalTime delta = now - timein; if (delta > ticks) break; rv = PR_WaitCondVar(cv, ticks - delta); } while (PR_SUCCESS == rv); PR_Unlock(_pr_sleeplock); PR_DestroyCondVar(cv); } return rv; } /* PR_Sleep */ static void _pt_thread_death(void *arg) { void *thred; int rv; _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred); if (NULL == thred) { /* * Have PR_GetCurrentThread return the expected value to the * destructors. */ rv = pthread_setspecific(pt_book.key, arg); PR_ASSERT(0 == rv); } /* PR_TRUE for: call destructors */ _pt_thread_death_internal(arg, PR_TRUE); if (NULL == thred) { rv = pthread_setspecific(pt_book.key, NULL); PR_ASSERT(0 == rv); } } static void _pt_thread_death_internal(void *arg, PRBool callDestructors) { PRThread *thred = (PRThread*)arg; if (thred->state & (PT_THREAD_FOREIGN|PT_THREAD_PRIMORD)) { PR_Lock(pt_book.ml); if (NULL == thred->prev) pt_book.first = thred->next; else thred->prev->next = thred->next; if (NULL == thred->next) pt_book.last = thred->prev; else thred->next->prev = thred->prev; PR_Unlock(pt_book.ml); } if (callDestructors) _PR_DestroyThreadPrivate(thred); PR_Free(thred->privateData); if (NULL != thred->errorString) PR_Free(thred->errorString); if (NULL != thred->name) PR_Free(thred->name); PR_Free(thred->stack); if (NULL != thred->syspoll_list) PR_Free(thred->syspoll_list); #if defined(_PR_POLL_WITH_SELECT) if (NULL != thred->selectfd_list) PR_Free(thred->selectfd_list); #endif #if defined(DEBUG) memset(thred, 0xaf, sizeof(PRThread)); #endif /* defined(DEBUG) */ PR_Free(thred); } /* _pt_thread_death */ void _PR_InitThreads( PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) { int rv; PRThread *thred; PR_ASSERT(priority == PR_PRIORITY_NORMAL); #ifdef _PR_NEED_PTHREAD_INIT /* * On BSD/OS (3.1 and 4.0), the pthread subsystem is lazily * initialized, but pthread_self() fails to initialize * pthreads and hence returns a null thread ID if invoked * by the primordial thread before any other pthread call. * So we explicitly initialize pthreads here. */ pthread_init(); #endif #if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0 #if defined(FREEBSD) { pthread_attr_t attr; int policy; /* get the min and max priorities of the default policy */ pthread_attr_init(&attr); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); pthread_attr_getschedpolicy(&attr, &policy); pt_book.minPrio = sched_get_priority_min(policy); PR_ASSERT(-1 != pt_book.minPrio); pt_book.maxPrio = sched_get_priority_max(policy); PR_ASSERT(-1 != pt_book.maxPrio); pthread_attr_destroy(&attr); } #else /* ** These might be function evaluations */ pt_book.minPrio = PT_PRIO_MIN; pt_book.maxPrio = PT_PRIO_MAX; #endif #endif PR_ASSERT(NULL == pt_book.ml); pt_book.ml = PR_NewLock(); PR_ASSERT(NULL != pt_book.ml); pt_book.cv = PR_NewCondVar(pt_book.ml); PR_ASSERT(NULL != pt_book.cv); thred = PR_NEWZAP(PRThread); PR_ASSERT(NULL != thred); thred->arg = NULL; thred->startFunc = NULL; thred->priority = priority; thred->id = pthread_self(); thred->idSet = PR_TRUE; #ifdef _PR_NICE_PRIORITY_SCHEDULING thred->tid = gettid(); #endif thred->state = (PT_THREAD_DETACHED | PT_THREAD_PRIMORD); if (PR_SYSTEM_THREAD == type) { thred->state |= PT_THREAD_SYSTEM; pt_book.system += 1; pt_book.this_many = 0; } else { pt_book.user += 1; pt_book.this_many = 1; } thred->next = thred->prev = NULL; pt_book.first = pt_book.last = thred; thred->stack = PR_NEWZAP(PRThreadStack); PR_ASSERT(thred->stack != NULL); thred->stack->stackSize = 0; thred->stack->thr = thred; _PR_InitializeStack(thred->stack); /* * Create a key for our use to store a backpointer in the pthread * to our PRThread object. This object gets deleted when the thread * returns from its root in the case of a detached thread. Other * threads delete the objects in Join. * * NB: The destructor logic seems to have a bug so it isn't used. * NBB: Oh really? I'm going to give it a spin - AOF 19 June 1998. * More info - the problem is that pthreads calls the destructor * eagerly as the thread returns from its root, rather than lazily * after the thread is joined. Therefore, threads that are joining * and holding PRThread references are actually holding pointers to * nothing. */ rv = _PT_PTHREAD_KEY_CREATE(&pt_book.key, _pt_thread_death); if (0 != rv) PR_Assert("0 == rv", __FILE__, __LINE__); pt_book.keyCreated = PR_TRUE; rv = pthread_setspecific(pt_book.key, thred); PR_ASSERT(0 == rv); } /* _PR_InitThreads */ #ifdef __GNUC__ /* * GCC supports the constructor and destructor attributes as of * version 2.5. */ static void _PR_Fini(void) __attribute__ ((destructor)); #elif defined(__SUNPRO_C) /* * Sun Studio compiler */ #pragma fini(_PR_Fini) static void _PR_Fini(void); #elif defined(HPUX) /* * Current versions of HP C compiler define __HP_cc. * HP C compiler A.11.01.20 doesn't define __HP_cc. */ #if defined(__ia64) || defined(_LP64) #pragma FINI "_PR_Fini" static void _PR_Fini(void); #else /* * Only HP-UX 10.x style initializers are supported in 32-bit links. * Need to use the +I PR_HPUX10xInit linker option. */ #include static void _PR_Fini(void); void PR_HPUX10xInit(shl_t handle, int loading) { /* * This function is called when a shared library is loaded as well * as when the shared library is unloaded. Note that it may not * be called when the user's program terminates. * * handle is the shl_load API handle for the shared library being * initialized. * * loading is non-zero at startup and zero at termination. */ if (loading) { /* ... do some initializations ... */ } else { _PR_Fini(); } } #endif #elif defined(AIX) /* Need to use the -binitfini::_PR_Fini linker option. */ #endif void _PR_Fini(void) { void *thred; int rv; if (!_pr_initialized) { /* Either NSPR was never successfully initialized or * PR_Cleanup has been called already. */ if (pt_book.keyCreated) { rv = pthread_key_delete(pt_book.key); PR_ASSERT(0 == rv); pt_book.keyCreated = PR_FALSE; } return; } _PT_PTHREAD_GETSPECIFIC(pt_book.key, thred); if (NULL != thred) { /* * PR_FALSE, because it is unsafe to call back to the * thread private data destructors at final cleanup. */ _pt_thread_death_internal(thred, PR_FALSE); rv = pthread_setspecific(pt_book.key, NULL); PR_ASSERT(0 == rv); } rv = pthread_key_delete(pt_book.key); PR_ASSERT(0 == rv); pt_book.keyCreated = PR_FALSE; /* TODO: free other resources used by NSPR */ /* _pr_initialized = PR_FALSE; */ } /* _PR_Fini */ PR_IMPLEMENT(PRStatus) PR_Cleanup(void) { PRThread *me = PR_GetCurrentThread(); int rv; PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("PR_Cleanup: shutting down NSPR")); PR_ASSERT(me->state & PT_THREAD_PRIMORD); if (me->state & PT_THREAD_PRIMORD) { PR_Lock(pt_book.ml); while (pt_book.user > pt_book.this_many) PR_WaitCondVar(pt_book.cv, PR_INTERVAL_NO_TIMEOUT); if (me->state & PT_THREAD_SYSTEM) pt_book.system -= 1; else pt_book.user -= 1; PR_Unlock(pt_book.ml); _PR_MD_EARLY_CLEANUP(); _PR_CleanupMW(); _PR_CleanupTime(); _PR_CleanupDtoa(); _PR_CleanupCallOnce(); _PR_ShutdownLinker(); _PR_LogCleanup(); _PR_CleanupNet(); /* Close all the fd's before calling _PR_CleanupIO */ _PR_CleanupIO(); _PR_CleanupCMon(); _pt_thread_death(me); rv = pthread_setspecific(pt_book.key, NULL); PR_ASSERT(0 == rv); /* * I am not sure if it's safe to delete the cv and lock here, * since there may still be "system" threads around. If this * call isn't immediately prior to exiting, then there's a * problem. */ if (0 == pt_book.system) { PR_DestroyCondVar(pt_book.cv); pt_book.cv = NULL; PR_DestroyLock(pt_book.ml); pt_book.ml = NULL; } PR_DestroyLock(_pr_sleeplock); _pr_sleeplock = NULL; _PR_CleanupLayerCache(); _PR_CleanupEnv(); #ifdef _PR_ZONE_ALLOCATOR _PR_DestroyZones(); #endif _pr_initialized = PR_FALSE; return PR_SUCCESS; } return PR_FAILURE; } /* PR_Cleanup */ PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status) { _exit(status); } PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred) { #if defined(_PR_DCETHREADS) return (PRUint32)&thred->id; /* this is really a sham! */ #else return (PRUint32)thred->id; /* and I don't know what they will do with it */ #endif } /* * $$$ * The following two thread-to-processor affinity functions are not * yet implemented for pthreads. By the way, these functions should return * PRStatus rather than PRInt32 to indicate the success/failure status. * $$$ */ PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask) { return 0; /* not implemented */ } PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask ) { return 0; /* not implemented */ } PR_IMPLEMENT(void) PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg) { thread->dump = dump; thread->dumpArg = arg; } /* * Garbage collection support follows. */ #if defined(_PR_DCETHREADS) /* * statics for Garbage Collection support. We don't need to protect these * signal masks since the garbage collector itself is protected by a lock * and multiple threads will not be garbage collecting at the same time. */ static sigset_t javagc_vtalarm_sigmask; static sigset_t javagc_intsoff_sigmask; #else /* defined(_PR_DCETHREADS) */ /* a bogus signal mask for forcing a timed wait */ /* Not so bogus in AIX as we really do a sigwait */ static sigset_t sigwait_set; static struct timespec onemillisec = {0, 1000000L}; #ifndef PT_NO_SIGTIMEDWAIT static struct timespec hundredmillisec = {0, 100000000L}; #endif static void suspend_signal_handler(PRIntn sig); #ifdef PT_NO_SIGTIMEDWAIT static void null_signal_handler(PRIntn sig); #endif #endif /* defined(_PR_DCETHREADS) */ /* * Linux pthreads use SIGUSR1 and SIGUSR2 internally, which * conflict with the use of these two signals in our GC support. * So we don't know how to support GC on Linux pthreads. */ static void init_pthread_gc_support(void) { #ifndef SYMBIAN PRIntn rv; #if defined(_PR_DCETHREADS) rv = sigemptyset(&javagc_vtalarm_sigmask); PR_ASSERT(0 == rv); rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM); PR_ASSERT(0 == rv); #else /* defined(_PR_DCETHREADS) */ { struct sigaction sigact_usr2; sigact_usr2.sa_handler = suspend_signal_handler; sigact_usr2.sa_flags = SA_RESTART; sigemptyset (&sigact_usr2.sa_mask); rv = sigaction (SIGUSR2, &sigact_usr2, NULL); PR_ASSERT(0 == rv); sigemptyset (&sigwait_set); #if defined(PT_NO_SIGTIMEDWAIT) sigaddset (&sigwait_set, SIGUSR1); #else sigaddset (&sigwait_set, SIGUSR2); #endif /* defined(PT_NO_SIGTIMEDWAIT) */ } #if defined(PT_NO_SIGTIMEDWAIT) { struct sigaction sigact_null; sigact_null.sa_handler = null_signal_handler; sigact_null.sa_flags = SA_RESTART; sigemptyset (&sigact_null.sa_mask); rv = sigaction (SIGUSR1, &sigact_null, NULL); PR_ASSERT(0 ==rv); } #endif /* defined(PT_NO_SIGTIMEDWAIT) */ #endif /* defined(_PR_DCETHREADS) */ #endif /* SYMBIAN */ } PR_IMPLEMENT(void) PR_SetThreadGCAble(void) { PR_Lock(pt_book.ml); PR_GetCurrentThread()->state |= PT_THREAD_GCABLE; PR_Unlock(pt_book.ml); } PR_IMPLEMENT(void) PR_ClearThreadGCAble(void) { PR_Lock(pt_book.ml); PR_GetCurrentThread()->state &= (~PT_THREAD_GCABLE); PR_Unlock(pt_book.ml); } #if defined(DEBUG) static PRBool suspendAllOn = PR_FALSE; #endif static PRBool suspendAllSuspended = PR_FALSE; PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg) { PRIntn count = 0; PRStatus rv = PR_SUCCESS; PRThread* thred = pt_book.first; #if defined(DEBUG) || defined(FORCE_PR_ASSERT) #if !defined(_PR_DCETHREADS) PRThread *me = PR_GetCurrentThread(); #endif #endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_EnumerateThreads\n")); /* * $$$ * Need to suspend all threads other than me before doing this. * This is really a gross and disgusting thing to do. The only * good thing is that since all other threads are suspended, holding * the lock during a callback seems like child's play. * $$$ */ PR_ASSERT(suspendAllOn); while (thred != NULL) { /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking * qp->next after applying the function "func". In particular, "func" * might remove the thread from the queue and put it into another one in * which case qp->next no longer points to the next entry in the original * queue. * * To get around this problem, we save qp->next in qp_next before applying * "func" and use that saved value as the next value after applying "func". */ PRThread* next = thred->next; if (_PT_IS_GCABLE_THREAD(thred)) { #if !defined(_PR_DCETHREADS) PR_ASSERT((thred == me) || (thred->suspend & PT_THREAD_SUSPENDED)); #endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("In PR_EnumerateThreads callback thread %p thid = %X\n", thred, thred->id)); rv = func(thred, count++, arg); if (rv != PR_SUCCESS) return rv; } thred = next; } PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_EnumerateThreads count = %d \n", count)); return rv; } /* PR_EnumerateThreads */ /* * PR_SuspendAll and PR_ResumeAll are called during garbage collection. The strategy * we use is to send a SIGUSR2 signal to every gc able thread that we intend to suspend. * The signal handler will record the stack pointer and will block until resumed by * the resume call. Since the signal handler is the last routine called for the * suspended thread, the stack pointer will also serve as a place where all the * registers have been saved on the stack for the previously executing routines. * * Through global variables, we also make sure that PR_Suspend and PR_Resume does not * proceed until the thread is suspended or resumed. */ #if !defined(_PR_DCETHREADS) /* * In the signal handler, we can not use condition variable notify or wait. * This does not work consistently across all pthread platforms. We also can not * use locking since that does not seem to work reliably across platforms. * Only thing we can do is yielding while testing for a global condition * to change. This does work on pthread supported platforms. We may have * to play with priortities if there are any problems detected. */ /* * In AIX, you cannot use ANY pthread calls in the signal handler except perhaps * pthread_yield. But that is horribly inefficient. Hence we use only sigwait, no * sigtimedwait is available. We need to use another user signal, SIGUSR1. Actually * SIGUSR1 is also used by exec in Java. So our usage here breaks the exec in Java, * for AIX. You cannot use pthread_cond_wait or pthread_delay_np in the signal * handler as all synchronization mechanisms just break down. */ #if defined(PT_NO_SIGTIMEDWAIT) static void null_signal_handler(PRIntn sig) { return; } #endif static void suspend_signal_handler(PRIntn sig) { PRThread *me = PR_GetCurrentThread(); PR_ASSERT(me != NULL); PR_ASSERT(_PT_IS_GCABLE_THREAD(me)); PR_ASSERT((me->suspend & PT_THREAD_SUSPENDED) == 0); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin suspend_signal_handler thred %p thread id = %X\n", me, me->id)); /* * save stack pointer */ me->sp = &me; /* At this point, the thread's stack pointer has been saved, And it is going to enter a wait loop until it is resumed. So it is _really_ suspended */ me->suspend |= PT_THREAD_SUSPENDED; /* * now, block current thread */ #if defined(PT_NO_SIGTIMEDWAIT) pthread_cond_signal(&me->suspendResumeCV); while (me->suspend & PT_THREAD_SUSPENDED) { #if !defined(FREEBSD) && !defined(NETBSD) && !defined(OPENBSD) \ && !defined(BSDI) && !defined(UNIXWARE) \ && !defined(DARWIN) && !defined(RISCOS) \ && !defined(SYMBIAN) /*XXX*/ PRIntn rv; sigwait(&sigwait_set, &rv); #endif } me->suspend |= PT_THREAD_RESUMED; pthread_cond_signal(&me->suspendResumeCV); #else /* defined(PT_NO_SIGTIMEDWAIT) */ while (me->suspend & PT_THREAD_SUSPENDED) { PRIntn rv = sigtimedwait(&sigwait_set, NULL, &hundredmillisec); PR_ASSERT(-1 == rv); } me->suspend |= PT_THREAD_RESUMED; #endif /* * At this point, thread has been resumed, so set a global condition. * The ResumeAll needs to know that this has really been resumed. * So the signal handler sets a flag which PR_ResumeAll will reset. * The PR_ResumeAll must reset this flag ... */ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End suspend_signal_handler thred = %p tid = %X\n", me, me->id)); } /* suspend_signal_handler */ static void pt_SuspendSet(PRThread *thred) { PRIntn rv; PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("pt_SuspendSet thred %p thread id = %X\n", thred, thred->id)); /* * Check the thread state and signal the thread to suspend */ PR_ASSERT((thred->suspend & PT_THREAD_SUSPENDED) == 0); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("doing pthread_kill in pt_SuspendSet thred %p tid = %X\n", thred, thred->id)); #if defined(SYMBIAN) /* All signal group functions are not implemented in Symbian OS */ rv = 0; #else rv = pthread_kill (thred->id, SIGUSR2); #endif PR_ASSERT(0 == rv); } static void pt_SuspendTest(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin pt_SuspendTest thred %p thread id = %X\n", thred, thred->id)); /* * Wait for the thread to be really suspended. This happens when the * suspend signal handler stores the stack pointer and sets the state * to suspended. */ #if defined(PT_NO_SIGTIMEDWAIT) pthread_mutex_lock(&thred->suspendResumeMutex); while ((thred->suspend & PT_THREAD_SUSPENDED) == 0) { pthread_cond_timedwait( &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec); } pthread_mutex_unlock(&thred->suspendResumeMutex); #else while ((thred->suspend & PT_THREAD_SUSPENDED) == 0) { PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec); PR_ASSERT(-1 == rv); } #endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End pt_SuspendTest thred %p tid %X\n", thred, thred->id)); } /* pt_SuspendTest */ static void pt_ResumeSet(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("pt_ResumeSet thred %p thread id = %X\n", thred, thred->id)); /* * Clear the global state and set the thread state so that it will * continue past yield loop in the suspend signal handler */ PR_ASSERT(thred->suspend & PT_THREAD_SUSPENDED); thred->suspend &= ~PT_THREAD_SUSPENDED; #if defined(PT_NO_SIGTIMEDWAIT) #if defined(SYMBIAN) /* All signal group functions are not implemented in Symbian OS */ #else pthread_kill(thred->id, SIGUSR1); #endif #endif } /* pt_ResumeSet */ static void pt_ResumeTest(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin pt_ResumeTest thred %p thread id = %X\n", thred, thred->id)); /* * Wait for the threads resume state to change * to indicate it is really resumed */ #if defined(PT_NO_SIGTIMEDWAIT) pthread_mutex_lock(&thred->suspendResumeMutex); while ((thred->suspend & PT_THREAD_RESUMED) == 0) { pthread_cond_timedwait( &thred->suspendResumeCV, &thred->suspendResumeMutex, &onemillisec); } pthread_mutex_unlock(&thred->suspendResumeMutex); #else while ((thred->suspend & PT_THREAD_RESUMED) == 0) { PRIntn rv = sigtimedwait(&sigwait_set, NULL, &onemillisec); PR_ASSERT(-1 == rv); } #endif thred->suspend &= ~PT_THREAD_RESUMED; PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ( "End pt_ResumeTest thred %p tid %X\n", thred, thred->id)); } /* pt_ResumeTest */ static pthread_once_t pt_gc_support_control = PTHREAD_ONCE_INIT; PR_IMPLEMENT(void) PR_SuspendAll(void) { #ifdef DEBUG PRIntervalTime stime, etime; #endif PRThread* thred = pt_book.first; PRThread *me = PR_GetCurrentThread(); int rv; rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support); PR_ASSERT(0 == rv); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n")); /* * Stop all threads which are marked GC able. */ PR_Lock(pt_book.ml); #ifdef DEBUG suspendAllOn = PR_TRUE; stime = PR_IntervalNow(); #endif while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) pt_SuspendSet(thred); thred = thred->next; } /* Wait till they are really suspended */ thred = pt_book.first; while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) pt_SuspendTest(thred); thred = thred->next; } suspendAllSuspended = PR_TRUE; #ifdef DEBUG etime = PR_IntervalNow(); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,\ ("End PR_SuspendAll (time %dms)\n", PR_IntervalToMilliseconds(etime - stime))); #endif } /* PR_SuspendAll */ PR_IMPLEMENT(void) PR_ResumeAll(void) { #ifdef DEBUG PRIntervalTime stime, etime; #endif PRThread* thred = pt_book.first; PRThread *me = PR_GetCurrentThread(); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n")); /* * Resume all previously suspended GC able threads. */ suspendAllSuspended = PR_FALSE; #ifdef DEBUG stime = PR_IntervalNow(); #endif while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) pt_ResumeSet(thred); thred = thred->next; } thred = pt_book.first; while (thred != NULL) { if ((thred != me) && _PT_IS_GCABLE_THREAD(thred)) pt_ResumeTest(thred); thred = thred->next; } PR_Unlock(pt_book.ml); #ifdef DEBUG suspendAllOn = PR_FALSE; etime = PR_IntervalNow(); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll (time %dms)\n", PR_IntervalToMilliseconds(etime - stime))); #endif } /* PR_ResumeAll */ /* Return the stack pointer for the given thread- used by the GC */ PR_IMPLEMENT(void *)PR_GetSP(PRThread *thred) { PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("in PR_GetSP thred %p thid = %X, sp = %p\n", thred, thred->id, thred->sp)); return thred->sp; } /* PR_GetSP */ #else /* !defined(_PR_DCETHREADS) */ static pthread_once_t pt_gc_support_control = pthread_once_init; /* * For DCE threads, there is no pthread_kill or a way of suspending or resuming a * particular thread. We will just disable the preemption (virtual timer alarm) and * let the executing thread finish the garbage collection. This stops all other threads * (GC able or not) and is very inefficient but there is no other choice. */ PR_IMPLEMENT(void) PR_SuspendAll() { PRIntn rv; rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support); PR_ASSERT(0 == rv); /* returns -1 on failure */ #ifdef DEBUG suspendAllOn = PR_TRUE; #endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n")); /* * turn off preemption - i.e add virtual alarm signal to the set of * blocking signals */ rv = sigprocmask( SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask); PR_ASSERT(0 == rv); suspendAllSuspended = PR_TRUE; PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_SuspendAll\n")); } /* PR_SuspendAll */ PR_IMPLEMENT(void) PR_ResumeAll() { PRIntn rv; suspendAllSuspended = PR_FALSE; PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n")); /* turn on preemption - i.e re-enable virtual alarm signal */ rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL); PR_ASSERT(0 == rv); #ifdef DEBUG suspendAllOn = PR_FALSE; #endif PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n")); } /* PR_ResumeAll */ /* Return the stack pointer for the given thread- used by the GC */ PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred) { pthread_t tid = thred->id; char *thread_tcb, *top_sp; /* * For HPUX DCE threads, pthread_t is a struct with the * following three fields (see pthread.h, dce/cma.h): * cma_t_address field1; * short int field2; * short int field3; * where cma_t_address is typedef'd to be either void* * or char*. */ PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n")); thread_tcb = (char*)tid.field1; top_sp = *(char**)(thread_tcb + 128); PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %p \n", top_sp)); return top_sp; } /* PR_GetSP */ #endif /* !defined(_PR_DCETHREADS) */ PR_IMPLEMENT(PRStatus) PR_SetCurrentThreadName(const char *name) { PRThread *thread; size_t nameLen; int result; if (!name) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } thread = PR_GetCurrentThread(); if (!thread) return PR_FAILURE; PR_Free(thread->name); nameLen = strlen(name); thread->name = (char *)PR_Malloc(nameLen + 1); if (!thread->name) return PR_FAILURE; memcpy(thread->name, name, nameLen + 1); #if defined(OPENBSD) || defined(FREEBSD) result = pthread_set_name_np(thread->id, name); #else /* not BSD */ /* * On OSX, pthread_setname_np is only available in 10.6 or later, so test * for it at runtime. It also may not be available on all linux distros. */ #if defined(DARWIN) int (*dynamic_pthread_setname_np)(const char*); #else int (*dynamic_pthread_setname_np)(pthread_t, const char*); #endif *(void**)(&dynamic_pthread_setname_np) = dlsym(RTLD_DEFAULT, "pthread_setname_np"); if (!dynamic_pthread_setname_np) return PR_SUCCESS; /* * The 15-character name length limit is an experimentally determined * length of a null-terminated string that most linux distros and OS X * accept as an argument to pthread_setname_np. Otherwise the E2BIG * error is returned by the function. */ #define SETNAME_LENGTH_CONSTRAINT 15 #define SETNAME_FRAGMENT1_LENGTH (SETNAME_LENGTH_CONSTRAINT >> 1) #define SETNAME_FRAGMENT2_LENGTH \ (SETNAME_LENGTH_CONSTRAINT - SETNAME_FRAGMENT1_LENGTH - 1) char name_dup[SETNAME_LENGTH_CONSTRAINT + 1]; if (nameLen > SETNAME_LENGTH_CONSTRAINT) { memcpy(name_dup, name, SETNAME_FRAGMENT1_LENGTH); name_dup[SETNAME_FRAGMENT1_LENGTH] = '~'; /* Note that this also copies the null terminator. */ memcpy(name_dup + SETNAME_FRAGMENT1_LENGTH + 1, name + nameLen - SETNAME_FRAGMENT2_LENGTH, SETNAME_FRAGMENT2_LENGTH + 1); name = name_dup; } #if defined(DARWIN) result = dynamic_pthread_setname_np(name); #else result = dynamic_pthread_setname_np(thread->id, name); #endif #endif /* not BSD */ if (result) { PR_SetError(PR_UNKNOWN_ERROR, result); return PR_FAILURE; } return PR_SUCCESS; } PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) { if (!thread) return NULL; return thread->name; } #endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */ /* ptthread.c */ nspr-4.11/nspr/pr/src/threads/.cvsignore0000644000000000000000000000001112623070344016364 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/threads/Makefile.in0000644000000000000000000000170512623070344016444 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifdef USE_PTHREADS DIRS = else ifdef USE_BTHREADS DIRS = else DIRS = combined endif endif ifdef USE_PTHREADS CSRCS = \ prcmon.c \ prrwlock.c \ prtpd.c \ $(NULL) else ifdef USE_BTHREADS CSRCS = \ prcmon.c \ prrwlock.c \ prtpd.c \ $(NULL) else CSRCS = \ prcmon.c \ prdump.c \ prmon.c \ prsem.c \ prrwlock.c \ prcthr.c \ prtpd.c \ $(NULL) endif endif TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/threads/combined/.cvsignore0000644000000000000000000000001112623070344020144 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/src/threads/combined/Makefile.in0000644000000000000000000000136012623070344020221 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifdef USE_PTHREADS CSRCS = \ $(NULL) else CSRCS = \ prucpu.c \ prucv.c \ prulock.c \ pruthr.c \ prustack.c \ $(NULL) endif TARGETS = $(OBJS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private DEFINES += -D_NSPR_BUILD_ include $(topsrcdir)/config/rules.mk export:: $(TARGETS) nspr-4.11/nspr/pr/src/threads/combined/README0000644000000000000000000000630612623070344017041 0ustar 00000000000000NSPR 2.0 evolution ------------------ Phase 1- today Currently (Oct 10, 1996) NSPR 2.0 has two modes. Either _PR_NTHREAD is defined, in which case the PR_CreateThread() call always creates a native kernel thread, or _PR_NTHREAD is not defined and PR_CreateThread() always creates user level threads within the single, original process. This source code is reflected in two directories, nspr20/pr/src/threads/native, and nspr20/pr/src/threads/user. Although the PR_CreateThread() function has a paramter to specify the "scope" of a thread, this parameter is not yet used- except on solaris where it uses it to specify bound vs unbound threads. Phase 2 - next week The next step is to provide a combination of user and native threads. The idea, of course, is to have some small number of native threads and each of those threads be able to run user level threads. The number of native threads created will most likely be proportional to the number of CPUs in the system. For this reason, the specific set of native threads which are used to run the user-level threads will be called "CPU" threads. The user level threads which will be run on the CPU threads are able to run on any of the CPU threads available, and over the course of a user-level thread's lifetime, it may drift from one CPU thread to another. All user-level threads will compete for processing time via a single run queue. Creation of a CPU thread will be primarily controlled by NSPR itself or by the user running a function PR_Concurrency(). The details of PR_Concurrency() have not yet been worked out; but the idea is that the user can specify to NSPR how many CPU threads are desired. In this system, user-level threads are created by using PR_CreateThread() and specifying the PR_LOCAL_SCOPE option. LOCAL_SCOPE indicates that the thread will be under the control of the "local" scheduler. Creating threads with GLOBAL_SCOPE, on the other hand will create a thread which is under the control of the system's scheduler. In otherwords, this creates a native thread which is not a CPU thread; it runs a single thread task and never has more than one task to run. LOCAL_SCOPE is much like creating a Solaris unbound thread, while GLOBAL_SCOPE is similar to creating a Solaris bound thread. To implement this architecture, the source code will still maintain the "user" and "native" directories which is has today. However a third directory "combined" will also exist. To compile a version of NSPR which only creates native threads, the user can define _PR_NTHREAD. For exclusive user-level threads, do not define _PR_NTHREAD. To get the combined threads, define _PR_NTHREAD and _PR_USE_CPUS. Phase 3 - later than next week The goal is to eliminate the 3 directories. Once these three models are in place, the remaining work will be to eliminate the native and user thread directories for all platforms, so that the entire thread model is contained within what is today called the "combined" model. This new and glorious source code will attempt to make the "combined" model on any platforms which provide the necessary underlying native threading, but will also be capable of using exclusive user-level threads on systems which don't have native threads. nspr-4.11/nspr/pr/src/threads/combined/prucpu.c0000644000000000000000000002617012623070344017644 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" _PRCPU *_pr_primordialCPU = NULL; PRInt32 _pr_md_idle_cpus; /* number of idle cpus */ /* * The idle threads in MxN models increment/decrement _pr_md_idle_cpus. * If _PR_HAVE_ATOMIC_OPS is not defined, they can't use the atomic * increment/decrement routines (which are based on PR_Lock/PR_Unlock), * because PR_Lock asserts that the calling thread is not an idle thread. * So we use a _MDLock to protect _pr_md_idle_cpus. */ #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) #ifndef _PR_HAVE_ATOMIC_OPS static _MDLock _pr_md_idle_cpus_lock; #endif #endif PRUintn _pr_numCPU; PRInt32 _pr_cpus_exit; PRUint32 _pr_cpu_affinity_mask = 0; #if !defined (_PR_GLOBAL_THREADS_ONLY) static PRUintn _pr_cpuID; static void PR_CALLBACK _PR_CPU_Idle(void *); static _PRCPU *_PR_CreateCPU(void); static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread); #if !defined(_PR_LOCAL_THREADS_ONLY) static void _PR_RunCPU(void *arg); #endif void _PR_InitCPUs() { PRThread *me = _PR_MD_CURRENT_THREAD(); if (_native_threads_only) return; _pr_cpuID = 0; _MD_NEW_LOCK( &_pr_cpuLock); #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) #ifndef _PR_HAVE_ATOMIC_OPS _MD_NEW_LOCK(&_pr_md_idle_cpus_lock); #endif #endif #ifdef _PR_LOCAL_THREADS_ONLY #ifdef HAVE_CUSTOM_USER_THREADS _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me); #endif /* Now start the first CPU. */ _pr_primordialCPU = _PR_CreateCPU(); _pr_numCPU = 1; _PR_StartCPU(_pr_primordialCPU, me); _PR_MD_SET_CURRENT_CPU(_pr_primordialCPU); /* Initialize cpu for current thread (could be different from me) */ _PR_MD_CURRENT_THREAD()->cpu = _pr_primordialCPU; _PR_MD_SET_LAST_THREAD(me); #else /* Combined MxN model */ _pr_primordialCPU = _PR_CreateCPU(); _pr_numCPU = 1; _PR_CreateThread(PR_SYSTEM_THREAD, _PR_RunCPU, _pr_primordialCPU, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0, _PR_IDLE_THREAD); #endif /* _PR_LOCAL_THREADS_ONLY */ _PR_MD_INIT_CPUS(); } #ifdef WINNT /* * Right now this function merely stops the CPUs and does * not do any other cleanup. * * It is only implemented for WINNT because bug 161998 only * affects the WINNT version of NSPR, but it would be nice * to implement this function for other platforms too. */ void _PR_CleanupCPUs(void) { PRUintn i; PRCList *qp; _PRCPU *cpu; _pr_cpus_exit = 1; for (i = 0; i < _pr_numCPU; i++) { _PR_MD_WAKEUP_WAITER(NULL); } for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { cpu = _PR_CPU_PTR(qp); _PR_MD_JOIN_THREAD(&cpu->thread->md); } } #endif static _PRCPUQueue *_PR_CreateCPUQueue(void) { PRInt32 index; _PRCPUQueue *cpuQueue; cpuQueue = PR_NEWZAP(_PRCPUQueue); _MD_NEW_LOCK( &cpuQueue->runQLock ); _MD_NEW_LOCK( &cpuQueue->sleepQLock ); _MD_NEW_LOCK( &cpuQueue->miscQLock ); for (index = 0; index < PR_ARRAY_SIZE(cpuQueue->runQ); index++) PR_INIT_CLIST( &(cpuQueue->runQ[index]) ); PR_INIT_CLIST( &(cpuQueue->sleepQ) ); PR_INIT_CLIST( &(cpuQueue->pauseQ) ); PR_INIT_CLIST( &(cpuQueue->suspendQ) ); PR_INIT_CLIST( &(cpuQueue->waitingToJoinQ) ); cpuQueue->numCPUs = 1; return cpuQueue; } /* * Create a new CPU. * * This function initializes enough of the _PRCPU structure so * that it can be accessed safely by a global thread or another * CPU. This function does not create the native thread that * will run the CPU nor does it initialize the parts of _PRCPU * that must be initialized by that native thread. * * The reason we cannot simply have the native thread create * and fully initialize a new CPU is that we need to be able to * create a usable _pr_primordialCPU in _PR_InitCPUs without * assuming that the primordial CPU thread we created can run * during NSPR initialization. For example, on Windows while * new threads can be created by DllMain, they won't be able * to run during DLL initialization. If NSPR is initialized * by DllMain, the primordial CPU thread won't run until DLL * initialization is finished. */ static _PRCPU *_PR_CreateCPU(void) { _PRCPU *cpu; cpu = PR_NEWZAP(_PRCPU); if (cpu) { cpu->queue = _PR_CreateCPUQueue(); if (!cpu->queue) { PR_DELETE(cpu); return NULL; } } return cpu; } /* * Start a new CPU. * * 'cpu' is a _PRCPU structure created by _PR_CreateCPU(). * 'thread' is the native thread that will run the CPU. * * If this function fails, 'cpu' is destroyed. */ static PRStatus _PR_StartCPU(_PRCPU *cpu, PRThread *thread) { /* ** Start a new cpu. The assumption this code makes is that the ** underlying operating system creates a stack to go with the new ** native thread. That stack will be used by the cpu when pausing. */ PR_ASSERT(!_native_threads_only); cpu->last_clock = PR_IntervalNow(); /* Before we create any threads on this CPU we have to * set the current CPU */ _PR_MD_SET_CURRENT_CPU(cpu); _PR_MD_INIT_RUNNING_CPU(cpu); thread->cpu = cpu; cpu->idle_thread = _PR_CreateThread(PR_SYSTEM_THREAD, _PR_CPU_Idle, (void *)cpu, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0, _PR_IDLE_THREAD); if (!cpu->idle_thread) { /* didn't clean up CPU queue XXXMB */ PR_DELETE(cpu); return PR_FAILURE; } PR_ASSERT(cpu->idle_thread->cpu == cpu); cpu->idle_thread->no_sched = 0; cpu->thread = thread; if (_pr_cpu_affinity_mask) PR_SetThreadAffinityMask(thread, _pr_cpu_affinity_mask); /* Created and started a new CPU */ _PR_CPU_LIST_LOCK(); cpu->id = _pr_cpuID++; PR_APPEND_LINK(&cpu->links, &_PR_CPUQ()); _PR_CPU_LIST_UNLOCK(); return PR_SUCCESS; } #if !defined(_PR_GLOBAL_THREADS_ONLY) && !defined(_PR_LOCAL_THREADS_ONLY) /* ** This code is used during a cpu's initial creation. */ static void _PR_RunCPU(void *arg) { _PRCPU *cpu = (_PRCPU *)arg; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(NULL != me); /* * _PR_StartCPU calls _PR_CreateThread to create the * idle thread. Because _PR_CreateThread calls PR_Lock, * the current thread has to remain a global thread * during the _PR_StartCPU call so that it can wait for * the lock if the lock is held by another thread. If * we clear the _PR_GLOBAL_SCOPE flag in * _PR_MD_CREATE_PRIMORDIAL_THREAD, the current thread * will be treated as a local thread and have trouble * waiting for the lock because the CPU is not fully * constructed yet. * * After the CPU is started, it is safe to mark the * current thread as a local thread. */ #ifdef HAVE_CUSTOM_USER_THREADS _PR_MD_CREATE_PRIMORDIAL_USER_THREAD(me); #endif me->no_sched = 1; _PR_StartCPU(cpu, me); #ifdef HAVE_CUSTOM_USER_THREADS me->flags &= (~_PR_GLOBAL_SCOPE); #endif _PR_MD_SET_CURRENT_CPU(cpu); _PR_MD_SET_CURRENT_THREAD(cpu->thread); me->cpu = cpu; while(1) { PRInt32 is; if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_MD_START_INTERRUPTS(); _PR_MD_SWITCH_CONTEXT(me); } } #endif static void PR_CALLBACK _PR_CPU_Idle(void *_cpu) { _PRCPU *cpu = (_PRCPU *)_cpu; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(NULL != me); me->cpu = cpu; cpu->idle_thread = me; if (_MD_LAST_THREAD()) _MD_LAST_THREAD()->no_sched = 0; if (!_PR_IS_NATIVE_THREAD(me)) _PR_MD_SET_INTSOFF(0); while(1) { PRInt32 is; PRIntervalTime timeout; if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_RUNQ_LOCK(cpu); #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) #ifdef _PR_HAVE_ATOMIC_OPS _PR_MD_ATOMIC_INCREMENT(&_pr_md_idle_cpus); #else _PR_MD_LOCK(&_pr_md_idle_cpus_lock); _pr_md_idle_cpus++; _PR_MD_UNLOCK(&_pr_md_idle_cpus_lock); #endif /* _PR_HAVE_ATOMIC_OPS */ #endif /* If someone on runq; do a nonblocking PAUSECPU */ if (_PR_RUNQREADYMASK(me->cpu) != 0) { _PR_RUNQ_UNLOCK(cpu); timeout = PR_INTERVAL_NO_WAIT; } else { _PR_RUNQ_UNLOCK(cpu); _PR_SLEEPQ_LOCK(cpu); if (PR_CLIST_IS_EMPTY(&_PR_SLEEPQ(me->cpu))) { timeout = PR_INTERVAL_NO_TIMEOUT; } else { PRThread *wakeThread; wakeThread = _PR_THREAD_PTR(_PR_SLEEPQ(me->cpu).next); timeout = wakeThread->sleep; } _PR_SLEEPQ_UNLOCK(cpu); } /* Wait for an IO to complete */ (void)_PR_MD_PAUSE_CPU(timeout); #ifdef WINNT if (_pr_cpus_exit) { /* _PR_CleanupCPUs tells us to exit */ _PR_MD_END_THREAD(); } #endif #if !defined(_PR_LOCAL_THREADS_ONLY) && !defined(_PR_GLOBAL_THREADS_ONLY) #ifdef _PR_HAVE_ATOMIC_OPS _PR_MD_ATOMIC_DECREMENT(&_pr_md_idle_cpus); #else _PR_MD_LOCK(&_pr_md_idle_cpus_lock); _pr_md_idle_cpus--; _PR_MD_UNLOCK(&_pr_md_idle_cpus_lock); #endif /* _PR_HAVE_ATOMIC_OPS */ #endif _PR_ClockInterrupt(); /* Now schedule any thread that is on the runq * INTS must be OFF when calling PR_Schedule() */ me->state = _PR_RUNNABLE; _PR_MD_SWITCH_CONTEXT(me); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); } } #endif /* _PR_GLOBAL_THREADS_ONLY */ PR_IMPLEMENT(void) PR_SetConcurrency(PRUintn numCPUs) { #if defined(_PR_GLOBAL_THREADS_ONLY) || defined(_PR_LOCAL_THREADS_ONLY) /* do nothing */ #else /* combined, MxN thread model */ PRUintn newCPU; _PRCPU *cpu; PRThread *thr; if (!_pr_initialized) _PR_ImplicitInitialization(); if (_native_threads_only) return; _PR_CPU_LIST_LOCK(); if (_pr_numCPU < numCPUs) { newCPU = numCPUs - _pr_numCPU; _pr_numCPU = numCPUs; } else newCPU = 0; _PR_CPU_LIST_UNLOCK(); for (; newCPU; newCPU--) { cpu = _PR_CreateCPU(); thr = _PR_CreateThread(PR_SYSTEM_THREAD, _PR_RunCPU, cpu, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0, _PR_IDLE_THREAD); } #endif } PR_IMPLEMENT(_PRCPU *) _PR_GetPrimordialCPU(void) { if (_pr_primordialCPU) return _pr_primordialCPU; else return _PR_MD_CURRENT_CPU(); } nspr-4.11/nspr/pr/src/threads/combined/prucv.c0000644000000000000000000004450312623070344017465 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include "prinrval.h" #include "prtypes.h" #if defined(WIN95) /* ** Some local variables report warnings on Win95 because the code paths ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. ** The pragma suppresses the warning. ** */ #pragma warning(disable : 4101) #endif /* ** Notify one thread that it has finished waiting on a condition variable ** Caller must hold the _PR_CVAR_LOCK(cv) */ PRBool _PR_NotifyThread (PRThread *thread, PRThread *me) { PRBool rv; PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); _PR_THREAD_LOCK(thread); PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); if ( !_PR_IS_NATIVE_THREAD(thread) ) { if (thread->wait.cvar != NULL) { thread->wait.cvar = NULL; _PR_SLEEPQ_LOCK(thread->cpu); /* The notify and timeout can collide; in which case both may * attempt to delete from the sleepQ; only let one do it. */ if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) _PR_DEL_SLEEPQ(thread, PR_TRUE); _PR_SLEEPQ_UNLOCK(thread->cpu); if (thread->flags & _PR_SUSPENDING) { /* * set thread state to SUSPENDED; a Resume operation * on the thread will move it to the runQ */ thread->state = _PR_SUSPENDED; _PR_MISCQ_LOCK(thread->cpu); _PR_ADD_SUSPENDQ(thread, thread->cpu); _PR_MISCQ_UNLOCK(thread->cpu); _PR_THREAD_UNLOCK(thread); } else { /* Make thread runnable */ thread->state = _PR_RUNNABLE; _PR_THREAD_UNLOCK(thread); _PR_AddThreadToRunQ(me, thread); _PR_MD_WAKEUP_WAITER(thread); } rv = PR_TRUE; } else { /* Thread has already been notified */ _PR_THREAD_UNLOCK(thread); rv = PR_FALSE; } } else { /* If the thread is a native thread */ if (thread->wait.cvar) { thread->wait.cvar = NULL; if (thread->flags & _PR_SUSPENDING) { /* * set thread state to SUSPENDED; a Resume operation * on the thread will enable the thread to run */ thread->state = _PR_SUSPENDED; } else thread->state = _PR_RUNNING; _PR_THREAD_UNLOCK(thread); _PR_MD_WAKEUP_WAITER(thread); rv = PR_TRUE; } else { _PR_THREAD_UNLOCK(thread); rv = PR_FALSE; } } return rv; } /* * Notify thread waiting on cvar; called when thread is interrupted * The thread lock is held on entry and released before return */ void _PR_NotifyLockedThread (PRThread *thread) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRCondVar *cvar; PRThreadPriority pri; if ( !_PR_IS_NATIVE_THREAD(me)) PR_ASSERT(_PR_MD_GET_INTSOFF() != 0); cvar = thread->wait.cvar; thread->wait.cvar = NULL; _PR_THREAD_UNLOCK(thread); _PR_CVAR_LOCK(cvar); _PR_THREAD_LOCK(thread); if (!_PR_IS_NATIVE_THREAD(thread)) { _PR_SLEEPQ_LOCK(thread->cpu); /* The notify and timeout can collide; in which case both may * attempt to delete from the sleepQ; only let one do it. */ if (thread->flags & (_PR_ON_SLEEPQ|_PR_ON_PAUSEQ)) _PR_DEL_SLEEPQ(thread, PR_TRUE); _PR_SLEEPQ_UNLOCK(thread->cpu); /* Make thread runnable */ pri = thread->priority; thread->state = _PR_RUNNABLE; PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); _PR_AddThreadToRunQ(me, thread); _PR_THREAD_UNLOCK(thread); _PR_MD_WAKEUP_WAITER(thread); } else { if (thread->flags & _PR_SUSPENDING) { /* * set thread state to SUSPENDED; a Resume operation * on the thread will enable the thread to run */ thread->state = _PR_SUSPENDED; } else thread->state = _PR_RUNNING; _PR_THREAD_UNLOCK(thread); _PR_MD_WAKEUP_WAITER(thread); } _PR_CVAR_UNLOCK(cvar); return; } /* ** Make the given thread wait for the given condition variable */ PRStatus _PR_WaitCondVar( PRThread *thread, PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout) { PRIntn is; PRStatus rv = PR_SUCCESS; PR_ASSERT(thread == _PR_MD_CURRENT_THREAD()); PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); #ifdef _PR_GLOBAL_THREADS_ONLY if (_PR_PENDING_INTERRUPT(thread)) { PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); thread->flags &= ~_PR_INTERRUPT; return PR_FAILURE; } thread->wait.cvar = cvar; lock->owner = NULL; _PR_MD_WAIT_CV(&cvar->md,&lock->ilock, timeout); thread->wait.cvar = NULL; lock->owner = thread; if (_PR_PENDING_INTERRUPT(thread)) { PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); thread->flags &= ~_PR_INTERRUPT; return PR_FAILURE; } return PR_SUCCESS; #else /* _PR_GLOBAL_THREADS_ONLY */ if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_INTSOFF(is); _PR_CVAR_LOCK(cvar); _PR_THREAD_LOCK(thread); if (_PR_PENDING_INTERRUPT(thread)) { PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); thread->flags &= ~_PR_INTERRUPT; _PR_CVAR_UNLOCK(cvar); _PR_THREAD_UNLOCK(thread); if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_INTSON(is); return PR_FAILURE; } thread->state = _PR_COND_WAIT; thread->wait.cvar = cvar; /* ** Put the caller thread on the condition variable's wait Q */ PR_APPEND_LINK(&thread->waitQLinks, &cvar->condQ); /* Note- for global scope threads, we don't put them on the * global sleepQ, so each global thread must put itself * to sleep only for the time it wants to. */ if ( !_PR_IS_NATIVE_THREAD(thread) ) { _PR_SLEEPQ_LOCK(thread->cpu); _PR_ADD_SLEEPQ(thread, timeout); _PR_SLEEPQ_UNLOCK(thread->cpu); } _PR_CVAR_UNLOCK(cvar); _PR_THREAD_UNLOCK(thread); /* ** Release lock protecting the condition variable and thereby giving time ** to the next thread which can potentially notify on the condition variable */ PR_Unlock(lock); PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_Wait: cvar=%p waiting for %d", cvar, timeout)); rv = _PR_MD_WAIT(thread, timeout); _PR_CVAR_LOCK(cvar); PR_REMOVE_LINK(&thread->waitQLinks); _PR_CVAR_UNLOCK(cvar); PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_Wait: cvar=%p done waiting", cvar)); if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_INTSON(is); /* Acquire lock again that we had just relinquished */ PR_Lock(lock); if (_PR_PENDING_INTERRUPT(thread)) { PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); thread->flags &= ~_PR_INTERRUPT; return PR_FAILURE; } return rv; #endif /* _PR_GLOBAL_THREADS_ONLY */ } void _PR_NotifyCondVar(PRCondVar *cvar, PRThread *me) { #ifdef _PR_GLOBAL_THREADS_ONLY _PR_MD_NOTIFY_CV(&cvar->md, &cvar->lock->ilock); #else /* _PR_GLOBAL_THREADS_ONLY */ PRCList *q; PRIntn is; if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); _PR_CVAR_LOCK(cvar); q = cvar->condQ.next; while (q != &cvar->condQ) { PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("_PR_NotifyCondVar: cvar=%p", cvar)); if (_PR_THREAD_CONDQ_PTR(q)->wait.cvar) { if (_PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me) == PR_TRUE) break; } q = q->next; } _PR_CVAR_UNLOCK(cvar); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); #endif /* _PR_GLOBAL_THREADS_ONLY */ } /* ** Cndition variable debugging log info. */ PRUint32 _PR_CondVarToString(PRCondVar *cvar, char *buf, PRUint32 buflen) { PRUint32 nb; if (cvar->lock->owner) { nb = PR_snprintf(buf, buflen, "[%p] owner=%ld[%p]", cvar, cvar->lock->owner->id, cvar->lock->owner); } else { nb = PR_snprintf(buf, buflen, "[%p]", cvar); } return nb; } /* ** Expire condition variable waits that are ready to expire. "now" is the current ** time. */ void _PR_ClockInterrupt(void) { PRThread *thread, *me = _PR_MD_CURRENT_THREAD(); _PRCPU *cpu = me->cpu; PRIntervalTime elapsed, now; PR_ASSERT(_PR_MD_GET_INTSOFF() != 0); /* Figure out how much time elapsed since the last clock tick */ now = PR_IntervalNow(); elapsed = now - cpu->last_clock; cpu->last_clock = now; PR_LOG(_pr_clock_lm, PR_LOG_MAX, ("ExpireWaits: elapsed=%lld usec", elapsed)); while(1) { _PR_SLEEPQ_LOCK(cpu); if (_PR_SLEEPQ(cpu).next == &_PR_SLEEPQ(cpu)) { _PR_SLEEPQ_UNLOCK(cpu); break; } thread = _PR_THREAD_PTR(_PR_SLEEPQ(cpu).next); PR_ASSERT(thread->cpu == cpu); if (elapsed < thread->sleep) { thread->sleep -= elapsed; _PR_SLEEPQMAX(thread->cpu) -= elapsed; _PR_SLEEPQ_UNLOCK(cpu); break; } _PR_SLEEPQ_UNLOCK(cpu); PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread)); _PR_THREAD_LOCK(thread); if (thread->cpu != cpu) { /* ** The thread was switched to another CPU ** between the time we unlocked the sleep ** queue and the time we acquired the thread ** lock, so it is none of our business now. */ _PR_THREAD_UNLOCK(thread); continue; } /* ** Consume this sleeper's amount of elapsed time from the elapsed ** time value. The next remaining piece of elapsed time will be ** available for the next sleeping thread's timer. */ _PR_SLEEPQ_LOCK(cpu); PR_ASSERT(!(thread->flags & _PR_ON_PAUSEQ)); if (thread->flags & _PR_ON_SLEEPQ) { _PR_DEL_SLEEPQ(thread, PR_FALSE); elapsed -= thread->sleep; _PR_SLEEPQ_UNLOCK(cpu); } else { /* Thread was already handled; Go get another one */ _PR_SLEEPQ_UNLOCK(cpu); _PR_THREAD_UNLOCK(thread); continue; } /* Notify the thread waiting on the condition variable */ if (thread->flags & _PR_SUSPENDING) { PR_ASSERT((thread->state == _PR_IO_WAIT) || (thread->state == _PR_COND_WAIT)); /* ** Thread is suspended and its condition timeout ** expired. Transfer thread from sleepQ to suspendQ. */ thread->wait.cvar = NULL; _PR_MISCQ_LOCK(cpu); thread->state = _PR_SUSPENDED; _PR_ADD_SUSPENDQ(thread, cpu); _PR_MISCQ_UNLOCK(cpu); } else { if (thread->wait.cvar) { PRThreadPriority pri; /* Do work very similar to what _PR_NotifyThread does */ PR_ASSERT( !_PR_IS_NATIVE_THREAD(thread) ); /* Make thread runnable */ pri = thread->priority; thread->state = _PR_RUNNABLE; PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); PR_ASSERT(thread->cpu == cpu); _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thread, cpu, pri); _PR_RUNQ_UNLOCK(cpu); if (pri > me->priority) _PR_SET_RESCHED_FLAG(); thread->wait.cvar = NULL; _PR_MD_WAKEUP_WAITER(thread); } else if (thread->io_pending == PR_TRUE) { /* Need to put IO sleeper back on runq */ int pri = thread->priority; thread->io_suspended = PR_TRUE; #ifdef WINNT /* * For NT, record the cpu on which I/O was issued * I/O cancellation is done on the same cpu */ thread->md.thr_bound_cpu = cpu; #endif PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); PR_ASSERT(thread->cpu == cpu); thread->state = _PR_RUNNABLE; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thread, cpu, pri); _PR_RUNQ_UNLOCK(cpu); } } _PR_THREAD_UNLOCK(thread); } } /************************************************************************/ /* ** Create a new condition variable. ** "lock" is the lock to use with the condition variable. ** ** Condition variables are synchronization objects that threads can use ** to wait for some condition to occur. ** ** This may fail if memory is tight or if some operating system resource ** is low. */ PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock) { PRCondVar *cvar; cvar = PR_NEWZAP(PRCondVar); if (cvar) { if (_PR_InitCondVar(cvar, lock) != PR_SUCCESS) { PR_DELETE(cvar); return NULL; } } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return cvar; } PRStatus _PR_InitCondVar(PRCondVar *cvar, PRLock *lock) { PR_ASSERT(lock != NULL); #ifdef _PR_GLOBAL_THREADS_ONLY if(_PR_MD_NEW_CV(&cvar->md)) { PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return PR_FAILURE; } #endif if (_PR_MD_NEW_LOCK(&(cvar->ilock)) != PR_SUCCESS) { PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return PR_FAILURE; } cvar->lock = lock; PR_INIT_CLIST(&cvar->condQ); return PR_SUCCESS; } /* ** Destroy a condition variable. There must be no thread ** waiting on the condvar. The caller is responsible for guaranteeing ** that the condvar is no longer in use. ** */ PR_IMPLEMENT(void) PR_DestroyCondVar(PRCondVar *cvar) { _PR_FreeCondVar(cvar); PR_DELETE(cvar); } void _PR_FreeCondVar(PRCondVar *cvar) { PR_ASSERT(cvar->condQ.next == &cvar->condQ); #ifdef _PR_GLOBAL_THREADS_ONLY _PR_MD_FREE_CV(&cvar->md); #endif _PR_MD_FREE_LOCK(&(cvar->ilock)); } /* ** Wait for a notify on the condition variable. Sleep for "tiemout" amount ** of ticks (if "timeout" is zero then the sleep is indefinite). While ** the thread is waiting it unlocks lock. When the wait has ** finished the thread regains control of the condition variable after ** locking the associated lock. ** ** The thread waiting on the condvar will be resumed when the condvar is ** notified (assuming the thread is the next in line to receive the ** notify) or when the timeout elapses. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable or the thread has been interrupted. */ extern PRThread *suspendAllThread; PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(cvar->lock->owner == me); PR_ASSERT(me != suspendAllThread); if (cvar->lock->owner != me) return PR_FAILURE; return _PR_WaitCondVar(me, cvar, cvar->lock, timeout); } /* ** Notify the highest priority thread waiting on the condition ** variable. If a thread is waiting on the condition variable (using ** PR_Wait) then it is awakened and begins waiting on the lock. */ PR_IMPLEMENT(PRStatus) PR_NotifyCondVar(PRCondVar *cvar) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(cvar->lock->owner == me); PR_ASSERT(me != suspendAllThread); if (cvar->lock->owner != me) return PR_FAILURE; _PR_NotifyCondVar(cvar, me); return PR_SUCCESS; } /* ** Notify all of the threads waiting on the condition variable. All of ** threads are notified in turn. The highest priority thread will ** probably acquire the lock. */ PR_IMPLEMENT(PRStatus) PR_NotifyAllCondVar(PRCondVar *cvar) { PRCList *q; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(cvar->lock->owner == me); if (cvar->lock->owner != me) return PR_FAILURE; #ifdef _PR_GLOBAL_THREADS_ONLY _PR_MD_NOTIFYALL_CV(&cvar->md, &cvar->lock->ilock); return PR_SUCCESS; #else /* _PR_GLOBAL_THREADS_ONLY */ if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_CVAR_LOCK(cvar); q = cvar->condQ.next; while (q != &cvar->condQ) { PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar)); _PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me); q = q->next; } _PR_CVAR_UNLOCK(cvar); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_SUCCESS; #endif /* _PR_GLOBAL_THREADS_ONLY */ } /*********************************************************************/ /*********************************************************************/ /********************ROUTINES FOR DCE EMULATION***********************/ /*********************************************************************/ /*********************************************************************/ #include "prpdce.h" PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void) { PRCondVar *cvar = PR_NEWZAP(PRCondVar); if (NULL != cvar) { if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) { PR_DELETE(cvar); cvar = NULL; } else { PR_INIT_CLIST(&cvar->condQ); cvar->lock = _PR_NAKED_CV_LOCK; } } return cvar; } PR_IMPLEMENT(void) PRP_DestroyNakedCondVar(PRCondVar *cvar) { PR_ASSERT(cvar->condQ.next == &cvar->condQ); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); _PR_MD_FREE_LOCK(&(cvar->ilock)); PR_DELETE(cvar); } PR_IMPLEMENT(PRStatus) PRP_NakedWait( PRCondVar *cvar, PRLock *lock, PRIntervalTime timeout) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); return _PR_WaitCondVar(me, cvar, lock, timeout); } /* PRP_NakedWait */ PR_IMPLEMENT(PRStatus) PRP_NakedNotify(PRCondVar *cvar) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); _PR_NotifyCondVar(cvar, me); return PR_SUCCESS; } /* PRP_NakedNotify */ PR_IMPLEMENT(PRStatus) PRP_NakedBroadcast(PRCondVar *cvar) { PRCList *q; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(_PR_NAKED_CV_LOCK == cvar->lock); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_MD_LOCK( &(cvar->ilock) ); q = cvar->condQ.next; while (q != &cvar->condQ) { PR_LOG(_pr_cvar_lm, PR_LOG_MIN, ("PR_NotifyAll: cvar=%p", cvar)); _PR_NotifyThread(_PR_THREAD_CONDQ_PTR(q), me); q = q->next; } _PR_MD_UNLOCK( &(cvar->ilock) ); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_SUCCESS; } /* PRP_NakedBroadcast */ nspr-4.11/nspr/pr/src/threads/combined/prulock.c0000644000000000000000000002776112623070344020014 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #if defined(WIN95) /* ** Some local variables report warnings on Win95 because the code paths ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. ** The pragma suppresses the warning. ** */ #pragma warning(disable : 4101) #endif void _PR_InitLocks(void) { _PR_MD_INIT_LOCKS(); } /* ** Deal with delayed interrupts/requested reschedule during interrupt ** re-enables. */ void _PR_IntsOn(_PRCPU *cpu) { PRUintn missed, pri, i; _PRInterruptTable *it; PRThread *me; PR_ASSERT(cpu); /* Global threads don't have CPUs */ PR_ASSERT(_PR_MD_GET_INTSOFF() > 0); me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); /* ** Process delayed interrupts. This logic is kinda scary because we ** need to avoid losing an interrupt (it's ok to delay an interrupt ** until later). ** ** There are two missed state words. _pr_ints.where indicates to the ** interrupt handler which state word is currently safe for ** modification. ** ** This code scans both interrupt state words, using the where flag ** to indicate to the interrupt which state word is safe for writing. ** If an interrupt comes in during a scan the other word will be ** modified. This modification will be noticed during the next ** iteration of the loop or during the next call to this routine. */ for (i = 0; i < 2; i++) { cpu->where = (1 - i); missed = cpu->u.missed[i]; if (missed != 0) { cpu->u.missed[i] = 0; for (it = _pr_interruptTable; it->name; it++) { if (missed & it->missed_bit) { PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("IntsOn[0]: %s intr", it->name)); (*it->handler)(); } } } } if (cpu->u.missed[3] != 0) { _PRCPU *cpu; _PR_THREAD_LOCK(me); me->state = _PR_RUNNABLE; pri = me->priority; cpu = me->cpu; _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(me, cpu, pri); _PR_RUNQ_UNLOCK(cpu); _PR_THREAD_UNLOCK(me); _PR_MD_SWITCH_CONTEXT(me); } } /* ** Unblock the first runnable waiting thread. Skip over ** threads that are trying to be suspended ** Note: Caller must hold _PR_LOCK_LOCK() */ void _PR_UnblockLockWaiter(PRLock *lock) { PRThread *t = NULL; PRThread *me; PRCList *q; q = lock->waitQ.next; PR_ASSERT(q != &lock->waitQ); while (q != &lock->waitQ) { /* Unblock first waiter */ t = _PR_THREAD_CONDQ_PTR(q); /* ** We are about to change the thread's state to runnable and for local ** threads, we are going to assign a cpu to it. So, protect thread's ** data structure. */ _PR_THREAD_LOCK(t); if (t->flags & _PR_SUSPENDING) { q = q->next; _PR_THREAD_UNLOCK(t); continue; } /* Found a runnable thread */ PR_ASSERT(t->state == _PR_LOCK_WAIT); PR_ASSERT(t->wait.lock == lock); t->wait.lock = 0; PR_REMOVE_LINK(&t->waitQLinks); /* take it off lock's waitQ */ /* ** If this is a native thread, nothing else to do except to wake it ** up by calling the machine dependent wakeup routine. ** ** If this is a local thread, we need to assign it a cpu and ** put the thread on that cpu's run queue. There are two cases to ** take care of. If the currently running thread is also a local ** thread, we just assign our own cpu to that thread and put it on ** the cpu's run queue. If the the currently running thread is a ** native thread, we assign the primordial cpu to it (on NT, ** MD_WAKEUP handles the cpu assignment). */ if ( !_PR_IS_NATIVE_THREAD(t) ) { t->state = _PR_RUNNABLE; me = _PR_MD_CURRENT_THREAD(); _PR_AddThreadToRunQ(me, t); _PR_THREAD_UNLOCK(t); } else { t->state = _PR_RUNNING; _PR_THREAD_UNLOCK(t); } _PR_MD_WAKEUP_WAITER(t); break; } return; } /************************************************************************/ PR_IMPLEMENT(PRLock*) PR_NewLock(void) { PRLock *lock; if (!_pr_initialized) _PR_ImplicitInitialization(); lock = PR_NEWZAP(PRLock); if (lock) { if (_PR_InitLock(lock) != PR_SUCCESS) { PR_DELETE(lock); return NULL; } } return lock; } PRStatus _PR_InitLock(PRLock *lock) { if (_PR_MD_NEW_LOCK(&lock->ilock) != PR_SUCCESS) { return PR_FAILURE; } PR_INIT_CLIST(&lock->links); PR_INIT_CLIST(&lock->waitQ); return PR_SUCCESS; } /* ** Destroy the given lock "lock". There is no point in making this race ** free because if some other thread has the pointer to this lock all ** bets are off. */ PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock) { _PR_FreeLock(lock); PR_DELETE(lock); } void _PR_FreeLock(PRLock *lock) { PR_ASSERT(lock->owner == 0); _PR_MD_FREE_LOCK(&lock->ilock); } extern PRThread *suspendAllThread; /* ** Lock the lock. */ PR_IMPLEMENT(void) PR_Lock(PRLock *lock) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntn is; PRThread *t; PRCList *q; PR_ASSERT(me != suspendAllThread); PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); PR_ASSERT(lock != NULL); #ifdef _PR_GLOBAL_THREADS_ONLY _PR_MD_LOCK(&lock->ilock); PR_ASSERT(lock->owner == 0); lock->owner = me; return; #else /* _PR_GLOBAL_THREADS_ONLY */ if (_native_threads_only) { _PR_MD_LOCK(&lock->ilock); PR_ASSERT(lock->owner == 0); lock->owner = me; return; } if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); retry: _PR_LOCK_LOCK(lock); if (lock->owner == 0) { /* Just got the lock */ lock->owner = me; lock->priority = me->priority; /* Add the granted lock to this owning thread's lock list */ PR_APPEND_LINK(&lock->links, &me->lockList); _PR_LOCK_UNLOCK(lock); if (!_PR_IS_NATIVE_THREAD(me)) _PR_FAST_INTSON(is); return; } /* If this thread already owns this lock, then it is a deadlock */ PR_ASSERT(lock->owner != me); PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); #if 0 if (me->priority > lock->owner->priority) { /* ** Give the lock owner a priority boost until we get the ** lock. Record the priority we boosted it to. */ lock->boostPriority = me->priority; _PR_SetThreadPriority(lock->owner, me->priority); } #endif /* Add this thread to the asked for lock's list of waiting threads. We add this thread thread in the right priority order so when the unlock occurs, the thread with the higher priority will get the lock. */ q = lock->waitQ.next; if (q == &lock->waitQ || _PR_THREAD_CONDQ_PTR(q)->priority == _PR_THREAD_CONDQ_PTR(lock->waitQ.prev)->priority) { /* * If all the threads in the lock waitQ have the same priority, * then avoid scanning the list: insert the element at the end. */ q = &lock->waitQ; } else { /* Sort thread into lock's waitQ at appropriate point */ /* Now scan the list for where to insert this entry */ while (q != &lock->waitQ) { t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next); if (me->priority > t->priority) { /* Found a lower priority thread to insert in front of */ break; } q = q->next; } } PR_INSERT_BEFORE(&me->waitQLinks, q); /* Now grab the threadLock since we are about to change the state. We have to do this since a PR_Suspend or PR_SetThreadPriority type call that takes a PRThread* as an argument could be changing the state of this thread from a thread running on a different cpu. */ _PR_THREAD_LOCK(me); me->state = _PR_LOCK_WAIT; me->wait.lock = lock; _PR_THREAD_UNLOCK(me); _PR_LOCK_UNLOCK(lock); _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT); goto retry; #endif /* _PR_GLOBAL_THREADS_ONLY */ } /* ** Unlock the lock. */ PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock) { PRCList *q; PRThreadPriority pri, boost; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(lock != NULL); PR_ASSERT(lock->owner == me); PR_ASSERT(me != suspendAllThread); PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); if (lock->owner != me) { return PR_FAILURE; } #ifdef _PR_GLOBAL_THREADS_ONLY lock->owner = 0; _PR_MD_UNLOCK(&lock->ilock); return PR_SUCCESS; #else /* _PR_GLOBAL_THREADS_ONLY */ if (_native_threads_only) { lock->owner = 0; _PR_MD_UNLOCK(&lock->ilock); return PR_SUCCESS; } if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_LOCK_LOCK(lock); /* Remove the lock from the owning thread's lock list */ PR_REMOVE_LINK(&lock->links); pri = lock->priority; boost = lock->boostPriority; if (boost > pri) { /* ** We received a priority boost during the time we held the lock. ** We need to figure out what priority to move to by scanning ** down our list of lock's that we are still holding and using ** the highest boosted priority found. */ q = me->lockList.next; while (q != &me->lockList) { PRLock *ll = _PR_LOCK_PTR(q); if (ll->boostPriority > pri) { pri = ll->boostPriority; } q = q->next; } if (pri != me->priority) { _PR_SetThreadPriority(me, pri); } } /* Unblock the first waiting thread */ q = lock->waitQ.next; if (q != &lock->waitQ) _PR_UnblockLockWaiter(lock); lock->boostPriority = PR_PRIORITY_LOW; lock->owner = 0; _PR_LOCK_UNLOCK(lock); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_SUCCESS; #endif /* _PR_GLOBAL_THREADS_ONLY */ } /* ** If the current thread owns |lock|, this assertion is guaranteed to ** succeed. Otherwise, the behavior of this function is undefined. */ PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock) { PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(lock->owner == me); } /* ** Test and then lock the lock if it's not already locked by some other ** thread. Return PR_FALSE if some other thread owned the lock at the ** time of the call. */ PR_IMPLEMENT(PRBool) PR_TestAndLock(PRLock *lock) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRBool rv = PR_FALSE; PRIntn is; #ifdef _PR_GLOBAL_THREADS_ONLY is = _PR_MD_TEST_AND_LOCK(&lock->ilock); if (is == 0) { lock->owner = me; return PR_TRUE; } return PR_FALSE; #else /* _PR_GLOBAL_THREADS_ONLY */ #ifndef _PR_LOCAL_THREADS_ONLY if (_native_threads_only) { is = _PR_MD_TEST_AND_LOCK(&lock->ilock); if (is == 0) { lock->owner = me; return PR_TRUE; } return PR_FALSE; } #endif if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_LOCK_LOCK(lock); if (lock->owner == 0) { /* Just got the lock */ lock->owner = me; lock->priority = me->priority; /* Add the granted lock to this owning thread's lock list */ PR_APPEND_LINK(&lock->links, &me->lockList); rv = PR_TRUE; } _PR_LOCK_UNLOCK(lock); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return rv; #endif /* _PR_GLOBAL_THREADS_ONLY */ } /************************************************************************/ /************************************************************************/ /***********************ROUTINES FOR DCE EMULATION***********************/ /************************************************************************/ /************************************************************************/ PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock) { return (PR_TestAndLock(lock)) ? PR_SUCCESS : PR_FAILURE; } nspr-4.11/nspr/pr/src/threads/combined/prustack.c0000644000000000000000000001047012623070344020156 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /* List of free stack virtual memory chunks */ PRLock *_pr_stackLock; PRCList _pr_freeStacks = PR_INIT_STATIC_CLIST(&_pr_freeStacks); PRIntn _pr_numFreeStacks; PRIntn _pr_maxFreeStacks = 4; #ifdef DEBUG /* ** A variable that can be set via the debugger... */ PRBool _pr_debugStacks = PR_FALSE; #endif /* How much space to leave between the stacks, at each end */ #define REDZONE (2 << _pr_pageShift) #define _PR_THREAD_STACK_PTR(_qp) \ ((PRThreadStack*) ((char*) (_qp) - offsetof(PRThreadStack,links))) void _PR_InitStacks(void) { _pr_stackLock = PR_NewLock(); } void _PR_CleanupStacks(void) { if (_pr_stackLock) { PR_DestroyLock(_pr_stackLock); _pr_stackLock = NULL; } } /* ** Allocate a stack for a thread. */ PRThreadStack *_PR_NewStack(PRUint32 stackSize) { PRCList *qp; PRThreadStack *ts; PRThread *thr; /* ** Trim the list of free stacks. Trim it backwards, tossing out the ** oldest stack found first (this way more recent stacks have a ** chance of being present in the data cache). */ PR_Lock(_pr_stackLock); qp = _pr_freeStacks.prev; while ((_pr_numFreeStacks > _pr_maxFreeStacks) && (qp != &_pr_freeStacks)) { ts = _PR_THREAD_STACK_PTR(qp); thr = _PR_THREAD_STACK_TO_PTR(ts); qp = qp->prev; /* * skip stacks which are still being used */ if (thr->no_sched) continue; PR_REMOVE_LINK(&ts->links); /* Give platform OS to clear out the stack for debugging */ _PR_MD_CLEAR_STACK(ts); _pr_numFreeStacks--; _PR_DestroySegment(ts->seg); PR_DELETE(ts); } /* ** Find a free thread stack. This searches the list of free'd up ** virtually mapped thread stacks. */ qp = _pr_freeStacks.next; ts = 0; while (qp != &_pr_freeStacks) { ts = _PR_THREAD_STACK_PTR(qp); thr = _PR_THREAD_STACK_TO_PTR(ts); qp = qp->next; /* * skip stacks which are still being used */ if ((!(thr->no_sched)) && ((ts->allocSize - 2*REDZONE) >= stackSize)) { /* ** Found a stack that is not in use and is big enough. Change ** stackSize to fit it. */ stackSize = ts->allocSize - 2*REDZONE; PR_REMOVE_LINK(&ts->links); _pr_numFreeStacks--; ts->links.next = 0; ts->links.prev = 0; PR_Unlock(_pr_stackLock); goto done; } ts = 0; } PR_Unlock(_pr_stackLock); if (!ts) { /* Make a new thread stack object. */ ts = PR_NEWZAP(PRThreadStack); if (!ts) { return NULL; } /* ** Assign some of the virtual space to the new stack object. We ** may not get that piece of VM, but if nothing else we will ** advance the pointer so we don't collide (unless the OS screws ** up). */ ts->allocSize = stackSize + 2*REDZONE; ts->seg = _PR_NewSegment(ts->allocSize, 0); if (!ts->seg) { PR_DELETE(ts); return NULL; } } done: ts->allocBase = (char*)ts->seg->vaddr; ts->flags = _PR_STACK_MAPPED; ts->stackSize = stackSize; #ifdef HAVE_STACK_GROWING_UP ts->stackTop = ts->allocBase + REDZONE; ts->stackBottom = ts->stackTop + stackSize; #else ts->stackBottom = ts->allocBase + REDZONE; ts->stackTop = ts->stackBottom + stackSize; #endif PR_LOG(_pr_thread_lm, PR_LOG_NOTICE, ("thread stack: base=0x%x limit=0x%x bottom=0x%x top=0x%x\n", ts->allocBase, ts->allocBase + ts->allocSize - 1, ts->allocBase + REDZONE, ts->allocBase + REDZONE + stackSize - 1)); _PR_MD_INIT_STACK(ts,REDZONE); return ts; } /* ** Free the stack for the current thread */ void _PR_FreeStack(PRThreadStack *ts) { if (!ts) { return; } if (ts->flags & _PR_STACK_PRIMORDIAL) { PR_DELETE(ts); return; } /* ** Put the stack on the free list. This is done because we are still ** using the stack. Next time a thread is created we will trim the ** list down; it's safe to do it then because we will have had to ** context switch to a live stack before another thread can be ** created. */ PR_Lock(_pr_stackLock); PR_APPEND_LINK(&ts->links, _pr_freeStacks.prev); _pr_numFreeStacks++; PR_Unlock(_pr_stackLock); } nspr-4.11/nspr/pr/src/threads/combined/pruthr.c0000644000000000000000000015741012623070344017654 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include #if defined(WIN95) /* ** Some local variables report warnings on Win95 because the code paths ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. ** The pragma suppresses the warning. ** */ #pragma warning(disable : 4101) #endif /* _pr_activeLock protects the following global variables */ PRLock *_pr_activeLock; PRInt32 _pr_primordialExitCount; /* In PR_Cleanup(), the primordial thread * waits until all other user (non-system) * threads have terminated before it exits. * So whenever we decrement _pr_userActive, * it is compared with * _pr_primordialExitCount. * If the primordial thread is a system * thread, then _pr_primordialExitCount * is 0. If the primordial thread is * itself a user thread, then * _pr_primordialThread is 1. */ PRCondVar *_pr_primordialExitCVar; /* When _pr_userActive is decremented to * _pr_primordialExitCount, this condition * variable is notified. */ PRLock *_pr_deadQLock; PRUint32 _pr_numNativeDead; PRUint32 _pr_numUserDead; PRCList _pr_deadNativeQ; PRCList _pr_deadUserQ; PRUint32 _pr_join_counter; PRUint32 _pr_local_threads; PRUint32 _pr_global_threads; PRBool suspendAllOn = PR_FALSE; PRThread *suspendAllThread = NULL; extern PRCList _pr_active_global_threadQ; extern PRCList _pr_active_local_threadQ; static void _PR_DecrActiveThreadCount(PRThread *thread); static PRThread *_PR_AttachThread(PRThreadType, PRThreadPriority, PRThreadStack *); static void _PR_InitializeNativeStack(PRThreadStack *ts); static void _PR_InitializeRecycledThread(PRThread *thread); static void _PR_UserRunThread(void); void _PR_InitThreads(PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs) { PRThread *thread; PRThreadStack *stack; PR_ASSERT(priority == PR_PRIORITY_NORMAL); _pr_terminationCVLock = PR_NewLock(); _pr_activeLock = PR_NewLock(); #ifndef HAVE_CUSTOM_USER_THREADS stack = PR_NEWZAP(PRThreadStack); #ifdef HAVE_STACK_GROWING_UP stack->stackTop = (char*) ((((PRWord)&type) >> _pr_pageShift) << _pr_pageShift); #else #if defined(SOLARIS) || defined (UNIXWARE) && defined (USR_SVR4_THREADS) stack->stackTop = (char*) &thread; #else stack->stackTop = (char*) ((((PRWord)&type + _pr_pageSize - 1) >> _pr_pageShift) << _pr_pageShift); #endif #endif #else /* If stack is NULL, we're using custom user threads like NT fibers. */ stack = PR_NEWZAP(PRThreadStack); if (stack) { stack->stackSize = 0; _PR_InitializeNativeStack(stack); } #endif /* HAVE_CUSTOM_USER_THREADS */ thread = _PR_AttachThread(type, priority, stack); if (thread) { _PR_MD_SET_CURRENT_THREAD(thread); if (type == PR_SYSTEM_THREAD) { thread->flags = _PR_SYSTEM; _pr_systemActive++; _pr_primordialExitCount = 0; } else { _pr_userActive++; _pr_primordialExitCount = 1; } thread->no_sched = 1; _pr_primordialExitCVar = PR_NewCondVar(_pr_activeLock); } if (!thread) PR_Abort(); #ifdef _PR_LOCAL_THREADS_ONLY thread->flags |= _PR_PRIMORDIAL; #else thread->flags |= _PR_PRIMORDIAL | _PR_GLOBAL_SCOPE; #endif /* * Needs _PR_PRIMORDIAL flag set before calling * _PR_MD_INIT_THREAD() */ if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) { /* * XXX do what? */ } if (_PR_IS_NATIVE_THREAD(thread)) { PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ()); _pr_global_threads++; } else { PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ()); _pr_local_threads++; } _pr_recycleThreads = 0; _pr_deadQLock = PR_NewLock(); _pr_numNativeDead = 0; _pr_numUserDead = 0; PR_INIT_CLIST(&_pr_deadNativeQ); PR_INIT_CLIST(&_pr_deadUserQ); } void _PR_CleanupThreads(void) { if (_pr_terminationCVLock) { PR_DestroyLock(_pr_terminationCVLock); _pr_terminationCVLock = NULL; } if (_pr_activeLock) { PR_DestroyLock(_pr_activeLock); _pr_activeLock = NULL; } if (_pr_primordialExitCVar) { PR_DestroyCondVar(_pr_primordialExitCVar); _pr_primordialExitCVar = NULL; } /* TODO _pr_dead{Native,User}Q need to be deleted */ if (_pr_deadQLock) { PR_DestroyLock(_pr_deadQLock); _pr_deadQLock = NULL; } } /* ** Initialize a stack for a native thread */ static void _PR_InitializeNativeStack(PRThreadStack *ts) { if( ts && (ts->stackTop == 0) ) { ts->allocSize = ts->stackSize; /* ** Setup stackTop and stackBottom values. */ #ifdef HAVE_STACK_GROWING_UP ts->allocBase = (char*) ((((PRWord)&ts) >> _pr_pageShift) << _pr_pageShift); ts->stackBottom = ts->allocBase + ts->stackSize; ts->stackTop = ts->allocBase; #else ts->allocBase = (char*) ((((PRWord)&ts + _pr_pageSize - 1) >> _pr_pageShift) << _pr_pageShift); ts->stackTop = ts->allocBase; ts->stackBottom = ts->allocBase - ts->stackSize; #endif } } void _PR_NotifyJoinWaiters(PRThread *thread) { /* ** Handle joinable threads. Change the state to waiting for join. ** Remove from our run Q and put it on global waiting to join Q. ** Notify on our "termination" condition variable so that joining ** thread will know about our termination. Switch our context and ** come back later on to continue the cleanup. */ PR_ASSERT(thread == _PR_MD_CURRENT_THREAD()); if (thread->term != NULL) { PR_Lock(_pr_terminationCVLock); _PR_THREAD_LOCK(thread); thread->state = _PR_JOIN_WAIT; if ( !_PR_IS_NATIVE_THREAD(thread) ) { _PR_MISCQ_LOCK(thread->cpu); _PR_ADD_JOINQ(thread, thread->cpu); _PR_MISCQ_UNLOCK(thread->cpu); } _PR_THREAD_UNLOCK(thread); PR_NotifyCondVar(thread->term); PR_Unlock(_pr_terminationCVLock); _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(thread->state != _PR_JOIN_WAIT); } } /* * Zero some of the data members of a recycled thread. * * Note that we can do this either when a dead thread is added to * the dead thread queue or when it is reused. Here, we are doing * this lazily, when the thread is reused in _PR_CreateThread(). */ static void _PR_InitializeRecycledThread(PRThread *thread) { /* * Assert that the following data members are already zeroed * by _PR_CleanupThread(). */ #ifdef DEBUG if (thread->privateData) { unsigned int i; for (i = 0; i < thread->tpdLength; i++) { PR_ASSERT(thread->privateData[i] == NULL); } } #endif PR_ASSERT(thread->dumpArg == 0 && thread->dump == 0); PR_ASSERT(thread->errorString == 0 && thread->errorStringSize == 0); PR_ASSERT(thread->errorStringLength == 0); PR_ASSERT(thread->name == 0); /* Reset data members in thread structure */ thread->errorCode = thread->osErrorCode = 0; thread->io_pending = thread->io_suspended = PR_FALSE; thread->environment = 0; PR_INIT_CLIST(&thread->lockList); } PRStatus _PR_RecycleThread(PRThread *thread) { if ( _PR_IS_NATIVE_THREAD(thread) && _PR_NUM_DEADNATIVE < _pr_recycleThreads) { _PR_DEADQ_LOCK; PR_APPEND_LINK(&thread->links, &_PR_DEADNATIVEQ); _PR_INC_DEADNATIVE; _PR_DEADQ_UNLOCK; return (PR_SUCCESS); } else if ( !_PR_IS_NATIVE_THREAD(thread) && _PR_NUM_DEADUSER < _pr_recycleThreads) { _PR_DEADQ_LOCK; PR_APPEND_LINK(&thread->links, &_PR_DEADUSERQ); _PR_INC_DEADUSER; _PR_DEADQ_UNLOCK; return (PR_SUCCESS); } return (PR_FAILURE); } /* * Decrement the active thread count, either _pr_systemActive or * _pr_userActive, depending on whether the thread is a system thread * or a user thread. If all the user threads, except possibly * the primordial thread, have terminated, we notify the primordial * thread of this condition. * * Since this function will lock _pr_activeLock, do not call this * function while holding the _pr_activeLock lock, as this will result * in a deadlock. */ static void _PR_DecrActiveThreadCount(PRThread *thread) { PR_Lock(_pr_activeLock); if (thread->flags & _PR_SYSTEM) { _pr_systemActive--; } else { _pr_userActive--; if (_pr_userActive == _pr_primordialExitCount) { PR_NotifyCondVar(_pr_primordialExitCVar); } } PR_Unlock(_pr_activeLock); } /* ** Detach thread structure */ static void _PR_DestroyThread(PRThread *thread) { _PR_MD_FREE_LOCK(&thread->threadLock); PR_DELETE(thread); } void _PR_NativeDestroyThread(PRThread *thread) { if(thread->term) { PR_DestroyCondVar(thread->term); thread->term = 0; } if (NULL != thread->privateData) { PR_ASSERT(0 != thread->tpdLength); PR_DELETE(thread->privateData); thread->tpdLength = 0; } PR_DELETE(thread->stack); _PR_DestroyThread(thread); } void _PR_UserDestroyThread(PRThread *thread) { if(thread->term) { PR_DestroyCondVar(thread->term); thread->term = 0; } if (NULL != thread->privateData) { PR_ASSERT(0 != thread->tpdLength); PR_DELETE(thread->privateData); thread->tpdLength = 0; } _PR_MD_FREE_LOCK(&thread->threadLock); if (thread->threadAllocatedOnStack == 1) { _PR_MD_CLEAN_THREAD(thread); /* * Because the no_sched field is set, this thread/stack will * will not be re-used until the flag is cleared by the thread * we will context switch to. */ _PR_FreeStack(thread->stack); } else { #ifdef WINNT _PR_MD_CLEAN_THREAD(thread); #else /* * This assertion does not apply to NT. On NT, every fiber * has its threadAllocatedOnStack equal to 0. Elsewhere, * only the primordial thread has its threadAllocatedOnStack * equal to 0. */ PR_ASSERT(thread->flags & _PR_PRIMORDIAL); #endif } } /* ** Run a thread's start function. When the start function returns the ** thread is done executing and no longer needs the CPU. If there are no ** more user threads running then we can exit the program. */ void _PR_NativeRunThread(void *arg) { PRThread *thread = (PRThread *)arg; _PR_MD_SET_CURRENT_THREAD(thread); _PR_MD_SET_CURRENT_CPU(NULL); /* Set up the thread stack information */ _PR_InitializeNativeStack(thread->stack); /* Set up the thread md information */ if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) { /* * thread failed to initialize itself, possibly due to * failure to allocate per-thread resources */ return; } while(1) { thread->state = _PR_RUNNING; /* * Add to list of active threads */ PR_Lock(_pr_activeLock); PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_GLOBAL_THREADQ()); _pr_global_threads++; PR_Unlock(_pr_activeLock); (*thread->startFunc)(thread->arg); /* * The following two assertions are meant for NT asynch io. * * The thread should have no asynch io in progress when it * exits, otherwise the overlapped buffer, which is part of * the thread structure, would become invalid. */ PR_ASSERT(thread->io_pending == PR_FALSE); /* * This assertion enforces the programming guideline that * if an io function times out or is interrupted, the thread * should close the fd to force the asynch io to abort * before it exits. Right now, closing the fd is the only * way to clear the io_suspended flag. */ PR_ASSERT(thread->io_suspended == PR_FALSE); /* * remove thread from list of active threads */ PR_Lock(_pr_activeLock); PR_REMOVE_LINK(&thread->active); _pr_global_threads--; PR_Unlock(_pr_activeLock); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting")); /* All done, time to go away */ _PR_CleanupThread(thread); _PR_NotifyJoinWaiters(thread); _PR_DecrActiveThreadCount(thread); thread->state = _PR_DEAD_STATE; if (!_pr_recycleThreads || (_PR_RecycleThread(thread) == PR_FAILURE)) { /* * thread not recycled * platform-specific thread exit processing * - for stuff like releasing native-thread resources, etc. */ _PR_MD_EXIT_THREAD(thread); /* * Free memory allocated for the thread */ _PR_NativeDestroyThread(thread); /* * thread gone, cannot de-reference thread now */ return; } /* Now wait for someone to activate us again... */ _PR_MD_WAIT(thread, PR_INTERVAL_NO_TIMEOUT); } } static void _PR_UserRunThread(void) { PRThread *thread = _PR_MD_CURRENT_THREAD(); PRIntn is; if (_MD_LAST_THREAD()) _MD_LAST_THREAD()->no_sched = 0; #ifdef HAVE_CUSTOM_USER_THREADS if (thread->stack == NULL) { thread->stack = PR_NEWZAP(PRThreadStack); _PR_InitializeNativeStack(thread->stack); } #endif /* HAVE_CUSTOM_USER_THREADS */ while(1) { /* Run thread main */ if ( !_PR_IS_NATIVE_THREAD(thread)) _PR_MD_SET_INTSOFF(0); /* * Add to list of active threads */ if (!(thread->flags & _PR_IDLE_THREAD)) { PR_Lock(_pr_activeLock); PR_APPEND_LINK(&thread->active, &_PR_ACTIVE_LOCAL_THREADQ()); _pr_local_threads++; PR_Unlock(_pr_activeLock); } (*thread->startFunc)(thread->arg); /* * The following two assertions are meant for NT asynch io. * * The thread should have no asynch io in progress when it * exits, otherwise the overlapped buffer, which is part of * the thread structure, would become invalid. */ PR_ASSERT(thread->io_pending == PR_FALSE); /* * This assertion enforces the programming guideline that * if an io function times out or is interrupted, the thread * should close the fd to force the asynch io to abort * before it exits. Right now, closing the fd is the only * way to clear the io_suspended flag. */ PR_ASSERT(thread->io_suspended == PR_FALSE); PR_Lock(_pr_activeLock); /* * remove thread from list of active threads */ if (!(thread->flags & _PR_IDLE_THREAD)) { PR_REMOVE_LINK(&thread->active); _pr_local_threads--; } PR_Unlock(_pr_activeLock); PR_LOG(_pr_thread_lm, PR_LOG_MIN, ("thread exiting")); /* All done, time to go away */ _PR_CleanupThread(thread); _PR_INTSOFF(is); _PR_NotifyJoinWaiters(thread); _PR_DecrActiveThreadCount(thread); thread->state = _PR_DEAD_STATE; if (!_pr_recycleThreads || (_PR_RecycleThread(thread) == PR_FAILURE)) { /* ** Destroy the thread resources */ _PR_UserDestroyThread(thread); } /* ** Find another user thread to run. This cpu has finished the ** previous threads main and is now ready to run another thread. */ { PRInt32 is; _PR_INTSOFF(is); _PR_MD_SWITCH_CONTEXT(thread); } /* Will land here when we get scheduled again if we are recycling... */ } } void _PR_SetThreadPriority(PRThread *thread, PRThreadPriority newPri) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntn is; if ( _PR_IS_NATIVE_THREAD(thread) ) { _PR_MD_SET_PRIORITY(&(thread->md), newPri); return; } if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(thread); if (newPri != thread->priority) { _PRCPU *cpu = thread->cpu; switch (thread->state) { case _PR_RUNNING: /* Change my priority */ _PR_RUNQ_LOCK(cpu); thread->priority = newPri; if (_PR_RUNQREADYMASK(cpu) >> (newPri + 1)) { if (!_PR_IS_NATIVE_THREAD(me)) _PR_SET_RESCHED_FLAG(); } _PR_RUNQ_UNLOCK(cpu); break; case _PR_RUNNABLE: _PR_RUNQ_LOCK(cpu); /* Move to different runQ */ _PR_DEL_RUNQ(thread); thread->priority = newPri; PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); _PR_ADD_RUNQ(thread, cpu, newPri); _PR_RUNQ_UNLOCK(cpu); if (newPri > me->priority) { if (!_PR_IS_NATIVE_THREAD(me)) _PR_SET_RESCHED_FLAG(); } break; case _PR_LOCK_WAIT: case _PR_COND_WAIT: case _PR_IO_WAIT: case _PR_SUSPENDED: thread->priority = newPri; break; } } _PR_THREAD_UNLOCK(thread); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); } /* ** Suspend the named thread and copy its gc registers into regBuf */ static void _PR_Suspend(PRThread *thread) { PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); PR_ASSERT(thread != me); PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread) || (!thread->cpu)); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(thread); switch (thread->state) { case _PR_RUNNABLE: if (!_PR_IS_NATIVE_THREAD(thread)) { _PR_RUNQ_LOCK(thread->cpu); _PR_DEL_RUNQ(thread); _PR_RUNQ_UNLOCK(thread->cpu); _PR_MISCQ_LOCK(thread->cpu); _PR_ADD_SUSPENDQ(thread, thread->cpu); _PR_MISCQ_UNLOCK(thread->cpu); } else { /* * Only LOCAL threads are suspended by _PR_Suspend */ PR_ASSERT(0); } thread->state = _PR_SUSPENDED; break; case _PR_RUNNING: /* * The thread being suspended should be a LOCAL thread with * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state */ PR_ASSERT(0); break; case _PR_LOCK_WAIT: case _PR_IO_WAIT: case _PR_COND_WAIT: if (_PR_IS_NATIVE_THREAD(thread)) { _PR_MD_SUSPEND_THREAD(thread); } thread->flags |= _PR_SUSPENDING; break; default: PR_Abort(); } _PR_THREAD_UNLOCK(thread); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); } static void _PR_Resume(PRThread *thread) { PRThreadPriority pri; PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(thread); switch (thread->state) { case _PR_SUSPENDED: thread->state = _PR_RUNNABLE; thread->flags &= ~_PR_SUSPENDING; if (!_PR_IS_NATIVE_THREAD(thread)) { _PR_MISCQ_LOCK(thread->cpu); _PR_DEL_SUSPENDQ(thread); _PR_MISCQ_UNLOCK(thread->cpu); pri = thread->priority; _PR_RUNQ_LOCK(thread->cpu); _PR_ADD_RUNQ(thread, thread->cpu, pri); _PR_RUNQ_UNLOCK(thread->cpu); if (pri > _PR_MD_CURRENT_THREAD()->priority) { if (!_PR_IS_NATIVE_THREAD(me)) _PR_SET_RESCHED_FLAG(); } } else { PR_ASSERT(0); } break; case _PR_IO_WAIT: case _PR_COND_WAIT: thread->flags &= ~_PR_SUSPENDING; /* PR_ASSERT(thread->wait.monitor->stickyCount == 0); */ break; case _PR_LOCK_WAIT: { PRLock *wLock = thread->wait.lock; thread->flags &= ~_PR_SUSPENDING; _PR_LOCK_LOCK(wLock); if (thread->wait.lock->owner == 0) { _PR_UnblockLockWaiter(thread->wait.lock); } _PR_LOCK_UNLOCK(wLock); break; } case _PR_RUNNABLE: break; case _PR_RUNNING: /* * The thread being suspended should be a LOCAL thread with * _pr_numCPUs == 1. Hence, the thread cannot be in RUNNING state */ PR_ASSERT(0); break; default: /* * thread should have been in one of the above-listed blocked states * (_PR_JOIN_WAIT, _PR_IO_WAIT, _PR_UNBORN, _PR_DEAD_STATE) */ PR_Abort(); } _PR_THREAD_UNLOCK(thread); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); } #if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) static PRThread *get_thread(_PRCPU *cpu, PRBool *wakeup_cpus) { PRThread *thread; PRIntn pri; PRUint32 r; PRCList *qp; PRIntn priMin, priMax; _PR_RUNQ_LOCK(cpu); r = _PR_RUNQREADYMASK(cpu); if (r==0) { priMin = priMax = PR_PRIORITY_FIRST; } else if (r == (1<= priMin ; pri-- ) { if (r & (1 << pri)) { for (qp = _PR_RUNQ(cpu)[pri].next; qp != &_PR_RUNQ(cpu)[pri]; qp = qp->next) { thread = _PR_THREAD_PTR(qp); /* * skip non-schedulable threads */ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); if (thread->no_sched) { thread = NULL; /* * Need to wakeup cpus to avoid missing a * runnable thread * Waking up all CPU's need happen only once. */ *wakeup_cpus = PR_TRUE; continue; } else if (thread->flags & _PR_BOUND_THREAD) { /* * Thread bound to cpu 0 */ thread = NULL; #ifdef IRIX _PR_MD_WAKEUP_PRIMORDIAL_CPU(); #endif continue; } else if (thread->io_pending == PR_TRUE) { /* * A thread that is blocked for I/O needs to run * on the same cpu on which it was blocked. This is because * the cpu's ioq is accessed without lock protection and scheduling * the thread on a different cpu would preclude this optimization. */ thread = NULL; continue; } else { /* Pull thread off of its run queue */ _PR_DEL_RUNQ(thread); _PR_RUNQ_UNLOCK(cpu); return(thread); } } } thread = NULL; } _PR_RUNQ_UNLOCK(cpu); return(thread); } #endif /* !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) */ /* ** Schedule this native thread by finding the highest priority nspr ** thread that is ready to run. ** ** Note- everyone really needs to call _PR_MD_SWITCH_CONTEXT (which calls ** PR_Schedule() rather than calling PR_Schedule. Otherwise if there ** is initialization required for switching from SWITCH_CONTEXT, ** it will not get done! */ void _PR_Schedule(void) { PRThread *thread, *me = _PR_MD_CURRENT_THREAD(); _PRCPU *cpu = _PR_MD_CURRENT_CPU(); PRIntn pri; PRUint32 r; PRCList *qp; PRIntn priMin, priMax; #if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) PRBool wakeup_cpus; #endif /* Interrupts must be disabled */ PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); /* Since we are rescheduling, we no longer want to */ _PR_CLEAR_RESCHED_FLAG(); /* ** Find highest priority thread to run. Bigger priority numbers are ** higher priority threads */ _PR_RUNQ_LOCK(cpu); /* * if we are in SuspendAll mode, can schedule only the thread * that called PR_SuspendAll * * The thread may be ready to run now, after completing an I/O * operation, for example */ if ((thread = suspendAllThread) != 0) { if ((!(thread->no_sched)) && (thread->state == _PR_RUNNABLE)) { /* Pull thread off of its run queue */ _PR_DEL_RUNQ(thread); _PR_RUNQ_UNLOCK(cpu); goto found_thread; } else { thread = NULL; _PR_RUNQ_UNLOCK(cpu); goto idle_thread; } } r = _PR_RUNQREADYMASK(cpu); if (r==0) { priMin = priMax = PR_PRIORITY_FIRST; } else if (r == (1<= priMin ; pri-- ) { if (r & (1 << pri)) { for (qp = _PR_RUNQ(cpu)[pri].next; qp != &_PR_RUNQ(cpu)[pri]; qp = qp->next) { thread = _PR_THREAD_PTR(qp); /* * skip non-schedulable threads */ PR_ASSERT(!(thread->flags & _PR_IDLE_THREAD)); if ((thread->no_sched) && (me != thread)){ thread = NULL; continue; } else { /* Pull thread off of its run queue */ _PR_DEL_RUNQ(thread); _PR_RUNQ_UNLOCK(cpu); goto found_thread; } } } thread = NULL; } _PR_RUNQ_UNLOCK(cpu); #if !defined(_PR_LOCAL_THREADS_ONLY) && defined(XP_UNIX) wakeup_cpus = PR_FALSE; _PR_CPU_LIST_LOCK(); for (qp = _PR_CPUQ().next; qp != &_PR_CPUQ(); qp = qp->next) { if (cpu != _PR_CPU_PTR(qp)) { if ((thread = get_thread(_PR_CPU_PTR(qp), &wakeup_cpus)) != NULL) { thread->cpu = cpu; _PR_CPU_LIST_UNLOCK(); if (wakeup_cpus == PR_TRUE) _PR_MD_WAKEUP_CPUS(); goto found_thread; } } } _PR_CPU_LIST_UNLOCK(); if (wakeup_cpus == PR_TRUE) _PR_MD_WAKEUP_CPUS(); #endif /* _PR_LOCAL_THREADS_ONLY */ idle_thread: /* ** There are no threads to run. Switch to the idle thread */ PR_LOG(_pr_sched_lm, PR_LOG_MAX, ("pausing")); thread = _PR_MD_CURRENT_CPU()->idle_thread; found_thread: PR_ASSERT((me == thread) || ((thread->state == _PR_RUNNABLE) && (!(thread->no_sched)))); /* Resume the thread */ PR_LOG(_pr_sched_lm, PR_LOG_MAX, ("switching to %d[%p]", thread->id, thread)); PR_ASSERT(thread->state != _PR_RUNNING); thread->state = _PR_RUNNING; /* If we are on the runq, it just means that we went to sleep on some * resource, and by the time we got here another real native thread had * already given us the resource and put us back on the runqueue */ PR_ASSERT(thread->cpu == _PR_MD_CURRENT_CPU()); if (thread != me) _PR_MD_RESTORE_CONTEXT(thread); #if 0 /* XXXMB; with setjmp/longjmp it is impossible to land here, but * it is not with fibers... Is this a bad thing? I believe it is * still safe. */ PR_NOT_REACHED("impossible return from schedule"); #endif } /* ** Attaches a thread. ** Does not set the _PR_MD_CURRENT_THREAD. ** Does not specify the scope of the thread. */ static PRThread * _PR_AttachThread(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack) { PRThread *thread; char *mem; if (priority > PR_PRIORITY_LAST) { priority = PR_PRIORITY_LAST; } else if (priority < PR_PRIORITY_FIRST) { priority = PR_PRIORITY_FIRST; } mem = (char*) PR_CALLOC(sizeof(PRThread)); if (mem) { thread = (PRThread*) mem; thread->priority = priority; thread->stack = stack; thread->state = _PR_RUNNING; PR_INIT_CLIST(&thread->lockList); if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) { PR_DELETE(thread); return 0; } return thread; } return 0; } PR_IMPLEMENT(PRThread*) _PR_NativeCreateThread(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize, PRUint32 flags) { PRThread *thread; thread = _PR_AttachThread(type, priority, NULL); if (thread) { PR_Lock(_pr_activeLock); thread->flags = (flags | _PR_GLOBAL_SCOPE); thread->id = ++_pr_utid; if (type == PR_SYSTEM_THREAD) { thread->flags |= _PR_SYSTEM; _pr_systemActive++; } else { _pr_userActive++; } PR_Unlock(_pr_activeLock); thread->stack = PR_NEWZAP(PRThreadStack); if (!thread->stack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto done; } thread->stack->stackSize = stackSize?stackSize:_MD_DEFAULT_STACK_SIZE; thread->stack->thr = thread; thread->startFunc = start; thread->arg = arg; /* Set thread flags related to scope and joinable state. If joinable thread, allocate a "termination" conidition variable. */ if (state == PR_JOINABLE_THREAD) { thread->term = PR_NewCondVar(_pr_terminationCVLock); if (thread->term == NULL) { PR_DELETE(thread->stack); goto done; } } thread->state = _PR_RUNNING; if (_PR_MD_CREATE_THREAD(thread, _PR_NativeRunThread, priority, scope,state,stackSize) == PR_SUCCESS) { return thread; } if (thread->term) { PR_DestroyCondVar(thread->term); thread->term = NULL; } PR_DELETE(thread->stack); } done: if (thread) { _PR_DecrActiveThreadCount(thread); _PR_DestroyThread(thread); } return NULL; } /************************************************************************/ PR_IMPLEMENT(PRThread*) _PR_CreateThread(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize, PRUint32 flags) { PRThread *me; PRThread *thread = NULL; PRThreadStack *stack; char *top; PRIntn is; PRIntn native = 0; PRIntn useRecycled = 0; PRBool status; /* First, pin down the priority. Not all compilers catch passing out of range enum here. If we let bad values thru, priority queues won't work. */ if (priority > PR_PRIORITY_LAST) { priority = PR_PRIORITY_LAST; } else if (priority < PR_PRIORITY_FIRST) { priority = PR_PRIORITY_FIRST; } if (!_pr_initialized) _PR_ImplicitInitialization(); if (! (flags & _PR_IDLE_THREAD)) me = _PR_MD_CURRENT_THREAD(); #if defined(_PR_GLOBAL_THREADS_ONLY) /* * can create global threads only */ if (scope == PR_LOCAL_THREAD) scope = PR_GLOBAL_THREAD; #endif if (_native_threads_only) scope = PR_GLOBAL_THREAD; native = (((scope == PR_GLOBAL_THREAD)|| (scope == PR_GLOBAL_BOUND_THREAD)) && _PR_IS_NATIVE_THREAD_SUPPORTED()); _PR_ADJUST_STACKSIZE(stackSize); if (native) { /* * clear the IDLE_THREAD flag which applies to LOCAL * threads only */ flags &= ~_PR_IDLE_THREAD; flags |= _PR_GLOBAL_SCOPE; if (_PR_NUM_DEADNATIVE > 0) { _PR_DEADQ_LOCK; if (_PR_NUM_DEADNATIVE == 0) { /* Thread safe check */ _PR_DEADQ_UNLOCK; } else { thread = _PR_THREAD_PTR(_PR_DEADNATIVEQ.next); PR_REMOVE_LINK(&thread->links); _PR_DEC_DEADNATIVE; _PR_DEADQ_UNLOCK; _PR_InitializeRecycledThread(thread); thread->startFunc = start; thread->arg = arg; thread->flags = (flags | _PR_GLOBAL_SCOPE); if (type == PR_SYSTEM_THREAD) { thread->flags |= _PR_SYSTEM; PR_ATOMIC_INCREMENT(&_pr_systemActive); } else PR_ATOMIC_INCREMENT(&_pr_userActive); if (state == PR_JOINABLE_THREAD) { if (!thread->term) thread->term = PR_NewCondVar(_pr_terminationCVLock); } else { if(thread->term) { PR_DestroyCondVar(thread->term); thread->term = 0; } } thread->priority = priority; _PR_MD_SET_PRIORITY(&(thread->md), priority); /* XXX what about stackSize? */ thread->state = _PR_RUNNING; _PR_MD_WAKEUP_WAITER(thread); return thread; } } thread = _PR_NativeCreateThread(type, start, arg, priority, scope, state, stackSize, flags); } else { if (_PR_NUM_DEADUSER > 0) { _PR_DEADQ_LOCK; if (_PR_NUM_DEADUSER == 0) { /* thread safe check */ _PR_DEADQ_UNLOCK; } else { PRCList *ptr; /* Go down list checking for a recycled thread with a * large enough stack. XXXMB - this has a bad degenerate case. */ ptr = _PR_DEADUSERQ.next; while( ptr != &_PR_DEADUSERQ ) { thread = _PR_THREAD_PTR(ptr); if ((thread->stack->stackSize >= stackSize) && (!thread->no_sched)) { PR_REMOVE_LINK(&thread->links); _PR_DEC_DEADUSER; break; } else { ptr = ptr->next; thread = NULL; } } _PR_DEADQ_UNLOCK; if (thread) { _PR_InitializeRecycledThread(thread); thread->startFunc = start; thread->arg = arg; thread->priority = priority; if (state == PR_JOINABLE_THREAD) { if (!thread->term) thread->term = PR_NewCondVar(_pr_terminationCVLock); } else { if(thread->term) { PR_DestroyCondVar(thread->term); thread->term = 0; } } useRecycled++; } } } if (thread == NULL) { #ifndef HAVE_CUSTOM_USER_THREADS stack = _PR_NewStack(stackSize); if (!stack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } /* Allocate thread object and per-thread data off the top of the stack*/ top = stack->stackTop; #ifdef HAVE_STACK_GROWING_UP thread = (PRThread*) top; top = top + sizeof(PRThread); /* * Make stack 64-byte aligned */ if ((PRUptrdiff)top & 0x3f) { top = (char*)(((PRUptrdiff)top + 0x40) & ~0x3f); } #else top = top - sizeof(PRThread); thread = (PRThread*) top; /* * Make stack 64-byte aligned */ if ((PRUptrdiff)top & 0x3f) { top = (char*)((PRUptrdiff)top & ~0x3f); } #endif stack->thr = thread; memset(thread, 0, sizeof(PRThread)); thread->threadAllocatedOnStack = 1; #else thread = _PR_MD_CREATE_USER_THREAD(stackSize, start, arg); if (!thread) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } thread->threadAllocatedOnStack = 0; stack = NULL; top = NULL; #endif /* Initialize thread */ thread->tpdLength = 0; thread->privateData = NULL; thread->stack = stack; thread->priority = priority; thread->startFunc = start; thread->arg = arg; PR_INIT_CLIST(&thread->lockList); if (_PR_MD_INIT_THREAD(thread) == PR_FAILURE) { if (thread->threadAllocatedOnStack == 1) _PR_FreeStack(thread->stack); else { PR_DELETE(thread); } PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return NULL; } if (_PR_MD_NEW_LOCK(&thread->threadLock) == PR_FAILURE) { if (thread->threadAllocatedOnStack == 1) _PR_FreeStack(thread->stack); else { PR_DELETE(thread->privateData); PR_DELETE(thread); } PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return NULL; } _PR_MD_INIT_CONTEXT(thread, top, _PR_UserRunThread, &status); if (status == PR_FALSE) { _PR_MD_FREE_LOCK(&thread->threadLock); if (thread->threadAllocatedOnStack == 1) _PR_FreeStack(thread->stack); else { PR_DELETE(thread->privateData); PR_DELETE(thread); } return NULL; } /* Set thread flags related to scope and joinable state. If joinable thread, allocate a "termination" condition variable. */ if (state == PR_JOINABLE_THREAD) { thread->term = PR_NewCondVar(_pr_terminationCVLock); if (thread->term == NULL) { _PR_MD_FREE_LOCK(&thread->threadLock); if (thread->threadAllocatedOnStack == 1) _PR_FreeStack(thread->stack); else { PR_DELETE(thread->privateData); PR_DELETE(thread); } return NULL; } } } /* Update thread type counter */ PR_Lock(_pr_activeLock); thread->flags = flags; thread->id = ++_pr_utid; if (type == PR_SYSTEM_THREAD) { thread->flags |= _PR_SYSTEM; _pr_systemActive++; } else { _pr_userActive++; } /* Make thread runnable */ thread->state = _PR_RUNNABLE; /* * Add to list of active threads */ PR_Unlock(_pr_activeLock); if ((! (thread->flags & _PR_IDLE_THREAD)) && _PR_IS_NATIVE_THREAD(me) ) thread->cpu = _PR_GetPrimordialCPU(); else thread->cpu = _PR_MD_CURRENT_CPU(); PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread)); if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me)) { _PR_INTSOFF(is); _PR_RUNQ_LOCK(thread->cpu); _PR_ADD_RUNQ(thread, thread->cpu, priority); _PR_RUNQ_UNLOCK(thread->cpu); } if (thread->flags & _PR_IDLE_THREAD) { /* ** If the creating thread is a kernel thread, we need to ** awaken the user thread idle thread somehow; potentially ** it could be sleeping in its idle loop, and we need to poke ** it. To do so, wake the idle thread... */ _PR_MD_WAKEUP_WAITER(NULL); } else if (_PR_IS_NATIVE_THREAD(me)) { _PR_MD_WAKEUP_WAITER(thread); } if ((! (thread->flags & _PR_IDLE_THREAD)) && !_PR_IS_NATIVE_THREAD(me) ) _PR_INTSON(is); } return thread; } PR_IMPLEMENT(PRThread*) PR_CreateThread(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { return _PR_CreateThread(type, start, arg, priority, scope, state, stackSize, 0); } /* ** Associate a thread object with an existing native thread. ** "type" is the type of thread object to attach ** "priority" is the priority to assign to the thread ** "stack" defines the shape of the threads stack ** ** This can return NULL if some kind of error occurs, or if memory is ** tight. ** ** This call is not normally needed unless you create your own native ** thread. PR_Init does this automatically for the primordial thread. */ PRThread* _PRI_AttachThread(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack, PRUint32 flags) { PRThread *thread; if ((thread = _PR_MD_GET_ATTACHED_THREAD()) != NULL) { return thread; } _PR_MD_SET_CURRENT_THREAD(NULL); /* Clear out any state if this thread was attached before */ _PR_MD_SET_CURRENT_CPU(NULL); thread = _PR_AttachThread(type, priority, stack); if (thread) { PRIntn is; _PR_MD_SET_CURRENT_THREAD(thread); thread->flags = flags | _PR_GLOBAL_SCOPE | _PR_ATTACHED; if (!stack) { thread->stack = PR_NEWZAP(PRThreadStack); if (!thread->stack) { _PR_DestroyThread(thread); return NULL; } thread->stack->stackSize = _MD_DEFAULT_STACK_SIZE; } PR_INIT_CLIST(&thread->links); if (_PR_MD_INIT_ATTACHED_THREAD(thread) == PR_FAILURE) { PR_DELETE(thread->stack); _PR_DestroyThread(thread); return NULL; } _PR_MD_SET_CURRENT_CPU(NULL); if (_PR_MD_CURRENT_CPU()) { _PR_INTSOFF(is); PR_Lock(_pr_activeLock); } if (type == PR_SYSTEM_THREAD) { thread->flags |= _PR_SYSTEM; _pr_systemActive++; } else { _pr_userActive++; } if (_PR_MD_CURRENT_CPU()) { PR_Unlock(_pr_activeLock); _PR_INTSON(is); } } return thread; } PR_IMPLEMENT(PRThread*) PR_AttachThread(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack) { return PR_GetCurrentThread(); } PR_IMPLEMENT(void) PR_DetachThread(void) { /* * On IRIX, Solaris, and Windows, foreign threads are detached when * they terminate. */ #if !defined(IRIX) && !defined(WIN32) \ && !(defined(SOLARIS) && defined(_PR_GLOBAL_THREADS_ONLY)) PRThread *me; if (_pr_initialized) { me = _PR_MD_GET_ATTACHED_THREAD(); if ((me != NULL) && (me->flags & _PR_ATTACHED)) _PRI_DetachThread(); } #endif } void _PRI_DetachThread(void) { PRThread *me = _PR_MD_CURRENT_THREAD(); if (me->flags & _PR_PRIMORDIAL) { /* * ignore, if primordial thread */ return; } PR_ASSERT(me->flags & _PR_ATTACHED); PR_ASSERT(_PR_IS_NATIVE_THREAD(me)); _PR_CleanupThread(me); PR_DELETE(me->privateData); _PR_DecrActiveThreadCount(me); _PR_MD_CLEAN_THREAD(me); _PR_MD_SET_CURRENT_THREAD(NULL); if (!me->threadAllocatedOnStack) PR_DELETE(me->stack); _PR_MD_FREE_LOCK(&me->threadLock); PR_DELETE(me); } /* ** Wait for thread termination: ** "thread" is the target thread ** ** This can return PR_FAILURE if no joinable thread could be found ** corresponding to the specified target thread. ** ** The calling thread is suspended until the target thread completes. ** Several threads cannot wait for the same thread to complete; one thread ** will complete successfully and others will terminate with an error PR_FAILURE. ** The calling thread will not be blocked if the target thread has already ** terminated. */ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thread) { PRIntn is; PRCondVar *term; PRThread *me = _PR_MD_CURRENT_THREAD(); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); term = thread->term; /* can't join a non-joinable thread */ if (term == NULL) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); goto ErrorExit; } /* multiple threads can't wait on the same joinable thread */ if (term->condQ.next != &term->condQ) { goto ErrorExit; } if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); /* wait for the target thread's termination cv invariant */ PR_Lock (_pr_terminationCVLock); while (thread->state != _PR_JOIN_WAIT) { (void) PR_WaitCondVar(term, PR_INTERVAL_NO_TIMEOUT); } (void) PR_Unlock (_pr_terminationCVLock); /* Remove target thread from global waiting to join Q; make it runnable again and put it back on its run Q. When it gets scheduled later in _PR_RunThread code, it will clean up its stack. */ if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); thread->state = _PR_RUNNABLE; if ( !_PR_IS_NATIVE_THREAD(thread) ) { _PR_THREAD_LOCK(thread); _PR_MISCQ_LOCK(thread->cpu); _PR_DEL_JOINQ(thread); _PR_MISCQ_UNLOCK(thread->cpu); _PR_AddThreadToRunQ(me, thread); _PR_THREAD_UNLOCK(thread); } if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); _PR_MD_WAKEUP_WAITER(thread); return PR_SUCCESS; ErrorExit: if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_FAILURE; } PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thread, PRThreadPriority newPri) { /* First, pin down the priority. Not all compilers catch passing out of range enum here. If we let bad values thru, priority queues won't work. */ if ((PRIntn)newPri > (PRIntn)PR_PRIORITY_LAST) { newPri = PR_PRIORITY_LAST; } else if ((PRIntn)newPri < (PRIntn)PR_PRIORITY_FIRST) { newPri = PR_PRIORITY_FIRST; } if ( _PR_IS_NATIVE_THREAD(thread) ) { thread->priority = newPri; _PR_MD_SET_PRIORITY(&(thread->md), newPri); } else _PR_SetThreadPriority(thread, newPri); } PR_IMPLEMENT(PRStatus) PR_SetCurrentThreadName(const char *name) { PRThread *thread; size_t nameLen; if (!name) { PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return PR_FAILURE; } thread = PR_GetCurrentThread(); if (!thread) return PR_FAILURE; PR_Free(thread->name); nameLen = strlen(name); thread->name = (char *)PR_Malloc(nameLen + 1); if (!thread->name) return PR_FAILURE; memcpy(thread->name, name, nameLen + 1); _PR_MD_SET_CURRENT_THREAD_NAME(thread->name); return PR_SUCCESS; } PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread) { if (!thread) return NULL; return thread->name; } /* ** This routine prevents all other threads from running. This call is needed by ** the garbage collector. */ PR_IMPLEMENT(void) PR_SuspendAll(void) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRCList *qp; /* * Stop all user and native threads which are marked GC able. */ PR_Lock(_pr_activeLock); suspendAllOn = PR_TRUE; suspendAllThread = _PR_MD_CURRENT_THREAD(); _PR_MD_BEGIN_SUSPEND_ALL(); for (qp = _PR_ACTIVE_LOCAL_THREADQ().next; qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) { if ((me != _PR_ACTIVE_THREAD_PTR(qp)) && _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp))) { _PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp)); PR_ASSERT((_PR_ACTIVE_THREAD_PTR(qp))->state != _PR_RUNNING); } } for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next; qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) { if ((me != _PR_ACTIVE_THREAD_PTR(qp)) && _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp))) /* PR_Suspend(_PR_ACTIVE_THREAD_PTR(qp)); */ _PR_MD_SUSPEND_THREAD(_PR_ACTIVE_THREAD_PTR(qp)); } _PR_MD_END_SUSPEND_ALL(); } /* ** This routine unblocks all other threads that were suspended from running by ** PR_SuspendAll(). This call is needed by the garbage collector. */ PR_IMPLEMENT(void) PR_ResumeAll(void) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRCList *qp; /* * Resume all user and native threads which are marked GC able. */ _PR_MD_BEGIN_RESUME_ALL(); for (qp = _PR_ACTIVE_LOCAL_THREADQ().next; qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp->next) { if ((me != _PR_ACTIVE_THREAD_PTR(qp)) && _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp))) _PR_Resume(_PR_ACTIVE_THREAD_PTR(qp)); } for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next; qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp->next) { if ((me != _PR_ACTIVE_THREAD_PTR(qp)) && _PR_IS_GCABLE_THREAD(_PR_ACTIVE_THREAD_PTR(qp))) _PR_MD_RESUME_THREAD(_PR_ACTIVE_THREAD_PTR(qp)); } _PR_MD_END_RESUME_ALL(); suspendAllThread = NULL; suspendAllOn = PR_FALSE; PR_Unlock(_pr_activeLock); } PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg) { PRCList *qp, *qp_next; PRIntn i = 0; PRStatus rv = PR_SUCCESS; PRThread* t; /* ** Currently Enumerate threads happen only with suspension and ** pr_activeLock held */ PR_ASSERT(suspendAllOn); /* Steve Morse, 4-23-97: Note that we can't walk a queue by taking * qp->next after applying the function "func". In particular, "func" * might remove the thread from the queue and put it into another one in * which case qp->next no longer points to the next entry in the original * queue. * * To get around this problem, we save qp->next in qp_next before applying * "func" and use that saved value as the next value after applying "func". */ /* * Traverse the list of local and global threads */ for (qp = _PR_ACTIVE_LOCAL_THREADQ().next; qp != &_PR_ACTIVE_LOCAL_THREADQ(); qp = qp_next) { qp_next = qp->next; t = _PR_ACTIVE_THREAD_PTR(qp); if (_PR_IS_GCABLE_THREAD(t)) { rv = (*func)(t, i, arg); if (rv != PR_SUCCESS) return rv; i++; } } for (qp = _PR_ACTIVE_GLOBAL_THREADQ().next; qp != &_PR_ACTIVE_GLOBAL_THREADQ(); qp = qp_next) { qp_next = qp->next; t = _PR_ACTIVE_THREAD_PTR(qp); if (_PR_IS_GCABLE_THREAD(t)) { rv = (*func)(t, i, arg); if (rv != PR_SUCCESS) return rv; i++; } } return rv; } /* FUNCTION: _PR_AddSleepQ ** DESCRIPTION: ** Adds a thread to the sleep/pauseQ. ** RESTRICTIONS: ** Caller must have the RUNQ lock. ** Caller must be a user level thread */ PR_IMPLEMENT(void) _PR_AddSleepQ(PRThread *thread, PRIntervalTime timeout) { _PRCPU *cpu = thread->cpu; if (timeout == PR_INTERVAL_NO_TIMEOUT) { /* append the thread to the global pause Q */ PR_APPEND_LINK(&thread->links, &_PR_PAUSEQ(thread->cpu)); thread->flags |= _PR_ON_PAUSEQ; } else { PRIntervalTime sleep; PRCList *q; PRThread *t; /* sort onto global sleepQ */ sleep = timeout; /* Check if we are longest timeout */ if (timeout >= _PR_SLEEPQMAX(cpu)) { PR_INSERT_BEFORE(&thread->links, &_PR_SLEEPQ(cpu)); thread->sleep = timeout - _PR_SLEEPQMAX(cpu); _PR_SLEEPQMAX(cpu) = timeout; } else { /* Sort thread into global sleepQ at appropriate point */ q = _PR_SLEEPQ(cpu).next; /* Now scan the list for where to insert this entry */ while (q != &_PR_SLEEPQ(cpu)) { t = _PR_THREAD_PTR(q); if (sleep < t->sleep) { /* Found sleeper to insert in front of */ break; } sleep -= t->sleep; q = q->next; } thread->sleep = sleep; PR_INSERT_BEFORE(&thread->links, q); /* ** Subtract our sleep time from the sleeper that follows us (there ** must be one) so that they remain relative to us. */ PR_ASSERT (thread->links.next != &_PR_SLEEPQ(cpu)); t = _PR_THREAD_PTR(thread->links.next); PR_ASSERT(_PR_THREAD_PTR(t->links.prev) == thread); t->sleep -= sleep; } thread->flags |= _PR_ON_SLEEPQ; } } /* FUNCTION: _PR_DelSleepQ ** DESCRIPTION: ** Removes a thread from the sleep/pauseQ. ** INPUTS: ** If propogate_time is true, then the thread following the deleted ** thread will be get the time from the deleted thread. This is used ** when deleting a sleeper that has not timed out. ** RESTRICTIONS: ** Caller must have the RUNQ lock. ** Caller must be a user level thread */ PR_IMPLEMENT(void) _PR_DelSleepQ(PRThread *thread, PRBool propogate_time) { _PRCPU *cpu = thread->cpu; /* Remove from pauseQ/sleepQ */ if (thread->flags & (_PR_ON_PAUSEQ|_PR_ON_SLEEPQ)) { if (thread->flags & _PR_ON_SLEEPQ) { PRCList *q = thread->links.next; if (q != &_PR_SLEEPQ(cpu)) { if (propogate_time == PR_TRUE) { PRThread *after = _PR_THREAD_PTR(q); after->sleep += thread->sleep; } else _PR_SLEEPQMAX(cpu) -= thread->sleep; } else { /* Check if prev is the beggining of the list; if so, * we are the only element on the list. */ if (thread->links.prev != &_PR_SLEEPQ(cpu)) _PR_SLEEPQMAX(cpu) -= thread->sleep; else _PR_SLEEPQMAX(cpu) = 0; } thread->flags &= ~_PR_ON_SLEEPQ; } else { thread->flags &= ~_PR_ON_PAUSEQ; } PR_REMOVE_LINK(&thread->links); } else PR_ASSERT(0); } void _PR_AddThreadToRunQ( PRThread *me, /* the current thread */ PRThread *thread) /* the local thread to be added to a run queue */ { PRThreadPriority pri = thread->priority; _PRCPU *cpu = thread->cpu; PR_ASSERT(!_PR_IS_NATIVE_THREAD(thread)); #if defined(WINNT) /* * On NT, we can only reliably know that the current CPU * is not idle. We add the awakened thread to the run * queue of its CPU if its CPU is the current CPU. * For any other CPU, we don't really know whether it * is busy or idle. So in all other cases, we just * "post" the awakened thread to the IO completion port * for the next idle CPU to execute (this is done in * _PR_MD_WAKEUP_WAITER). * Threads with a suspended I/O operation remain bound to * the same cpu until I/O is cancelled * * NOTE: the boolean expression below must be the exact * opposite of the corresponding boolean expression in * _PR_MD_WAKEUP_WAITER. */ if ((!_PR_IS_NATIVE_THREAD(me) && (cpu == me->cpu)) || (thread->md.thr_bound_cpu)) { PR_ASSERT(!thread->md.thr_bound_cpu || (thread->md.thr_bound_cpu == cpu)); _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thread, cpu, pri); _PR_RUNQ_UNLOCK(cpu); } #else _PR_RUNQ_LOCK(cpu); _PR_ADD_RUNQ(thread, cpu, pri); _PR_RUNQ_UNLOCK(cpu); if (!_PR_IS_NATIVE_THREAD(me) && (cpu == me->cpu)) { if (pri > me->priority) { _PR_SET_RESCHED_FLAG(); } } #endif } nspr-4.11/nspr/pr/src/threads/prcmon.c0000644000000000000000000002746512623070344016054 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #include /* Lock used to lock the monitor cache */ #ifdef _PR_NO_PREEMPT #define _PR_NEW_LOCK_MCACHE() #define _PR_DESTROY_LOCK_MCACHE() #define _PR_LOCK_MCACHE() #define _PR_UNLOCK_MCACHE() #else #ifdef _PR_LOCAL_THREADS_ONLY #define _PR_NEW_LOCK_MCACHE() #define _PR_DESTROY_LOCK_MCACHE() #define _PR_LOCK_MCACHE() { PRIntn _is; _PR_INTSOFF(_is) #define _PR_UNLOCK_MCACHE() _PR_INTSON(_is); } #else PRLock *_pr_mcacheLock; #define _PR_NEW_LOCK_MCACHE() (_pr_mcacheLock = PR_NewLock()) #define _PR_DESTROY_LOCK_MCACHE() \ PR_BEGIN_MACRO \ if (_pr_mcacheLock) { \ PR_DestroyLock(_pr_mcacheLock); \ _pr_mcacheLock = NULL; \ } \ PR_END_MACRO #define _PR_LOCK_MCACHE() PR_Lock(_pr_mcacheLock) #define _PR_UNLOCK_MCACHE() PR_Unlock(_pr_mcacheLock) #endif #endif /************************************************************************/ typedef struct MonitorCacheEntryStr MonitorCacheEntry; struct MonitorCacheEntryStr { MonitorCacheEntry* next; void* address; PRMonitor* mon; long cacheEntryCount; }; /* ** An array of MonitorCacheEntry's, plus a pointer to link these ** arrays together. */ typedef struct MonitorCacheEntryBlockStr MonitorCacheEntryBlock; struct MonitorCacheEntryBlockStr { MonitorCacheEntryBlock* next; MonitorCacheEntry entries[1]; }; static PRUint32 hash_mask; static PRUintn num_hash_buckets; static PRUintn num_hash_buckets_log2; static MonitorCacheEntry **hash_buckets; static MonitorCacheEntry *free_entries; static PRUintn num_free_entries; static PRBool expanding; static MonitorCacheEntryBlock *mcache_blocks; static void (*OnMonitorRecycle)(void *address); #define HASH(address) \ ((PRUint32) ( ((PRUptrdiff)(address) >> 2) ^ \ ((PRUptrdiff)(address) >> 10) ) \ & hash_mask) /* ** Expand the monitor cache. This grows the hash buckets and allocates a ** new chunk of cache entries and throws them on the free list. We keep ** as many hash buckets as there are entries. ** ** Because we call malloc and malloc may need the monitor cache, we must ** ensure that there are several free monitor cache entries available for ** malloc to get. FREE_THRESHOLD is used to prevent monitor cache ** starvation during monitor cache expansion. */ #define FREE_THRESHOLD 5 static PRStatus ExpandMonitorCache(PRUintn new_size_log2) { MonitorCacheEntry **old_hash_buckets, *p; PRUintn i, entries, old_num_hash_buckets, added; MonitorCacheEntry **new_hash_buckets; MonitorCacheEntryBlock *new_block; entries = 1L << new_size_log2; /* ** Expand the monitor-cache-entry free list */ new_block = (MonitorCacheEntryBlock*) PR_CALLOC(sizeof(MonitorCacheEntryBlock) + (entries - 1) * sizeof(MonitorCacheEntry)); if (NULL == new_block) return PR_FAILURE; /* ** Allocate system monitors for the new monitor cache entries. If we ** run out of system monitors, break out of the loop. */ for (i = 0, p = new_block->entries; i < entries; i++, p++) { p->mon = PR_NewMonitor(); if (!p->mon) break; } added = i; if (added != entries) { MonitorCacheEntryBlock *realloc_block; if (added == 0) { /* Totally out of system monitors. Lossage abounds */ PR_DELETE(new_block); return PR_FAILURE; } /* ** We were able to allocate some of the system monitors. Use ** realloc to shrink down the new_block memory. If that fails, ** carry on with the too-large new_block. */ realloc_block = (MonitorCacheEntryBlock*) PR_REALLOC(new_block, sizeof(MonitorCacheEntryBlock) + (added - 1) * sizeof(MonitorCacheEntry)); if (realloc_block) new_block = realloc_block; } /* ** Now that we have allocated all of the system monitors, build up ** the new free list. We can just update the free_list because we own ** the mcache-lock and we aren't calling anyone who might want to use ** it. */ for (i = 0, p = new_block->entries; i < added - 1; i++, p++) p->next = p + 1; p->next = free_entries; free_entries = new_block->entries; num_free_entries += added; new_block->next = mcache_blocks; mcache_blocks = new_block; /* Try to expand the hash table */ new_hash_buckets = (MonitorCacheEntry**) PR_CALLOC(entries * sizeof(MonitorCacheEntry*)); if (NULL == new_hash_buckets) { /* ** Partial lossage. In this situation we don't get any more hash ** buckets, which just means that the table lookups will take ** longer. This is bad, but not fatal */ PR_LOG(_pr_cmon_lm, PR_LOG_WARNING, ("unable to grow monitor cache hash buckets")); return PR_SUCCESS; } /* ** Compute new hash mask value. This value is used to mask an address ** until it's bits are in the right spot for indexing into the hash ** table. */ hash_mask = entries - 1; /* ** Expand the hash table. We have to rehash everything in the old ** table into the new table. */ old_hash_buckets = hash_buckets; old_num_hash_buckets = num_hash_buckets; for (i = 0; i < old_num_hash_buckets; i++) { p = old_hash_buckets[i]; while (p) { MonitorCacheEntry *next = p->next; /* Hash based on new table size, and then put p in the new table */ PRUintn hash = HASH(p->address); p->next = new_hash_buckets[hash]; new_hash_buckets[hash] = p; p = next; } } /* ** Switch over to new hash table and THEN call free of the old ** table. Since free might re-enter _pr_mcache_lock, things would ** break terribly if it used the old hash table. */ hash_buckets = new_hash_buckets; num_hash_buckets = entries; num_hash_buckets_log2 = new_size_log2; PR_DELETE(old_hash_buckets); PR_LOG(_pr_cmon_lm, PR_LOG_NOTICE, ("expanded monitor cache to %d (buckets %d)", num_free_entries, entries)); return PR_SUCCESS; } /* ExpandMonitorCache */ /* ** Lookup a monitor cache entry by address. Return a pointer to the ** pointer to the monitor cache entry on success, null on failure. */ static MonitorCacheEntry **LookupMonitorCacheEntry(void *address) { PRUintn hash; MonitorCacheEntry **pp, *p; hash = HASH(address); pp = hash_buckets + hash; while ((p = *pp) != 0) { if (p->address == address) { if (p->cacheEntryCount > 0) return pp; return NULL; } pp = &p->next; } return NULL; } /* ** Try to create a new cached monitor. If it's already in the cache, ** great - return it. Otherwise get a new free cache entry and set it ** up. If the cache free space is getting low, expand the cache. */ static PRMonitor *CreateMonitor(void *address) { PRUintn hash; MonitorCacheEntry **pp, *p; hash = HASH(address); pp = hash_buckets + hash; while ((p = *pp) != 0) { if (p->address == address) goto gotit; pp = &p->next; } /* Expand the monitor cache if we have run out of free slots in the table */ if (num_free_entries < FREE_THRESHOLD) { /* Expand monitor cache */ /* ** This function is called with the lock held. So what's the 'expanding' ** boolean all about? Seems a bit redundant. */ if (!expanding) { PRStatus rv; expanding = PR_TRUE; rv = ExpandMonitorCache(num_hash_buckets_log2 + 1); expanding = PR_FALSE; if (PR_FAILURE == rv) return NULL; /* redo the hash because it'll be different now */ hash = HASH(address); } else { /* ** We are in process of expanding and we need a cache ** monitor. Make sure we have enough! */ PR_ASSERT(num_free_entries > 0); } } /* Make a new monitor */ p = free_entries; free_entries = p->next; num_free_entries--; if (OnMonitorRecycle && p->address) OnMonitorRecycle(p->address); p->address = address; p->next = hash_buckets[hash]; hash_buckets[hash] = p; PR_ASSERT(p->cacheEntryCount == 0); gotit: p->cacheEntryCount++; return p->mon; } /* ** Initialize the monitor cache */ void _PR_InitCMon(void) { _PR_NEW_LOCK_MCACHE(); ExpandMonitorCache(3); } /* ** Destroy the monitor cache */ void _PR_CleanupCMon(void) { _PR_DESTROY_LOCK_MCACHE(); while (free_entries) { PR_DestroyMonitor(free_entries->mon); free_entries = free_entries->next; } num_free_entries = 0; while (mcache_blocks) { MonitorCacheEntryBlock *block; block = mcache_blocks; mcache_blocks = block->next; PR_DELETE(block); } PR_DELETE(hash_buckets); hash_mask = 0; num_hash_buckets = 0; num_hash_buckets_log2 = 0; expanding = PR_FALSE; OnMonitorRecycle = NULL; } /* ** Create monitor for address. Don't enter the monitor while we have the ** mcache locked because we might block! */ PR_IMPLEMENT(PRMonitor*) PR_CEnterMonitor(void *address) { PRMonitor *mon; if (!_pr_initialized) _PR_ImplicitInitialization(); _PR_LOCK_MCACHE(); mon = CreateMonitor(address); _PR_UNLOCK_MCACHE(); if (!mon) return NULL; PR_EnterMonitor(mon); return mon; } PR_IMPLEMENT(PRStatus) PR_CExitMonitor(void *address) { MonitorCacheEntry **pp, *p; PRStatus status = PR_SUCCESS; _PR_LOCK_MCACHE(); pp = LookupMonitorCacheEntry(address); if (pp != NULL) { p = *pp; if (--p->cacheEntryCount == 0) { /* ** Nobody is using the system monitor. Put it on the cached free ** list. We are safe from somebody trying to use it because we ** have the mcache locked. */ p->address = 0; /* defensive move */ *pp = p->next; /* unlink from hash_buckets */ p->next = free_entries; /* link into free list */ free_entries = p; num_free_entries++; /* count it as free */ } status = PR_ExitMonitor(p->mon); } else { status = PR_FAILURE; } _PR_UNLOCK_MCACHE(); return status; } PR_IMPLEMENT(PRStatus) PR_CWait(void *address, PRIntervalTime ticks) { MonitorCacheEntry **pp; PRMonitor *mon; _PR_LOCK_MCACHE(); pp = LookupMonitorCacheEntry(address); mon = pp ? ((*pp)->mon) : NULL; _PR_UNLOCK_MCACHE(); if (mon == NULL) return PR_FAILURE; return PR_Wait(mon, ticks); } PR_IMPLEMENT(PRStatus) PR_CNotify(void *address) { MonitorCacheEntry **pp; PRMonitor *mon; _PR_LOCK_MCACHE(); pp = LookupMonitorCacheEntry(address); mon = pp ? ((*pp)->mon) : NULL; _PR_UNLOCK_MCACHE(); if (mon == NULL) return PR_FAILURE; return PR_Notify(mon); } PR_IMPLEMENT(PRStatus) PR_CNotifyAll(void *address) { MonitorCacheEntry **pp; PRMonitor *mon; _PR_LOCK_MCACHE(); pp = LookupMonitorCacheEntry(address); mon = pp ? ((*pp)->mon) : NULL; _PR_UNLOCK_MCACHE(); if (mon == NULL) return PR_FAILURE; return PR_NotifyAll(mon); } PR_IMPLEMENT(void) PR_CSetOnMonitorRecycle(void (*callback)(void *address)) { OnMonitorRecycle = callback; } nspr-4.11/nspr/pr/src/threads/prcthr.c0000644000000000000000000002624312623070344016051 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #if defined(WIN95) /* ** Some local variables report warnings on Win95 because the code paths ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. ** The pragma suppresses the warning. ** */ #pragma warning(disable : 4101) #endif extern PRLock *_pr_sleeplock; /* allocated and initialized in prinit */ /* ** Routines common to both native and user threads. ** ** ** Clean up a thread object, releasing all of the attached data. Do not ** free the object itself (it may not have been malloc'd) */ void _PR_CleanupThread(PRThread *thread) { /* Free up per-thread-data */ _PR_DestroyThreadPrivate(thread); /* Free any thread dump procs */ if (thread->dumpArg) { PR_DELETE(thread->dumpArg); } thread->dump = 0; PR_DELETE(thread->name); PR_DELETE(thread->errorString); thread->errorStringSize = 0; thread->errorStringLength = 0; thread->environment = NULL; } PR_IMPLEMENT(PRStatus) PR_Yield() { static PRBool warning = PR_TRUE; if (warning) warning = _PR_Obsolete( "PR_Yield()", "PR_Sleep(PR_INTERVAL_NO_WAIT)"); return (PR_Sleep(PR_INTERVAL_NO_WAIT)); } /* ** Make the current thread sleep until "timeout" ticks amount of time ** has expired. If "timeout" is PR_INTERVAL_NO_WAIT then the call is ** equivalent to a yield. Waiting for an infinite amount of time is ** allowed in the expectation that another thread will interrupt(). ** ** A single lock is used for all threads calling sleep. Each caller ** does get its own condition variable since each is expected to have ** a unique 'timeout'. */ PR_IMPLEMENT(PRStatus) PR_Sleep(PRIntervalTime timeout) { PRStatus rv = PR_SUCCESS; if (!_pr_initialized) _PR_ImplicitInitialization(); if (PR_INTERVAL_NO_WAIT == timeout) { /* ** This is a simple yield, nothing more, nothing less. */ PRIntn is; PRThread *me = PR_GetCurrentThread(); PRUintn pri = me->priority; _PRCPU *cpu = _PR_MD_CURRENT_CPU(); if ( _PR_IS_NATIVE_THREAD(me) ) _PR_MD_YIELD(); else { _PR_INTSOFF(is); _PR_RUNQ_LOCK(cpu); if (_PR_RUNQREADYMASK(cpu) >> pri) { me->cpu = cpu; me->state = _PR_RUNNABLE; _PR_ADD_RUNQ(me, cpu, pri); _PR_RUNQ_UNLOCK(cpu); PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: yielding")); _PR_MD_SWITCH_CONTEXT(me); PR_LOG(_pr_sched_lm, PR_LOG_MIN, ("PR_Yield: done")); _PR_FAST_INTSON(is); } else { _PR_RUNQ_UNLOCK(cpu); _PR_INTSON(is); } } } else { /* ** This is waiting for some finite period of time. ** A thread in this state is interruptible (PR_Interrupt()), ** but the lock and cvar used are local to the implementation ** and not visible to the caller, therefore not notifiable. */ PRCondVar *cv; PRIntervalTime timein; timein = PR_IntervalNow(); cv = PR_NewCondVar(_pr_sleeplock); PR_ASSERT(cv != NULL); PR_Lock(_pr_sleeplock); do { PRIntervalTime delta = PR_IntervalNow() - timein; if (delta > timeout) break; rv = PR_WaitCondVar(cv, timeout - delta); } while (rv == PR_SUCCESS); PR_Unlock(_pr_sleeplock); PR_DestroyCondVar(cv); } return rv; } PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thread) { return thread->id; } PR_IMPLEMENT(PRThreadPriority) PR_GetThreadPriority(const PRThread *thread) { return (PRThreadPriority) thread->priority; } PR_IMPLEMENT(PRThread *) PR_GetCurrentThread() { if (!_pr_initialized) _PR_ImplicitInitialization(); return _PR_MD_CURRENT_THREAD(); } /* ** Set the interrupt flag for a thread. The thread will be unable to ** block in i/o functions when this happens. Also, any PR_Wait's in ** progress will be undone. The interrupt remains in force until ** PR_ClearInterrupt is called. */ PR_IMPLEMENT(PRStatus) PR_Interrupt(PRThread *thread) { #ifdef _PR_GLOBAL_THREADS_ONLY PRCondVar *victim; _PR_THREAD_LOCK(thread); thread->flags |= _PR_INTERRUPT; victim = thread->wait.cvar; _PR_THREAD_UNLOCK(thread); if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) { int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD()); if (!haveLock) PR_Lock(victim->lock); PR_NotifyAllCondVar(victim); if (!haveLock) PR_Unlock(victim->lock); } return PR_SUCCESS; #else /* ! _PR_GLOBAL_THREADS_ONLY */ PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(thread); thread->flags |= _PR_INTERRUPT; switch (thread->state) { case _PR_COND_WAIT: /* * call is made with thread locked; * on return lock is released */ if (!(thread->flags & _PR_INTERRUPT_BLOCKED)) _PR_NotifyLockedThread(thread); break; case _PR_IO_WAIT: /* * Need to hold the thread lock when calling * _PR_Unblock_IO_Wait(). On return lock is * released. */ #if defined(XP_UNIX) || defined(WINNT) || defined(WIN16) if (!(thread->flags & _PR_INTERRUPT_BLOCKED)) _PR_Unblock_IO_Wait(thread); #else _PR_THREAD_UNLOCK(thread); #endif break; case _PR_RUNNING: case _PR_RUNNABLE: case _PR_LOCK_WAIT: default: _PR_THREAD_UNLOCK(thread); break; } if (!_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); return PR_SUCCESS; #endif /* _PR_GLOBAL_THREADS_ONLY */ } /* ** Clear the interrupt flag for self. */ PR_IMPLEMENT(void) PR_ClearInterrupt() { PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(me); me->flags &= ~_PR_INTERRUPT; _PR_THREAD_UNLOCK(me); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); } PR_IMPLEMENT(void) PR_BlockInterrupt() { PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(me); _PR_THREAD_BLOCK_INTERRUPT(me); _PR_THREAD_UNLOCK(me); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); } /* PR_BlockInterrupt */ PR_IMPLEMENT(void) PR_UnblockInterrupt() { PRIntn is; PRThread *me = _PR_MD_CURRENT_THREAD(); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSOFF(is); _PR_THREAD_LOCK(me); _PR_THREAD_UNBLOCK_INTERRUPT(me); _PR_THREAD_UNLOCK(me); if ( !_PR_IS_NATIVE_THREAD(me)) _PR_INTSON(is); } /* PR_UnblockInterrupt */ /* ** Return the thread stack pointer of the given thread. */ PR_IMPLEMENT(void *) PR_GetSP(PRThread *thread) { return (void *)_PR_MD_GET_SP(thread); } PR_IMPLEMENT(void*) GetExecutionEnvironment(PRThread *thread) { return thread->environment; } PR_IMPLEMENT(void) SetExecutionEnvironment(PRThread *thread, void *env) { thread->environment = env; } PR_IMPLEMENT(PRInt32) PR_GetThreadAffinityMask(PRThread *thread, PRUint32 *mask) { #ifdef HAVE_THREAD_AFFINITY return _PR_MD_GETTHREADAFFINITYMASK(thread, mask); #else return 0; #endif } PR_IMPLEMENT(PRInt32) PR_SetThreadAffinityMask(PRThread *thread, PRUint32 mask ) { #ifdef HAVE_THREAD_AFFINITY #ifndef IRIX return _PR_MD_SETTHREADAFFINITYMASK(thread, mask); #else return 0; #endif #else return 0; #endif } /* This call is thread unsafe if another thread is calling SetConcurrency() */ PR_IMPLEMENT(PRInt32) PR_SetCPUAffinityMask(PRUint32 mask) { #ifdef HAVE_THREAD_AFFINITY PRCList *qp; extern PRUint32 _pr_cpu_affinity_mask; if (!_pr_initialized) _PR_ImplicitInitialization(); _pr_cpu_affinity_mask = mask; qp = _PR_CPUQ().next; while(qp != &_PR_CPUQ()) { _PRCPU *cpu; cpu = _PR_CPU_PTR(qp); PR_SetThreadAffinityMask(cpu->thread, mask); qp = qp->next; } #endif return 0; } PRUint32 _pr_recycleThreads = 0; PR_IMPLEMENT(void) PR_SetThreadRecycleMode(PRUint32 count) { _pr_recycleThreads = count; } PR_IMPLEMENT(PRThread*) PR_CreateThreadGCAble(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { return _PR_CreateThread(type, start, arg, priority, scope, state, stackSize, _PR_GCABLE_THREAD); } #ifdef SOLARIS PR_IMPLEMENT(PRThread*) PR_CreateThreadBound(PRThreadType type, void (*start)(void *arg), void *arg, PRUintn priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize) { return _PR_CreateThread(type, start, arg, priority, scope, state, stackSize, _PR_BOUND_THREAD); } #endif PR_IMPLEMENT(PRThread*) PR_AttachThreadGCAble( PRThreadType type, PRThreadPriority priority, PRThreadStack *stack) { /* $$$$ not sure how to finese this one */ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PR_IMPLEMENT(void) PR_SetThreadGCAble() { if (!_pr_initialized) _PR_ImplicitInitialization(); PR_Lock(_pr_activeLock); _PR_MD_CURRENT_THREAD()->flags |= _PR_GCABLE_THREAD; PR_Unlock(_pr_activeLock); } PR_IMPLEMENT(void) PR_ClearThreadGCAble() { if (!_pr_initialized) _PR_ImplicitInitialization(); PR_Lock(_pr_activeLock); _PR_MD_CURRENT_THREAD()->flags &= (~_PR_GCABLE_THREAD); PR_Unlock(_pr_activeLock); } PR_IMPLEMENT(PRThreadScope) PR_GetThreadScope(const PRThread *thread) { if (!_pr_initialized) _PR_ImplicitInitialization(); if (_PR_IS_NATIVE_THREAD(thread)) { return (thread->flags & _PR_BOUND_THREAD) ? PR_GLOBAL_BOUND_THREAD : PR_GLOBAL_THREAD; } else return PR_LOCAL_THREAD; } PR_IMPLEMENT(PRThreadType) PR_GetThreadType(const PRThread *thread) { return (thread->flags & _PR_SYSTEM) ? PR_SYSTEM_THREAD : PR_USER_THREAD; } PR_IMPLEMENT(PRThreadState) PR_GetThreadState(const PRThread *thread) { return (NULL == thread->term) ? PR_UNJOINABLE_THREAD : PR_JOINABLE_THREAD; } /* PR_GetThreadState */ nspr-4.11/nspr/pr/src/threads/prdump.c0000644000000000000000000000575612623070344016064 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #if defined(WIN95) /* ** Some local variables report warnings on Win95 because the code paths ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. ** The pragma suppresses the warning. ** */ #pragma warning(disable : 4101) #endif /* XXX use unbuffered nspr stdio */ PRFileDesc *_pr_dumpOut; PRUint32 _PR_DumpPrintf(PRFileDesc *fd, const char *fmt, ...) { char buf[100]; PRUint32 nb; va_list ap; va_start(ap, fmt); nb = PR_vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); PR_Write(fd, buf, nb); return nb; } void _PR_DumpThread(PRFileDesc *fd, PRThread *thread) { #ifndef _PR_GLOBAL_THREADS_ONLY _PR_DumpPrintf(fd, "%05d[%08p] pri=%2d flags=0x%02x", thread->id, thread, thread->priority, thread->flags); switch (thread->state) { case _PR_RUNNABLE: case _PR_RUNNING: break; case _PR_LOCK_WAIT: _PR_DumpPrintf(fd, " lock=%p", thread->wait.lock); break; case _PR_COND_WAIT: _PR_DumpPrintf(fd, " condvar=%p sleep=%lldms", thread->wait.cvar, thread->sleep); break; case _PR_SUSPENDED: _PR_DumpPrintf(fd, " suspended"); break; } PR_Write(fd, "\n", 1); #endif /* Now call dump routine */ if (thread->dump) { thread->dump(fd, thread, thread->dumpArg); } } static void DumpThreadQueue(PRFileDesc *fd, PRCList *list) { #ifndef _PR_GLOBAL_THREADS_ONLY PRCList *q; q = list->next; while (q != list) { PRThread *t = _PR_THREAD_PTR(q); _PR_DumpThread(fd, t); q = q->next; } #endif } void _PR_DumpThreads(PRFileDesc *fd) { PRThread *t; PRIntn i; _PR_DumpPrintf(fd, "Current Thread:\n"); t = _PR_MD_CURRENT_THREAD(); _PR_DumpThread(fd, t); _PR_DumpPrintf(fd, "Runnable Threads:\n"); for (i = 0; i < PR_ARRAY_SIZE(_PR_RUNQ(t->cpu)); i++) { DumpThreadQueue(fd, &_PR_RUNQ(t->cpu)[i]); } _PR_DumpPrintf(fd, "CondVar timed wait Threads:\n"); DumpThreadQueue(fd, &_PR_SLEEPQ(t->cpu)); _PR_DumpPrintf(fd, "CondVar wait Threads:\n"); DumpThreadQueue(fd, &_PR_PAUSEQ(t->cpu)); _PR_DumpPrintf(fd, "Suspended Threads:\n"); DumpThreadQueue(fd, &_PR_SUSPENDQ(t->cpu)); } PR_IMPLEMENT(void) PR_ShowStatus(void) { PRIntn is; if ( _PR_MD_CURRENT_THREAD() && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_INTSOFF(is); _pr_dumpOut = _pr_stderr; _PR_DumpThreads(_pr_dumpOut); if ( _PR_MD_CURRENT_THREAD() && !_PR_IS_NATIVE_THREAD(_PR_MD_CURRENT_THREAD())) _PR_FAST_INTSON(is); } PR_IMPLEMENT(void) PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg) { thread->dump = dump; thread->dumpArg = arg; } nspr-4.11/nspr/pr/src/threads/prmon.c0000644000000000000000000002245012623070344015676 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" /************************************************************************/ /* * Notifies just get posted to the monitor. The actual notification is done * when the monitor is fully exited so that MP systems don't contend for a * monitor that they can't enter. */ static void _PR_PostNotifyToMonitor(PRMonitor *mon, PRBool broadcast) { PR_ASSERT(mon != NULL); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mon); /* mon->notifyTimes is protected by the monitor, so we don't need to * acquire mon->lock. */ if (broadcast) mon->notifyTimes = -1; else if (mon->notifyTimes != -1) mon->notifyTimes += 1; } static void _PR_PostNotifiesFromMonitor(PRCondVar *cv, PRIntn times) { PRStatus rv; /* * Time to actually notify any waits that were affected while the monitor * was entered. */ PR_ASSERT(cv != NULL); PR_ASSERT(times != 0); if (times == -1) { rv = PR_NotifyAllCondVar(cv); PR_ASSERT(rv == PR_SUCCESS); } else { while (times-- > 0) { rv = PR_NotifyCondVar(cv); PR_ASSERT(rv == PR_SUCCESS); } } } /* ** Create a new monitor. */ PR_IMPLEMENT(PRMonitor*) PR_NewMonitor() { PRMonitor *mon; PRStatus rv; if (!_pr_initialized) _PR_ImplicitInitialization(); mon = PR_NEWZAP(PRMonitor); if (mon == NULL) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } rv = _PR_InitLock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); if (rv != PR_SUCCESS) goto error1; mon->owner = NULL; rv = _PR_InitCondVar(&mon->entryCV, &mon->lock); PR_ASSERT(rv == PR_SUCCESS); if (rv != PR_SUCCESS) goto error2; rv = _PR_InitCondVar(&mon->waitCV, &mon->lock); PR_ASSERT(rv == PR_SUCCESS); if (rv != PR_SUCCESS) goto error3; mon->notifyTimes = 0; mon->entryCount = 0; mon->name = NULL; return mon; error3: _PR_FreeCondVar(&mon->entryCV); error2: _PR_FreeLock(&mon->lock); error1: PR_Free(mon); return NULL; } PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name) { PRMonitor* mon = PR_NewMonitor(); if (mon) mon->name = name; return mon; } /* ** Destroy a monitor. There must be no thread waiting on the monitor's ** condition variable. The caller is responsible for guaranteeing that the ** monitor is no longer in use. */ PR_IMPLEMENT(void) PR_DestroyMonitor(PRMonitor *mon) { PR_ASSERT(mon != NULL); _PR_FreeCondVar(&mon->waitCV); _PR_FreeCondVar(&mon->entryCV); _PR_FreeLock(&mon->lock); #if defined(DEBUG) memset(mon, 0xaf, sizeof(PRMonitor)); #endif PR_Free(mon); } /* ** Enter the lock associated with the monitor. */ PR_IMPLEMENT(void) PR_EnterMonitor(PRMonitor *mon) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRStatus rv; PR_ASSERT(mon != NULL); PR_Lock(&mon->lock); if (mon->entryCount != 0) { if (mon->owner == me) goto done; while (mon->entryCount != 0) { rv = PR_WaitCondVar(&mon->entryCV, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(rv == PR_SUCCESS); } } /* and now I have the monitor */ PR_ASSERT(mon->notifyTimes == 0); PR_ASSERT(mon->owner == NULL); mon->owner = me; done: mon->entryCount += 1; rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); } /* ** Test and then enter the lock associated with the monitor if it's not ** already entered by some other thread. Return PR_FALSE if some other ** thread owned the lock at the time of the call. */ PR_IMPLEMENT(PRBool) PR_TestAndEnterMonitor(PRMonitor *mon) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRStatus rv; PR_ASSERT(mon != NULL); PR_Lock(&mon->lock); if (mon->entryCount != 0) { if (mon->owner == me) goto done; rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); return PR_FALSE; } /* and now I have the monitor */ PR_ASSERT(mon->notifyTimes == 0); PR_ASSERT(mon->owner == NULL); mon->owner = me; done: mon->entryCount += 1; rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); return PR_TRUE; } /* ** Exit the lock associated with the monitor once. */ PR_IMPLEMENT(PRStatus) PR_ExitMonitor(PRMonitor *mon) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRStatus rv; PR_ASSERT(mon != NULL); PR_Lock(&mon->lock); /* the entries should be > 0 and we'd better be the owner */ PR_ASSERT(mon->entryCount > 0); PR_ASSERT(mon->owner == me); if (mon->entryCount == 0 || mon->owner != me) { rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); return PR_FAILURE; } mon->entryCount -= 1; /* reduce by one */ if (mon->entryCount == 0) { /* and if it transitioned to zero - notify an entry waiter */ /* make the owner unknown */ mon->owner = NULL; if (mon->notifyTimes != 0) { _PR_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes); mon->notifyTimes = 0; } rv = PR_NotifyCondVar(&mon->entryCV); PR_ASSERT(rv == PR_SUCCESS); } rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); return PR_SUCCESS; } /* ** Return the number of times that the current thread has entered the ** lock. Returns zero if the current thread has not entered the lock. */ PR_IMPLEMENT(PRIntn) PR_GetMonitorEntryCount(PRMonitor *mon) { PRThread *me = _PR_MD_CURRENT_THREAD(); PRStatus rv; PRIntn count = 0; PR_Lock(&mon->lock); if (mon->owner == me) count = mon->entryCount; rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); return count; } PR_IMPLEMENT(void) PR_AssertCurrentThreadInMonitor(PRMonitor *mon) { #if defined(DEBUG) || defined(FORCE_PR_ASSERT) PRStatus rv; PR_Lock(&mon->lock); PR_ASSERT(mon->entryCount != 0 && mon->owner == _PR_MD_CURRENT_THREAD()); rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); #endif } /* ** Wait for a notify on the condition variable. Sleep for "ticks" amount ** of time (if "tick" is 0 then the sleep is indefinite). While ** the thread is waiting it exits the monitors lock (as if it called ** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When ** the wait has finished the thread regains control of the monitors lock ** with the same entry count as before the wait began. ** ** The thread waiting on the monitor will be resumed when the monitor is ** notified (assuming the thread is the next in line to receive the ** notify) or when the "ticks" elapses. ** ** Returns PR_FAILURE if the caller has not locked the lock associated ** with the condition variable. ** This routine can return PR_PENDING_INTERRUPT_ERROR if the waiting thread ** has been interrupted. */ PR_IMPLEMENT(PRStatus) PR_Wait(PRMonitor *mon, PRIntervalTime ticks) { PRStatus rv; PRUint32 saved_entries; PRThread *saved_owner; PR_ASSERT(mon != NULL); PR_Lock(&mon->lock); /* the entries better be positive */ PR_ASSERT(mon->entryCount > 0); /* and it better be owned by us */ PR_ASSERT(mon->owner == _PR_MD_CURRENT_THREAD()); /* XXX return failure */ /* tuck these away 'till later */ saved_entries = mon->entryCount; mon->entryCount = 0; saved_owner = mon->owner; mon->owner = NULL; /* If we have pending notifies, post them now. */ if (mon->notifyTimes != 0) { _PR_PostNotifiesFromMonitor(&mon->waitCV, mon->notifyTimes); mon->notifyTimes = 0; } rv = PR_NotifyCondVar(&mon->entryCV); PR_ASSERT(rv == PR_SUCCESS); rv = PR_WaitCondVar(&mon->waitCV, ticks); PR_ASSERT(rv == PR_SUCCESS); while (mon->entryCount != 0) { rv = PR_WaitCondVar(&mon->entryCV, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(rv == PR_SUCCESS); } PR_ASSERT(mon->notifyTimes == 0); /* reinstate the interesting information */ mon->entryCount = saved_entries; mon->owner = saved_owner; rv = PR_Unlock(&mon->lock); PR_ASSERT(rv == PR_SUCCESS); return rv; } /* ** Notify the highest priority thread waiting on the condition ** variable. If a thread is waiting on the condition variable (using ** PR_Wait) then it is awakened and begins waiting on the monitor's lock. */ PR_IMPLEMENT(PRStatus) PR_Notify(PRMonitor *mon) { _PR_PostNotifyToMonitor(mon, PR_FALSE); return PR_SUCCESS; } /* ** Notify all of the threads waiting on the condition variable. All of ** threads are notified in turn. The highest priority thread will ** probably acquire the monitor first when the monitor is exited. */ PR_IMPLEMENT(PRStatus) PR_NotifyAll(PRMonitor *mon) { _PR_PostNotifyToMonitor(mon, PR_TRUE); return PR_SUCCESS; } /************************************************************************/ PRUint32 _PR_MonitorToString(PRMonitor *mon, char *buf, PRUint32 buflen) { PRUint32 nb; if (mon->owner) { nb = PR_snprintf(buf, buflen, "[%p] owner=%d[%p] count=%ld", mon, mon->owner->id, mon->owner, mon->entryCount); } else { nb = PR_snprintf(buf, buflen, "[%p]", mon); } return nb; } nspr-4.11/nspr/pr/src/threads/prrwlock.c0000644000000000000000000002647512623070344016421 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include #if defined(HPUX) && defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include #define HAVE_UNIX98_RWLOCK #define RWLOCK_T pthread_rwlock_t #define RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL) #define RWLOCK_DESTROY(lock) pthread_rwlock_destroy(lock) #define RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock) #define RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock) #define RWLOCK_UNLOCK(lock) pthread_rwlock_unlock(lock) #elif defined(SOLARIS) && (defined(_PR_PTHREADS) \ || defined(_PR_GLOBAL_THREADS_ONLY)) #include #define HAVE_UI_RWLOCK #define RWLOCK_T rwlock_t #define RWLOCK_INIT(lock) rwlock_init(lock, USYNC_THREAD, NULL) #define RWLOCK_DESTROY(lock) rwlock_destroy(lock) #define RWLOCK_RDLOCK(lock) rw_rdlock(lock) #define RWLOCK_WRLOCK(lock) rw_wrlock(lock) #define RWLOCK_UNLOCK(lock) rw_unlock(lock) #endif /* * Reader-writer lock */ struct PRRWLock { char *rw_name; /* lock name */ PRUint32 rw_rank; /* rank of the lock */ #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) RWLOCK_T rw_lock; #else PRLock *rw_lock; PRInt32 rw_lock_cnt; /* == 0, if unlocked */ /* == -1, if write-locked */ /* > 0 , # of read locks */ PRUint32 rw_reader_cnt; /* number of waiting readers */ PRUint32 rw_writer_cnt; /* number of waiting writers */ PRCondVar *rw_reader_waitq; /* cvar for readers */ PRCondVar *rw_writer_waitq; /* cvar for writers */ #ifdef DEBUG PRThread *rw_owner; /* lock owner for write-lock */ #endif #endif }; #ifdef DEBUG #define _PR_RWLOCK_RANK_ORDER_DEBUG /* enable deadlock detection using rank-order for locks */ #endif #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG static PRUintn pr_thread_rwlock_key; /* TPD key for lock stack */ static PRUintn pr_thread_rwlock_alloc_failed; #define _PR_RWLOCK_RANK_ORDER_LIMIT 10 typedef struct thread_rwlock_stack { PRInt32 trs_index; /* top of stack */ PRRWLock *trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT]; /* stack of lock pointers */ } thread_rwlock_stack; static void _PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock); static PRUint32 _PR_GET_THREAD_RWLOCK_RANK(void); static void _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock); static void _PR_RELEASE_LOCK_STACK(void *lock_stack); #endif /* * Reader/Writer Locks */ /* * PR_NewRWLock * Create a reader-writer lock, with the given lock rank and lock name * */ PR_IMPLEMENT(PRRWLock *) PR_NewRWLock(PRUint32 lock_rank, const char *lock_name) { PRRWLock *rwlock; #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) int err; #endif if (!_pr_initialized) _PR_ImplicitInitialization(); rwlock = PR_NEWZAP(PRRWLock); if (rwlock == NULL) return NULL; rwlock->rw_rank = lock_rank; if (lock_name != NULL) { rwlock->rw_name = (char*) PR_Malloc(strlen(lock_name) + 1); if (rwlock->rw_name == NULL) { PR_DELETE(rwlock); return(NULL); } strcpy(rwlock->rw_name, lock_name); } else { rwlock->rw_name = NULL; } #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) err = RWLOCK_INIT(&rwlock->rw_lock); if (err != 0) { PR_SetError(PR_UNKNOWN_ERROR, err); PR_Free(rwlock->rw_name); PR_DELETE(rwlock); return NULL; } return rwlock; #else rwlock->rw_lock = PR_NewLock(); if (rwlock->rw_lock == NULL) { goto failed; } rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock); if (rwlock->rw_reader_waitq == NULL) { goto failed; } rwlock->rw_writer_waitq = PR_NewCondVar(rwlock->rw_lock); if (rwlock->rw_writer_waitq == NULL) { goto failed; } rwlock->rw_reader_cnt = 0; rwlock->rw_writer_cnt = 0; rwlock->rw_lock_cnt = 0; return rwlock; failed: if (rwlock->rw_reader_waitq != NULL) { PR_DestroyCondVar(rwlock->rw_reader_waitq); } if (rwlock->rw_lock != NULL) { PR_DestroyLock(rwlock->rw_lock); } PR_Free(rwlock->rw_name); PR_DELETE(rwlock); return NULL; #endif } /* ** Destroy the given RWLock "lock". */ PR_IMPLEMENT(void) PR_DestroyRWLock(PRRWLock *rwlock) { #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) int err; err = RWLOCK_DESTROY(&rwlock->rw_lock); PR_ASSERT(err == 0); #else PR_ASSERT(rwlock->rw_reader_cnt == 0); PR_DestroyCondVar(rwlock->rw_reader_waitq); PR_DestroyCondVar(rwlock->rw_writer_waitq); PR_DestroyLock(rwlock->rw_lock); #endif if (rwlock->rw_name != NULL) PR_Free(rwlock->rw_name); PR_DELETE(rwlock); } /* ** Read-lock the RWLock. */ PR_IMPLEMENT(void) PR_RWLock_Rlock(PRRWLock *rwlock) { #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) int err; #endif #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG /* * assert that rank ordering is not violated; the rank of 'rwlock' should * be equal to or greater than the highest rank of all the locks held by * the thread. */ PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) || (rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK())); #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) err = RWLOCK_RDLOCK(&rwlock->rw_lock); PR_ASSERT(err == 0); #else PR_Lock(rwlock->rw_lock); /* * wait if write-locked or if a writer is waiting; preference for writers */ while ((rwlock->rw_lock_cnt < 0) || (rwlock->rw_writer_cnt > 0)) { rwlock->rw_reader_cnt++; PR_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT); rwlock->rw_reader_cnt--; } /* * Increment read-lock count */ rwlock->rw_lock_cnt++; PR_Unlock(rwlock->rw_lock); #endif #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG /* * update thread's lock rank */ if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE) _PR_SET_THREAD_RWLOCK_RANK(rwlock); #endif } /* ** Write-lock the RWLock. */ PR_IMPLEMENT(void) PR_RWLock_Wlock(PRRWLock *rwlock) { #if defined(DEBUG) PRThread *me = PR_GetCurrentThread(); #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) int err; #endif #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG /* * assert that rank ordering is not violated; the rank of 'rwlock' should * be equal to or greater than the highest rank of all the locks held by * the thread. */ PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) || (rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK())); #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) err = RWLOCK_WRLOCK(&rwlock->rw_lock); PR_ASSERT(err == 0); #else PR_Lock(rwlock->rw_lock); /* * wait if read locked */ while (rwlock->rw_lock_cnt != 0) { rwlock->rw_writer_cnt++; PR_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT); rwlock->rw_writer_cnt--; } /* * apply write lock */ rwlock->rw_lock_cnt--; PR_ASSERT(rwlock->rw_lock_cnt == -1); #ifdef DEBUG PR_ASSERT(me != NULL); rwlock->rw_owner = me; #endif PR_Unlock(rwlock->rw_lock); #endif #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG /* * update thread's lock rank */ if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE) _PR_SET_THREAD_RWLOCK_RANK(rwlock); #endif } /* ** Unlock the RW lock. */ PR_IMPLEMENT(void) PR_RWLock_Unlock(PRRWLock *rwlock) { #if defined(DEBUG) PRThread *me = PR_GetCurrentThread(); #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) int err; #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) err = RWLOCK_UNLOCK(&rwlock->rw_lock); PR_ASSERT(err == 0); #else PR_Lock(rwlock->rw_lock); /* * lock must be read or write-locked */ PR_ASSERT(rwlock->rw_lock_cnt != 0); if (rwlock->rw_lock_cnt > 0) { /* * decrement read-lock count */ rwlock->rw_lock_cnt--; if (rwlock->rw_lock_cnt == 0) { /* * lock is not read-locked anymore; wakeup a waiting writer */ if (rwlock->rw_writer_cnt > 0) PR_NotifyCondVar(rwlock->rw_writer_waitq); } } else { PR_ASSERT(rwlock->rw_lock_cnt == -1); rwlock->rw_lock_cnt = 0; #ifdef DEBUG PR_ASSERT(rwlock->rw_owner == me); rwlock->rw_owner = NULL; #endif /* * wakeup a writer, if present; preference for writers */ if (rwlock->rw_writer_cnt > 0) PR_NotifyCondVar(rwlock->rw_writer_waitq); /* * else, wakeup all readers, if any */ else if (rwlock->rw_reader_cnt > 0) PR_NotifyAllCondVar(rwlock->rw_reader_waitq); } PR_Unlock(rwlock->rw_lock); #endif #ifdef _PR_RWLOCK_RANK_ORDER_DEBUG /* * update thread's lock rank */ if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE) _PR_UNSET_THREAD_RWLOCK_RANK(rwlock); #endif return; } #ifndef _PR_RWLOCK_RANK_ORDER_DEBUG void _PR_InitRWLocks(void) { } #else void _PR_InitRWLocks(void) { /* * allocated thread-private-data index for rwlock list */ if (PR_NewThreadPrivateIndex(&pr_thread_rwlock_key, _PR_RELEASE_LOCK_STACK) == PR_FAILURE) { pr_thread_rwlock_alloc_failed = 1; return; } } /* * _PR_SET_THREAD_RWLOCK_RANK * Set a thread's lock rank, which is the highest of the ranks of all * the locks held by the thread. Pointers to the locks are added to a * per-thread list, which is anchored off a thread-private data key. */ static void _PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock) { thread_rwlock_stack *lock_stack; PRStatus rv; /* * allocate a lock stack */ if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL) { lock_stack = (thread_rwlock_stack *) PR_CALLOC(1 * sizeof(thread_rwlock_stack)); if (lock_stack) { rv = PR_SetThreadPrivate(pr_thread_rwlock_key, lock_stack); if (rv == PR_FAILURE) { PR_DELETE(lock_stack); pr_thread_rwlock_alloc_failed = 1; return; } } else { pr_thread_rwlock_alloc_failed = 1; return; } } /* * add rwlock to lock stack, if limit is not exceeded */ if (lock_stack) { if (lock_stack->trs_index < _PR_RWLOCK_RANK_ORDER_LIMIT) lock_stack->trs_stack[lock_stack->trs_index++] = rwlock; } } static void _PR_RELEASE_LOCK_STACK(void *lock_stack) { PR_ASSERT(lock_stack); PR_DELETE(lock_stack); } /* * _PR_GET_THREAD_RWLOCK_RANK * * return thread's lock rank. If thread-private-data for the lock * stack is not allocated, return PR_RWLOCK_RANK_NONE. */ static PRUint32 _PR_GET_THREAD_RWLOCK_RANK(void) { thread_rwlock_stack *lock_stack; lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key); if (lock_stack == NULL || lock_stack->trs_index == 0) return (PR_RWLOCK_RANK_NONE); else return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank); } /* * _PR_UNSET_THREAD_RWLOCK_RANK * * remove the rwlock from the lock stack. Since locks may not be * unlocked in a FIFO order, the entire lock stack is searched. */ static void _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock) { thread_rwlock_stack *lock_stack; int new_index = 0, index, done = 0; lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key); PR_ASSERT(lock_stack != NULL); for (index = lock_stack->trs_index - 1; index >= 0; index--) { if (!done && (lock_stack->trs_stack[index] == rwlock)) { /* * reset the slot for rwlock */ lock_stack->trs_stack[index] = NULL; done = 1; } /* * search for the lowest-numbered empty slot, above which there are * no non-empty slots */ if (!new_index && (lock_stack->trs_stack[index] != NULL)) new_index = index + 1; if (done && new_index) break; } /* * set top of stack to highest numbered empty slot */ lock_stack->trs_index = new_index; } #endif /* _PR_RWLOCK_RANK_ORDER_DEBUG */ nspr-4.11/nspr/pr/src/threads/prsem.c0000644000000000000000000000665312623070344015700 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "primpl.h" #include "obsolete/prsem.h" /************************************************************************/ /* ** Create a new semaphore. */ PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value) { PRSemaphore *sem; PRCondVar *cvar; PRLock *lock; sem = PR_NEWZAP(PRSemaphore); if (sem) { #ifdef HAVE_CVAR_BUILT_ON_SEM _PR_MD_NEW_SEM(&sem->md, value); #else lock = PR_NewLock(); if (!lock) { PR_DELETE(sem); return NULL; } cvar = PR_NewCondVar(lock); if (!cvar) { PR_DestroyLock(lock); PR_DELETE(sem); return NULL; } sem->cvar = cvar; sem->count = value; #endif } return sem; } /* ** Destroy a semaphore. There must be no thread waiting on the semaphore. ** The caller is responsible for guaranteeing that the semaphore is ** no longer in use. */ PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *sem) { #ifdef HAVE_CVAR_BUILT_ON_SEM _PR_MD_DESTROY_SEM(&sem->md); #else PR_ASSERT(sem->waiters == 0); PR_DestroyLock(sem->cvar->lock); PR_DestroyCondVar(sem->cvar); #endif PR_DELETE(sem); } /* ** Wait on a Semaphore. ** ** This routine allows a calling thread to wait or proceed depending upon the ** state of the semahore sem. The thread can proceed only if the counter value ** of the semaphore sem is currently greater than 0. If the value of semaphore ** sem is positive, it is decremented by one and the routine returns immediately ** allowing the calling thread to continue. If the value of semaphore sem is 0, ** the calling thread blocks awaiting the semaphore to be released by another ** thread. ** ** This routine can return PR_PENDING_INTERRUPT if the waiting thread ** has been interrupted. */ PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *sem) { PRStatus status = PR_SUCCESS; #ifdef HAVE_CVAR_BUILT_ON_SEM return _PR_MD_WAIT_SEM(&sem->md); #else PR_Lock(sem->cvar->lock); while (sem->count == 0) { sem->waiters++; status = PR_WaitCondVar(sem->cvar, PR_INTERVAL_NO_TIMEOUT); sem->waiters--; if (status != PR_SUCCESS) break; } if (status == PR_SUCCESS) sem->count--; PR_Unlock(sem->cvar->lock); #endif return (status); } /* ** This routine increments the counter value of the semaphore. If other threads ** are blocked for the semaphore, then the scheduler will determine which ONE ** thread will be unblocked. */ PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *sem) { #ifdef HAVE_CVAR_BUILT_ON_SEM _PR_MD_POST_SEM(&sem->md); #else PR_Lock(sem->cvar->lock); if (sem->waiters) PR_NotifyCondVar(sem->cvar); sem->count++; PR_Unlock(sem->cvar->lock); #endif } #if DEBUG /* ** Returns the value of the semaphore referenced by sem without affecting ** the state of the semaphore. The value represents the semaphore vaule ** at the time of the call, but may not be the actual value when the ** caller inspects it. (FOR DEBUGGING ONLY) */ PR_IMPLEMENT(PRUintn) PR_GetValueSem(PRSemaphore *sem) { PRUintn rv; #ifdef HAVE_CVAR_BUILT_ON_SEM rv = _PR_MD_GET_VALUE_SEM(&sem->md); #else PR_Lock(sem->cvar->lock); rv = sem->count; PR_Unlock(sem->cvar->lock); #endif return rv; } #endif nspr-4.11/nspr/pr/src/threads/prtpd.c0000644000000000000000000002021712623070344015673 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Thread Private Data ** ** There is an aribitrary limit on the number of keys that will be allocated ** by the runtime. It's largish, so it is intended to be a sanity check, not ** an impediment. ** ** There is a counter, initialized to zero and incremented every time a ** client asks for a new key, that holds the high water mark for keys. All ** threads logically have the same high water mark and are permitted to ** ask for TPD up to that key value. ** ** The vector to hold the TPD are allocated when PR_SetThreadPrivate() is ** called. The size of the vector will be some value greater than or equal ** to the current high water mark. Each thread has its own TPD length and ** vector. ** ** Threads that get private data for keys they have not set (or perhaps ** don't even exist for that thread) get a NULL return. If the key is ** beyond the high water mark, an error will be returned. */ /* ** As of this time, BeOS has its own TPD implementation. Integrating ** this standard one is a TODO for anyone with a bit of spare time on ** their hand. For now, we just #ifdef out this whole file and use ** the routines in pr/src/btthreads/ */ #ifndef XP_BEOS #include "primpl.h" #include #if defined(WIN95) /* ** Some local variables report warnings on Win95 because the code paths ** using them are conditioned on HAVE_CUSTOME_USER_THREADS. ** The pragma suppresses the warning. ** */ #pragma warning(disable : 4101) #endif #define _PR_TPD_LIMIT 128 /* arbitary limit on the TPD slots */ static PRInt32 _pr_tpd_length = 0; /* current length of destructor vector */ static PRInt32 _pr_tpd_highwater = 0; /* next TPD key to be assigned */ static PRThreadPrivateDTOR *_pr_tpd_destructors = NULL; /* the destructors are associated with the keys, therefore asserting that the TPD key depicts the data's 'type' */ /* ** Initialize the thread private data manipulation */ void _PR_InitTPD(void) { _pr_tpd_destructors = (PRThreadPrivateDTOR*) PR_CALLOC(_PR_TPD_LIMIT * sizeof(PRThreadPrivateDTOR*)); PR_ASSERT(NULL != _pr_tpd_destructors); _pr_tpd_length = _PR_TPD_LIMIT; } /* ** Clean up the thread private data manipulation */ void _PR_CleanupTPD(void) { } /* _PR_CleanupTPD */ /* ** This routine returns a new index for per-thread-private data table. ** The index is visible to all threads within a process. This index can ** be used with the PR_SetThreadPrivate() and PR_GetThreadPrivate() routines ** to save and retrieve data associated with the index for a thread. ** ** The index independently maintains specific values for each binding thread. ** A thread can only get access to its own thread-specific-data. ** ** Upon a new index return the value associated with the index for all threads ** is NULL, and upon thread creation the value associated with all indices for ** that thread is NULL. ** ** "dtor" is the destructor function to invoke when the private ** data is set or destroyed ** ** Returns PR_FAILURE if the total number of indices will exceed the maximun ** allowed. */ PR_IMPLEMENT(PRStatus) PR_NewThreadPrivateIndex( PRUintn *newIndex, PRThreadPrivateDTOR dtor) { PRStatus rv; PRInt32 index; if (!_pr_initialized) _PR_ImplicitInitialization(); PR_ASSERT(NULL != newIndex); PR_ASSERT(NULL != _pr_tpd_destructors); index = PR_ATOMIC_INCREMENT(&_pr_tpd_highwater) - 1; /* allocate index */ if (_PR_TPD_LIMIT <= index) { PR_SetError(PR_TPD_RANGE_ERROR, 0); rv = PR_FAILURE; /* that's just wrong */ } else { _pr_tpd_destructors[index] = dtor; /* record destructor @index */ *newIndex = (PRUintn)index; /* copy into client's location */ rv = PR_SUCCESS; /* that's okay */ } return rv; } /* ** Define some per-thread-private data. ** "index" is an index into the per-thread private data table ** "priv" is the per-thread-private data ** ** If the per-thread private data table has a previously registered ** destructor function and a non-NULL per-thread-private data value, ** the destructor function is invoked. ** ** This can return PR_FAILURE if index is invalid (ie., beyond the limit ** on the TPD slots) or memory is insufficient to allocate an expanded ** vector. */ PR_IMPLEMENT(PRStatus) PR_SetThreadPrivate(PRUintn index, void *priv) { PRThread *self = PR_GetCurrentThread(); /* ** To improve performance, we don't check if the index has been ** allocated. */ if (index >= _PR_TPD_LIMIT) { PR_SetError(PR_TPD_RANGE_ERROR, 0); return PR_FAILURE; } PR_ASSERT(((NULL == self->privateData) && (0 == self->tpdLength)) || ((NULL != self->privateData) && (0 != self->tpdLength))); /* ** If this thread does not have a sufficient vector for the index ** being set, go ahead and extend this vector now. */ if ((NULL == self->privateData) || (self->tpdLength <= index)) { void *extension = PR_CALLOC(_pr_tpd_length * sizeof(void*)); if (NULL == extension) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return PR_FAILURE; } if (self->privateData) { (void)memcpy( extension, self->privateData, self->tpdLength * sizeof(void*)); PR_DELETE(self->privateData); } self->tpdLength = _pr_tpd_length; self->privateData = (void**)extension; } /* ** There wasn't much chance of having to call the destructor ** unless the slot already existed. */ else if (self->privateData[index] && _pr_tpd_destructors[index]) { void *data = self->privateData[index]; self->privateData[index] = NULL; (*_pr_tpd_destructors[index])(data); } PR_ASSERT(index < self->tpdLength); self->privateData[index] = priv; return PR_SUCCESS; } /* ** Recover the per-thread-private data for the current thread. "index" is ** the index into the per-thread private data table. ** ** The returned value may be NULL which is indistinguishable from an error ** condition. ** */ PR_IMPLEMENT(void*) PR_GetThreadPrivate(PRUintn index) { PRThread *self = PR_GetCurrentThread(); void *tpd = ((NULL == self->privateData) || (index >= self->tpdLength)) ? NULL : self->privateData[index]; return tpd; } /* ** Destroy the thread's private data, if any exists. This is called at ** thread termination time only. There should be no threading issues ** since this is being called by the thread itself. */ void _PR_DestroyThreadPrivate(PRThread* self) { #define _PR_TPD_DESTRUCTOR_ITERATIONS 4 if (NULL != self->privateData) /* we have some */ { PRBool clean; PRUint32 index; PRInt32 passes = _PR_TPD_DESTRUCTOR_ITERATIONS; PR_ASSERT(0 != self->tpdLength); do { clean = PR_TRUE; for (index = 0; index < self->tpdLength; ++index) { void *priv = self->privateData[index]; /* extract */ if (NULL != priv) /* we have data at this index */ { if (NULL != _pr_tpd_destructors[index]) { self->privateData[index] = NULL; /* precondition */ (*_pr_tpd_destructors[index])(priv); /* destroy */ clean = PR_FALSE; /* unknown side effects */ } } } } while ((--passes > 0) && !clean); /* limit # of passes */ /* ** We give up after a fixed number of passes. Any non-NULL ** thread-private data value with a registered destructor ** function is not destroyed. */ memset(self->privateData, 0, self->tpdLength * sizeof(void*)); } } /* _PR_DestroyThreadPrivate */ #endif /* !XP_BEOS */ nspr-4.11/nspr/pr/tests/.cvsignore0000644000000000000000000000001112623070344015305 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/tests/Makefile.in0000644000000000000000000002532012623070344015364 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk DIRS = dll CSRCS = \ accept.c \ acceptread.c \ acceptreademu.c \ addrstr.c \ affinity.c \ alarm.c \ anonfm.c \ append.c \ atomic.c \ attach.c \ bigfile.c \ bigfile2.c \ bigfile3.c \ cleanup.c \ cltsrv.c \ concur.c \ cvar.c \ cvar2.c \ dceemu.c \ dlltest.c \ dtoa.c \ env.c \ errcodes.c \ errset.c \ exit.c \ fdcach.c \ fileio.c \ foreign.c \ forktest.c \ formattm.c \ fsync.c \ getai.c \ gethost.c \ getproto.c \ i2l.c \ initclk.c \ inrval.c \ instrumt.c \ intrio.c \ intrupt.c \ io_timeout.c \ ioconthr.c \ ipv6.c \ join.c \ joinkk.c \ joinku.c \ joinuk.c \ joinuu.c \ layer.c \ lazyinit.c \ libfilename.c \ lltest.c \ lock.c \ lockfile.c \ logfile.c \ logger.c \ makedir.c \ mbcs.c \ multiacc.c \ multiwait.c \ many_cv.c \ monref.c \ nameshm1.c \ nbconn.c \ nblayer.c \ nonblock.c \ ntioto.c \ ntoh.c \ obsints.c \ op_2long.c \ op_excl.c \ op_filnf.c \ op_filok.c \ op_noacc.c \ op_nofil.c \ openfile.c \ parent.c \ parsetm.c \ peek.c \ perf.c \ pipeping.c \ pipeping2.c \ pipepong.c \ pipepong2.c \ pipeself.c \ poll_er.c \ poll_nm.c \ poll_to.c \ pollable.c \ prfdbl.c \ prftest.c \ prftest1.c \ prftest2.c \ prfz.c \ primblok.c \ priotest.c \ provider.c \ prpoll.c \ prpollml.c \ pushtop.c \ ranfile.c \ randseed.c \ reinit.c \ rmdir.c \ rwlockrank.c \ rwlocktest.c \ sel_spd.c \ selct_er.c \ selct_nm.c \ selct_to.c \ select2.c \ selintr.c \ sem.c \ sema.c \ semaerr.c \ semaerr1.c \ semaping.c \ semapong.c \ sendzlf.c \ server_test.c \ servr_kk.c \ servr_ku.c \ servr_uk.c \ servr_uu.c \ short_thread.c \ sigpipe.c \ socket.c \ sockopt.c \ sockping.c \ sockpong.c \ sprintf.c \ sproc_ch.c \ sproc_p.c \ stack.c \ stdio.c \ str2addr.c \ strod.c \ suspend.c \ switch.c \ system.c \ testbit.c \ testfile.c \ thrpool_server.c \ thrpool_client.c \ threads.c \ thruput.c \ timemac.c \ timetest.c \ tmoacc.c \ tmocon.c \ tpd.c \ vercheck.c \ version.c \ udpsrv.c \ writev.c \ xnotify.c \ y2k.c \ y2ktmo.c \ zerolen.c \ $(NULL) ifeq ($(OS_ARCH),WINCE) CFLAGS += -FImozce_shunt.h -Zi -UDEBUG -DNDEBUG LDOPTS += -link $(DIST)/lib/mozce_shunt.lib ws2.lib -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO -PDB:$(@:.exe=.pdb) endif ifeq ($(OS_TARGET),OS2) CSRCS += \ sleep.c \ stat.c \ yield.c \ $(NULL) endif ifeq (,$(filter-out WINCE WINNT OS2,$(OS_ARCH))) PROG_SUFFIX = .exe DLL_SUFFIX = .dll else PROG_SUFFIX = DLL_SUFFIX = endif PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX))) TARGETS = $(PROGS) INCLUDES = -I$(dist_includedir) -I$(topsrcdir)/pr/include -I$(topsrcdir)/pr/include/private ifeq ($(OS_ARCH), WINNT) ifdef NS_USE_GCC EXTRA_LIBS += -lws2_32 else EXTRA_LIBS += ws2_32.lib LDOPTS = -NOLOGO -DEBUG -DEBUGTYPE:CV -INCREMENTAL:NO ifdef PROFILE LDOPTS += -PROFILE -MAP endif # profile endif # NS_USE_GCC endif ifeq ($(OS_ARCH),OS2) EXTRA_LIBS = $(OS_LIBS) LDOPTS = -Zomf -Zlinker /PM:VIO -Zlinker /ST:0x64000 endif ifneq ($(OS_ARCH), WINNT) # Use an absolute pathname as the runtime library path (for the -R # or -rpath linker option or the LD_RUN_PATH environment variable). ifeq (,$(patsubst /%,,$(DIST))) # $(DIST) is already an absolute pathname. ABSOLUTE_LIB_DIR = $(dist_libdir) else # $(DIST) is a relative pathname: prepend the current directory. PWD = $(shell pwd) ABSOLUTE_LIB_DIR = $(PWD)/$(dist_libdir) endif endif ifeq ($(OS_ARCH), IRIX) ifeq ($(USE_CPLUS), 1) CC = CC endif LDOPTS += -rpath $(ABSOLUTE_LIB_DIR) ifdef NS_USE_GCC LDOPTS += -Wl,-rdata_shared else LDOPTS += -rdata_shared endif # For 6.x machines, include this flag ifeq ($(basename $(OS_RELEASE)),6) ifndef NS_USE_GCC ifeq ($(USE_N32),1) LDOPTS += -n32 else LDOPTS += -32 endif ifeq ($(USE_PTHREADS), 1) ifeq ($(OS_RELEASE), 6.2) LDOPTS += -Wl,-woff,85 endif endif endif endif endif ifeq ($(OS_ARCH), OSF1) ifeq ($(USE_CPLUS), 1) CC = cxx endif # I haven't figured out how to pass -rpath to cc on OSF1 V3.2, so # we do static linking. ifeq (,$(filter-out V2.0 V3.2,$(OS_RELEASE))) LIBNSPR = $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a LIBPLC = $(dist_libdir)/libplc$(MOD_MAJOR_VERSION).a EXTRA_LIBS = -lc_r else LDOPTS += -rpath $(ABSOLUTE_LIB_DIR) endif endif ifeq ($(OS_ARCH), HP-UX) LDOPTS += -z -Wl,+s,+b,$(ABSOLUTE_LIB_DIR) ifeq ($(USE_64),1) LDOPTS += +DD64 endif ifeq ($(USE_PTHREADS),1) EXTRA_LIBS = $(LIBPTHREAD) endif endif # AIX ifeq ($(OS_ARCH),AIX) LDOPTS += -blibpath:$(ABSOLUTE_LIB_DIR):/usr/lib:/lib ifneq ($(OS_ARCH)$(OS_RELEASE),AIX4.1) LDOPTS += -brtl EXTRA_LIBS = -ldl endif endif # Solaris ifeq ($(OS_ARCH), SunOS) ifdef NS_USE_GCC LDOPTS += -Xlinker -R -Xlinker $(ABSOLUTE_LIB_DIR) else ifeq ($(USE_CPLUS), 1) CC = CC endif LDOPTS += -R $(ABSOLUTE_LIB_DIR) endif ifdef USE_PTHREADS EXTRA_LIBS = -lpthread endif endif # SunOS ifeq (,$(filter-out Linux GNU GNU_%,$(OS_ARCH))) LDOPTS += -Xlinker -rpath $(ABSOLUTE_LIB_DIR) ifeq ($(USE_PTHREADS),1) EXTRA_LIBS = -lpthread endif endif ifeq ($(OS_ARCH), SCOOS) # SCO Unix needs to link against -lsocket again even though we # already linked with these system libraries when we built libnspr.so. EXTRA_LIBS = -lsocket # This hardcodes in the executable programs the directory to find # libnspr.so etc. at program startup. Equivalent to the -R or -rpath # option for ld on other platforms. export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR) endif ifeq ($(OS_ARCH),OpenUNIX) export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR) ifeq ($(USE_PTHREADS),1) LDOPTS += -pthread endif endif ifeq ($(OS_ARCH), UNIXWARE) export LD_RUN_PATH = $(ABSOLUTE_LIB_DIR) endif ifeq ($(OS_ARCH),FreeBSD) ifeq ($(USE_PTHREADS),1) LDOPTS += -pthread endif LDOPTS += -Xlinker -R $(ABSOLUTE_LIB_DIR) endif ifeq ($(OS_ARCH),OpenBSD) ifeq ($(USE_PTHREADS),1) LDOPTS += -pthread endif endif ifeq ($(OS_ARCH),BSD_OS) ifneq ($(OS_RELEASE),1.1) EXTRA_LIBS = -ldl endif endif ifeq ($(OS_ARCH),RISCOS) EXTRA_LIBS = -ldl endif ifeq ($(USE_PTHREADS),1) LIBPTHREAD = -lpthread ifeq ($(OS_ARCH),AIX) LIBPTHREAD = -lpthreads endif ifeq (,$(filter-out FreeBSD OpenBSD BSD_OS QNX Darwin OpenUNIX,$(OS_ARCH))) LIBPTHREAD = endif ifeq ($(OS_ARCH)$(basename $(OS_RELEASE)),HP-UXB.10) LIBPTHREAD = -ldce endif endif ifeq ($(OS_TARGET),Android) LIBPTHREAD = XCFLAGS = $(OS_CFLAGS) endif ##################################################### # # The rules # ##################################################### include $(topsrcdir)/config/rules.mk AIX_PRE_4_2 = 0 ifeq ($(OS_ARCH),AIX) ifeq ($(OS_RELEASE),4.1) ifneq ($(USE_PTHREADS), 1) #AIX_PRE_4_2 = 1 endif endif endif ifeq ($(AIX_PRE_4_2),1) # AIX releases prior to 4.2 need a special two-step linking hack # in order to both override the system select() and be able to # get at the original system select(). # # We use a pattern rule in ns/nspr20/config/rules.mk to generate # the .$(OBJ_SUFFIX) file from the .c source file, then do the # two-step linking hack below. $(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) rm -f $@ $(AIX_TMP) $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(MOD_MAJOR_VERSION).a $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) rm -f $(AIX_TMP) else # All platforms that are not AIX pre-4.2. $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) ifeq ($(NS_USE_GCC)_$(OS_ARCH),_WINNT) link $(LDOPTS) $(EXTRA_LDOPTS) $< $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) -out:$@ ifdef MT @if test -f $@.manifest; then \ $(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \ rm -f $@.manifest; \ fi endif else $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(EXTRA_LIBS) -o $@ endif # WINNT endif # AIX_PRE_4_2 export:: $(TARGETS) clean:: rm -f $(TARGETS) # The following tests call BSD socket functions, so they need to link # with -lsocket on some platforms. ifeq ($(OS_ARCH),SunOS) ifeq ($(USE_IPV6),1) $(OBJDIR)/gethost: $(OBJDIR)/gethost.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) -lsocket $(EXTRA_LIBS) -o $@ endif $(OBJDIR)/prpoll: $(OBJDIR)/prpoll.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) -lsocket $(EXTRA_LIBS) -o $@ endif ifeq ($(USE_PTHREADS), 1) $(OBJDIR)/attach: $(OBJDIR)/attach.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@ $(OBJDIR)/foreign: $(OBJDIR)/foreign.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@ $(OBJDIR)/provider: $(OBJDIR)/provider.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@ $(OBJDIR)/socket: $(OBJDIR)/socket.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@ $(OBJDIR)/testfile: $(OBJDIR)/testfile.o $(PURE) $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPLC) $(LIBNSPR) $(LIBPTHREAD) $(EXTRA_LIBS) -o $@ endif # # Run the test programs with no arguments # # Test output goes to the file pointed to by the environment variable # NSPR_TEST_LOGFILE, if set, else to /dev/null # ECHO = echo PROGRAMS = $(notdir $(PROGS)) ifdef NSPR_TEST_LOGFILE LOGFILE = $(NSPR_TEST_LOGFILE) else ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) LOGFILE = nul else LOGFILE = /dev/null endif endif ifeq ($(OS_TARGET),Linux) ECHO = /bin/echo endif ALWAYS: runtests:: $(PROGS) ALWAYS @$(ECHO) "\nNSPR Test Results - $(OBJDIR)\n" @$(ECHO) "BEGIN\t\t\t`date`" @$(ECHO) "NSPR_TEST_LOGFILE\t$(LOGFILE)\n" @$(ECHO) "Test\t\t\tResult\n" @cd $(OBJDIR); for i in $(PROGRAMS); do \ $(ECHO) "$$i\c"; \ ./$$i >> $(LOGFILE) 2>&1 ; \ if [ 0 = $$? ] ; then \ $(ECHO) "\t\t\tPassed"; \ else \ $(ECHO) "\t\t\tFAILED"; \ fi; \ done @$(ECHO) "\nEND\t\t`date`\n" nspr-4.11/nspr/pr/tests/README.TXT0000644000000000000000000001631412623070344014660 0ustar 00000000000000File: pr/tests/readme This document describes the test cases in the NSPR directory pr/tests. ===================================================================== There is a sub-directory here: dll sources for the .dll(.so) used by test dlltest.c ===================================================================== The individual files are described here. The script 'runtests.ksh' enumerates and runs test cases that are expected to run on all platforms. accept.c Tests PR_Accept() and related socket functions. acceptread.c Tests PR_AcceptRead() alarm.c Tests alarm functions declared in obsolete/pralarm.h. The alarm functions are obsolete, so is this test. atomic.c Tests Atomic operations defined in pratom.h attach.c Test PR_AttachThread() Note: This is an NSPR private function. bigfile.c Test 64bit file offset functions declared in prio.h bug1test.c Demonstrates a bug on NT. cleanup.c Tests PR_Cleanup() declared in prinit.h cltsrv.c Tests many socket functions. concur.c Tests threading functions and concurrent operations. cvar.c Tests condition variables. cvar2.c Tests condition variables. A rather abusive test. dbmalloc.c Obsolete. Originally for testing debug builds of NSPR's malloc. dbmalloc1.c Obsolete. Originally for testing debug builds of NSPR's malloc. dceemu.c Tests special functions for DCE emulation. depend.c Obsoltet. Tests early spec for library dependency. dlltest.c Tests dynamic library functions. Used with dll/my.c dtoa.c Tests conversions of double to string. exit.c Tests PR_ProcessExit() declared in prinit.h fileio.c Tests NSPR semaphores a bit of file i/o and threading functions. foreign.c Test auto-attach of a thread created by something other than NSPR. forktest.c Limited use. Tests unix fork() and related functions. fsync.c Tests use of PR_Sync() declared in prio.h getproto.c Tests socket functions PR_GetProtoByName(), etc. i2l.c Tests LongLong functions for converting 32bit integer to 64bit integer. initclk.c Tests timing on minimal use of condition variable inrval.c Tests interval timing functions. instrumt.c Tests instrumentation functions. prcountr.h prtrace.h intrupt.c Tests PR_Interrupt() ioconthr.c Tests i/o continuation mechanism in pthreads. io_timeout.c Test socket i/o timeouts. io_timeoutk.c Obsolete. Subsumed in io_timeout.c io_timeoutu.c Obsolete. Subsumed in io_timeout.c ipv6.c Tests IPv6. IPv6 is not used by NSPR clients. join.c Tests PR_JoinThread() joinkk.c Tests PR_JoinThread() joinku.c Tests PR_JoinThread() joinuk.c Tests PR_JoinThread() joinuu.c Tests PR_JoinThread() layer.c Tests layered I/O. lazyinit.c Tests implicit initialization. lltest.c Tests LongLong (64bit integer) arithmentic and conversions. lock.c Tests PR_Lock() in heavily threaded environment. lockfile.c Test PR_Lockfile(). logger.c Tests PR_LOG() makefile The makefile that builds all the tests many_cv.c Tests aquiring a large number of condition variables. multiwait.c ??? nbconn.c Test non-blocking connect. nblayer.c Tests NSPR's layered I/O capability. nonblock.c Tests operations on non-blocking socket. op_2long.c Tests PR_Open() where filename is too long. op_filnf.c Tests PR_Open() where filename is NotFound. op_filok.c Tests PR_Open() where filename is accessable. op_noacc.c Tests PR_Open() where file permissions are wrong. Limited use. Windows has no concept of Unix style file permissions. op_nofil.c Tests PR_Open() where filename does not exist. parent.c Test parent/child process capability perf.c Tests and measures context switch times for various thread syncronization functions. pipeping.c Tests inter-process pipes. Run with pipepong.c pipepong.c Tests inter-process pipes. Run with pipeping.c pipeself.c Tests inter-thread pipes. pollable.c Tests pollable events. prio.h poll_er.c Tests PR_Poll() where an error is expected. poll_nm.c Tests PR_Poll() where normal operation is expected. poll_to.c Tests PR_Poll() where timeout is expected. prftest.c Tests printf-like formatting. prftest1.c Obsolete. Subsumed in prftest.c prftest2.c Obsolete. Subsumed in prftest.c prfz.c Tests printf handling of (s)size_t formats priotest.c Limited use. Tests NSPR thread dispatching priority. provider.c prpoll.c Tests PR_Poll(). prselect.c Obsolete. PR_Select() is obsolete. prttools.h Unused file. ranfile.c Tests random file access. readme This file. runtests.ksh A korn shell script that runs a set of tests that should run on any of the NSPR supported platforms. runtests.pl A perl script to run the test cases. This srcipt runs tests common to all platforms and runs tests applicable to specific platforms. Uses file runtests.txt to control execution. runtests.txt Control file for perl script: runtests.pl rwlocktest.c Tests Reader/Writer lock selct_er.c Obsolete. PR_Select() is obsolete. selct_nm.c Obsolete. PR_Select() is obsolete. selct_to.c Obsolete. PR_Select() is obsolete. select2.c Obsolete. PR_Select() is obsolete. sel_spd.c Obsolete. PR_Select() is obsolete. sem.c Obsolete. Semaphores are not supported. server_test.c Tests sockets by simulating a server in loopback mode. Makes its own client threads. servr_kk.c Tests client/server sockets, threads using system threads. servr_ku.c Tests client/server sockets, threads using system and user threads. servr_uk.c Tests client/server sockets, threads using system and user threads. servr_uu.c Tests client/server sockets, threads user threads. short_thread.c Tests short-running threads. Useful for testing for race conditions. sigpipe.c Tests NSPR's SIGPIPE handler. Unix only. sleep.c Limited use. Tests sleep capability of platform. socket.c Tests many socket functions. sockopt.c Tests setting and getting socket options. sprintf.c Tests sprintf. sproc_ch.c Obsolete. Tests IRIX sproc-based threads. sproc_p.c Obsolete. Tests IRIX sproc-based threads. stack.c Test atomic stack operations. stat.c Tests performance of getfileinfo() vs. stat() stdio.c Tests NSPR's handling of stdin, stdout, stderr. strod.c Tests formatting of double precision floating point. suspend.c Private interfaces PR_SuspendAll(), PR_ResumeAll(), etc. switch.c Tests thread switching system.c Tests PR_GetSystemInfo() testbit.c Tests bit arrays. testfile.c Tests many file I/O functions. threads.c Tests thread caching. thruput.c Tests socket thruput. Must be run by hand as client/server. Does not self terminate. time.c Incomplete. Limited use. timemac.c Test time and date functions. Originally for Mac. timetest.c Tests time conversion over a wide range of dates. tmoacc.c Server to tmocon.c and writev.c Do not run it by itself. tmocon.c Client thread to tmoacc.c tpd.c Tests thread private data. udpsrv.c Tests UDP socket functions. ut_ttools.h unused file. version.c Extract and print library version data. vercheck.c Test PR_VersionCheck(). writev.c Tests gather-write on a socket. Requires tmoacc.c xnotify.c Tests cached monitors. yield.c Limited use y2k.c Test to verify NSPR's date functions as Y2K compliant. dll\Makefile makefile for mygetval.c, mysetval.c dll\mygetval.c Dynamic library test. See also dlltest.c dll\mysetval.c Dynamic library test. See also dlltest.c nspr-4.11/nspr/pr/tests/accept.c0000644000000000000000000003542312623070344014727 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1996 - Netscape Communications Corporation ** ** Name: accept.c ** ** Description: Run accept() sucessful connection tests. ** ** Modification History: ** 04-Jun-97 AGarcia - Reconvert test file to return a 0 for PASS and a 1 for FAIL ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 Revert to return code 0 and 1. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ #include "nspr.h" #include "prpriv.h" #include #include #include "plgetopt.h" #include "plerror.h" #define BASE_PORT 10000 #define CLIENT_DATA 128 #define ACCEPT_NORMAL 0x1 #define ACCEPT_FAST 0x2 #define ACCEPT_READ 0x3 #define ACCEPT_READ_FAST 0x4 #define ACCEPT_READ_FAST_CB 0x5 #define CLIENT_NORMAL 0x1 #define CLIENT_TIMEOUT_ACCEPT 0x2 #define CLIENT_TIMEOUT_SEND 0x3 #define SERVER_MAX_BIND_COUNT 100 #if defined(XP_OS2) || defined(SYMBIAN) #define TIMEOUTSECS 10 #else #define TIMEOUTSECS 2 #endif PRIntervalTime timeoutTime; static PRInt32 count = 1; static PRFileDesc *output; static PRNetAddr serverAddr; static PRThreadScope thread_scope = PR_LOCAL_THREAD; static PRInt32 clientCommand; static PRInt32 iterations; static PRStatus rv; static PRFileDesc *listenSock; static PRFileDesc *clientSock = NULL; static PRNetAddr listenAddr; static PRNetAddr clientAddr; static PRThread *clientThread; static PRNetAddr *raddr; static char buf[4096 + 2*sizeof(PRNetAddr) + 32]; static PRInt32 status; static PRInt32 bytesRead; PRIntn failed_already=0; PRIntn debug_mode; void Test_Assert(const char *msg, const char *file, PRIntn line) { failed_already=1; if (debug_mode) { PR_fprintf(output, "@%s:%d ", file, line); PR_fprintf(output, msg); } } /* Test_Assert */ #define TEST_ASSERT(expr) \ if (!(expr)) Test_Assert(#expr, __FILE__, __LINE__) #ifdef WINNT #define CALLBACK_MAGIC 0x12345678 void timeout_callback(void *magic) { TEST_ASSERT(magic == (void *)CALLBACK_MAGIC); if (debug_mode) PR_fprintf(output, "timeout callback called okay\n"); } #endif static void PR_CALLBACK ClientThread(void *_action) { PRInt32 action = * (PRInt32 *) _action; PRInt32 iterations = count; PRFileDesc *sock = NULL; serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = listenAddr.inet.port; serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); for (; iterations--;) { PRInt32 rv; char buf[CLIENT_DATA]; memset(buf, 0xaf, sizeof(buf)); /* initialize with arbitrary data */ sock = PR_NewTCPSocket(); if (!sock) { if (!debug_mode) failed_already=1; else PR_fprintf(output, "client: unable to create socket\n"); return; } if (action != CLIENT_TIMEOUT_ACCEPT) { if ((rv = PR_Connect(sock, &serverAddr, timeoutTime)) < 0) { if (!debug_mode) failed_already=1; else PR_fprintf(output, "client: unable to connect to server (%ld, %ld, %ld, %ld)\n", iterations, rv, PR_GetError(), PR_GetOSError()); goto ErrorExit; } if (action != CLIENT_TIMEOUT_SEND) { if ((rv = PR_Send(sock, buf, CLIENT_DATA, 0, timeoutTime))< 0) { if (!debug_mode) failed_already=1; else PR_fprintf(output, "client: unable to send to server (%d, %ld, %ld)\n", CLIENT_DATA, rv, PR_GetError()); goto ErrorExit; } } else { PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1)); } } else { PR_Sleep(PR_SecondsToInterval(TIMEOUTSECS + 1)); } if (debug_mode) PR_fprintf(output, "."); PR_Close(sock); sock = NULL; } if (debug_mode) PR_fprintf(output, "\n"); ErrorExit: if (sock != NULL) PR_Close(sock); } static void RunTest(PRInt32 acceptType, PRInt32 clientAction) { int i; /* First bind to the socket */ listenSock = PR_NewTCPSocket(); if (!listenSock) { failed_already=1; if (debug_mode) PR_fprintf(output, "unable to create listen socket\n"); return; } memset(&listenAddr, 0 , sizeof(listenAddr)); listenAddr.inet.family = PR_AF_INET; listenAddr.inet.port = PR_htons(BASE_PORT); listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(listenSock, &listenAddr) == PR_FAILURE) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { listenAddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } failed_already=1; if (debug_mode) PR_fprintf(output,"accept: ERROR - PR_Bind failed\n"); return; } rv = PR_Listen(listenSock, 100); if (rv == PR_FAILURE) { failed_already=1; if (debug_mode) PR_fprintf(output, "unable to listen\n"); return; } clientCommand = clientAction; clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread, (void *)&clientCommand, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (!clientThread) { failed_already=1; if (debug_mode) PR_fprintf(output, "error creating client thread\n"); return; } iterations = count; for (;iterations--;) { switch (acceptType) { case ACCEPT_NORMAL: clientSock = PR_Accept(listenSock, &clientAddr, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: TEST_ASSERT(clientSock == 0); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; case ACCEPT_READ: status = PR_AcceptRead(listenSock, &clientSock, &raddr, buf, CLIENT_DATA, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: /* Invalid test case */ TEST_ASSERT(0); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); TEST_ASSERT(status == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(status == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; #ifdef WINNT case ACCEPT_FAST: clientSock = PR_NTFast_Accept(listenSock, &clientAddr, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: TEST_ASSERT(clientSock == 0); if (debug_mode) PR_fprintf(output, "PR_GetError is %ld\n", PR_GetError()); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(clientSock); bytesRead = PR_Recv(clientSock, buf, CLIENT_DATA, 0, timeoutTime); TEST_ASSERT(bytesRead == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; break; case ACCEPT_READ_FAST: status = PR_NTFast_AcceptRead(listenSock, &clientSock, &raddr, buf, 4096, timeoutTime); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: /* Invalid test case */ TEST_ASSERT(0); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); TEST_ASSERT(status == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: TEST_ASSERT(clientSock == NULL); TEST_ASSERT(status == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; case ACCEPT_READ_FAST_CB: status = PR_NTFast_AcceptRead_WithTimeoutCallback( listenSock, &clientSock, &raddr, buf, 4096, timeoutTime, timeout_callback, (void *)CALLBACK_MAGIC); switch(clientAction) { case CLIENT_TIMEOUT_ACCEPT: /* Invalid test case */ TEST_ASSERT(0); break; case CLIENT_NORMAL: TEST_ASSERT(clientSock); TEST_ASSERT(status == CLIENT_DATA); break; case CLIENT_TIMEOUT_SEND: if (debug_mode) PR_fprintf(output, "clientSock = 0x%8.8lx\n", clientSock); TEST_ASSERT(clientSock == NULL); TEST_ASSERT(status == -1); TEST_ASSERT(PR_GetError() == PR_IO_TIMEOUT_ERROR); break; } break; #endif } if (clientSock != NULL) { PR_Close(clientSock); clientSock = NULL; } } PR_Close(listenSock); PR_JoinThread(clientThread); } void AcceptUpdatedTest(void) { RunTest(ACCEPT_NORMAL, CLIENT_NORMAL); } void AcceptNotUpdatedTest(void) { RunTest(ACCEPT_FAST, CLIENT_NORMAL); } void AcceptReadTest(void) { RunTest(ACCEPT_READ, CLIENT_NORMAL); } void AcceptReadNotUpdatedTest(void) { RunTest(ACCEPT_READ_FAST, CLIENT_NORMAL); } void AcceptReadCallbackTest(void) { RunTest(ACCEPT_READ_FAST_CB, CLIENT_NORMAL); } void TimeoutAcceptUpdatedTest(void) { RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_ACCEPT); } void TimeoutAcceptNotUpdatedTest(void) { RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_ACCEPT); } void TimeoutAcceptReadCallbackTest(void) { RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_ACCEPT); } void TimeoutReadUpdatedTest(void) { RunTest(ACCEPT_NORMAL, CLIENT_TIMEOUT_SEND); } void TimeoutReadNotUpdatedTest(void) { RunTest(ACCEPT_FAST, CLIENT_TIMEOUT_SEND); } void TimeoutReadReadTest(void) { RunTest(ACCEPT_READ, CLIENT_TIMEOUT_SEND); } void TimeoutReadReadNotUpdatedTest(void) { RunTest(ACCEPT_READ_FAST, CLIENT_TIMEOUT_SEND); } void TimeoutReadReadCallbackTest(void) { RunTest(ACCEPT_READ_FAST_CB, CLIENT_TIMEOUT_SEND); } /************************************************************************/ static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) PR_fprintf(output, "%40s: %6.2f usec\n", msg, d / count); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name [-d] [-c n] */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "Gdc:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'd': /* debug mode */ debug_mode = 1; break; case 'c': /* loop counter */ count = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); output = PR_STDERR; PR_STDIO_INIT(); timeoutTime = PR_SecondsToInterval(TIMEOUTSECS); if (debug_mode) PR_fprintf(output, "\nRun accept() sucessful connection tests\n"); Measure(AcceptUpdatedTest, "PR_Accept()"); Measure(AcceptReadTest, "PR_AcceptRead()"); #ifdef WINNT Measure(AcceptNotUpdatedTest, "PR_NTFast_Accept()"); Measure(AcceptReadNotUpdatedTest, "PR_NTFast_AcceptRead()"); Measure(AcceptReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()"); #endif if (debug_mode) PR_fprintf(output, "\nRun accept() timeout in the accept tests\n"); #ifdef WINNT Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()"); #endif Measure(TimeoutReadUpdatedTest, "PR_Accept()"); if (debug_mode) PR_fprintf(output, "\nRun accept() timeout in the read tests\n"); Measure(TimeoutReadReadTest, "PR_AcceptRead()"); #ifdef WINNT Measure(TimeoutReadNotUpdatedTest, "PR_NTFast_Accept()"); Measure(TimeoutReadReadNotUpdatedTest, "PR_NTFast_AcceptRead()"); Measure(TimeoutReadReadCallbackTest, "PR_NTFast_AcceptRead_WithTimeoutCallback()"); #endif PR_fprintf(output, "%s\n", (failed_already) ? "FAIL" : "PASS"); return failed_already; } nspr-4.11/nspr/pr/tests/acceptread.c0000644000000000000000000001651512623070344015564 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #define DEFAULT_PORT 12273 #define GET "GET / HTTP/1.0\n\n" static PRFileDesc *std_out, *err_out; static PRIntervalTime write_dally, accept_timeout; static PRStatus PrintAddress(const PRNetAddr* address) { char buffer[100]; PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer)); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString"); else PR_fprintf( std_out, "Accepted connection from (0x%p)%s:%d\n", address, buffer, address->inet.port); return rv; } /* PrintAddress */ static void ConnectingThread(void *arg) { PRInt32 nbytes; #ifdef SYMBIAN char buf[256]; #else char buf[1024]; #endif PRFileDesc *sock; PRNetAddr peer_addr, *addr; addr = (PRNetAddr*)arg; sock = PR_NewTCPSocket(); if (sock == NULL) { PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed"); PR_ProcessExit(1); } if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { PL_FPrintError(err_out, "PR_Connect (client) failed"); PR_ProcessExit(1); } if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE) { PL_FPrintError(err_out, "PR_GetPeerName (client) failed"); PR_ProcessExit(1); } /* ** Then wait between the connection coming up and sending the expected ** data. At some point in time, the server should fail due to a timeou ** on the AcceptRead() operation, which according to the document is ** only due to the read() portion. */ PR_Sleep(write_dally); nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT); if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed"); nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed"); else { PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes); buf[sizeof(buf) - 1] = '\0'; PR_fprintf(std_out, "%s\n", buf); } if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH)) PL_FPrintError(err_out, "PR_Shutdown (client) failed"); if (PR_FAILURE == PR_Close(sock)) PL_FPrintError(err_out, "PR_Close (client) failed"); return; } /* ConnectingThread */ #define BUF_SIZE 117 static void AcceptingThread(void *arg) { PRStatus rv; PRInt32 bytes; PRSize buf_size = BUF_SIZE; PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32]; PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg; PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket(); PRSocketOptionData sock_opt; if (NULL == listen_sock) { PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed"); PR_ProcessExit(1); } sock_opt.option = PR_SockOpt_Reuseaddr; sock_opt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(listen_sock, &sock_opt); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_SetSocketOption (server) failed"); PR_ProcessExit(1); } rv = PR_Bind(listen_sock, listen_addr); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_Bind (server) failed"); PR_ProcessExit(1); } rv = PR_Listen(listen_sock, 10); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_Listen (server) failed"); PR_ProcessExit(1); } bytes = PR_AcceptRead( listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout); if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed"); else { PrintAddress(accept_addr); PR_fprintf( std_out, "(Server) read [0x%p..0x%p) %s\n", buf, &buf[BUF_SIZE], buf); bytes = PR_Write(accept_sock, buf, bytes); rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Shutdown (server) failed"); } if (-1 != bytes) { rv = PR_Close(accept_sock); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Close (server) failed"); } rv = PR_Close(listen_sock); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Close (server) failed"); } /* AcceptingThread */ int main(int argc, char **argv) { PRHostEnt he; PRStatus status; PRIntn next_index; PRUint16 port_number; char netdb_buf[PR_NETDB_BUF_SIZE]; PRNetAddr client_addr, server_addr; PRThread *client_thread, *server_thread; PRIntervalTime delta = PR_MillisecondsToInterval(500); err_out = PR_STDERR; std_out = PR_STDOUT; accept_timeout = PR_SecondsToInterval(2); if (argc != 2 && argc != 3) port_number = DEFAULT_PORT; else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]); status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr); if (PR_SUCCESS != status) { PL_FPrintError(err_out, "PR_InitializeNetAddr failed"); PR_ProcessExit(1); } if (argc < 3) { status = PR_InitializeNetAddr( PR_IpAddrLoopback, port_number, &client_addr); if (PR_SUCCESS != status) { PL_FPrintError(err_out, "PR_InitializeNetAddr failed"); PR_ProcessExit(1); } } else { status = PR_GetHostByName( argv[1], netdb_buf, sizeof(netdb_buf), &he); if (status == PR_FAILURE) { PL_FPrintError(err_out, "PR_GetHostByName failed"); PR_ProcessExit(1); } next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr); if (next_index == -1) { PL_FPrintError(err_out, "PR_EnumerateHostEnt failed"); PR_ProcessExit(1); } } for ( write_dally = 0; write_dally < accept_timeout + (2 * delta); write_dally += delta) { PR_fprintf( std_out, "Testing w/ write_dally = %d msec\n", PR_IntervalToMilliseconds(write_dally)); server_thread = PR_CreateThread( PR_USER_THREAD, AcceptingThread, &server_addr, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (server_thread == NULL) { PL_FPrintError(err_out, "PR_CreateThread (server) failed"); PR_ProcessExit(1); } PR_Sleep(delta); /* let the server pot thicken */ client_thread = PR_CreateThread( PR_USER_THREAD, ConnectingThread, &client_addr, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (client_thread == NULL) { PL_FPrintError(err_out, "PR_CreateThread (client) failed"); PR_ProcessExit(1); } if (PR_JoinThread(client_thread) == PR_FAILURE) PL_FPrintError(err_out, "PR_JoinThread (client) failed"); if (PR_JoinThread(server_thread) == PR_FAILURE) PL_FPrintError(err_out, "PR_JoinThread (server) failed"); } return 0; } nspr-4.11/nspr/pr/tests/acceptreademu.c0000644000000000000000000002063312623070344016267 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This test is the same as acceptread.c except that it uses the * emulated acceptread method instead of the regular acceptread. */ #include #include #include #include #include #include #include #include #include #define DEFAULT_PORT 12273 #define GET "GET / HTTP/1.0\n\n" static PRFileDesc *std_out, *err_out; static PRIntervalTime write_dally, accept_timeout; static PRDescIdentity emu_layer_ident; static PRIOMethods emu_layer_methods; /* the acceptread method in emu_layer_methods */ static PRInt32 PR_CALLBACK emu_AcceptRead(PRFileDesc *sd, PRFileDesc **nd, PRNetAddr **raddr, void *buf, PRInt32 amount, PRIntervalTime timeout) { return PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout); } static PRStatus PrintAddress(const PRNetAddr* address) { char buffer[100]; PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer)); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_NetAddrToString"); else PR_fprintf( std_out, "Accepted connection from (0x%p)%s:%d\n", address, buffer, address->inet.port); return rv; } /* PrintAddress */ static void ConnectingThread(void *arg) { PRInt32 nbytes; #ifdef SYMBIAN char buf[256]; #else char buf[1024]; #endif PRFileDesc *sock; PRNetAddr peer_addr, *addr; addr = (PRNetAddr*)arg; sock = PR_NewTCPSocket(); if (sock == NULL) { PL_FPrintError(err_out, "PR_NewTCPSocket (client) failed"); PR_ProcessExit(1); } if (PR_Connect(sock, addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { PL_FPrintError(err_out, "PR_Connect (client) failed"); PR_ProcessExit(1); } if (PR_GetPeerName(sock, &peer_addr) == PR_FAILURE) { PL_FPrintError(err_out, "PR_GetPeerName (client) failed"); PR_ProcessExit(1); } /* ** Then wait between the connection coming up and sending the expected ** data. At some point in time, the server should fail due to a timeou ** on the AcceptRead() operation, which according to the document is ** only due to the read() portion. */ PR_Sleep(write_dally); nbytes = PR_Send(sock, GET, sizeof(GET), 0, PR_INTERVAL_NO_TIMEOUT); if (nbytes == -1) PL_FPrintError(err_out, "PR_Send (client) failed"); nbytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (nbytes == -1) PL_FPrintError(err_out, "PR_Recv (client) failed"); else { PR_fprintf(std_out, "PR_Recv (client) succeeded: %d bytes\n", nbytes); buf[sizeof(buf) - 1] = '\0'; PR_fprintf(std_out, "%s\n", buf); } if (PR_FAILURE == PR_Shutdown(sock, PR_SHUTDOWN_BOTH)) PL_FPrintError(err_out, "PR_Shutdown (client) failed"); if (PR_FAILURE == PR_Close(sock)) PL_FPrintError(err_out, "PR_Close (client) failed"); return; } /* ConnectingThread */ #define BUF_SIZE 117 static void AcceptingThread(void *arg) { PRStatus rv; PRInt32 bytes; PRSize buf_size = BUF_SIZE; PRUint8 buf[BUF_SIZE + (2 * sizeof(PRNetAddr)) + 32]; PRNetAddr *accept_addr, *listen_addr = (PRNetAddr*)arg; PRFileDesc *accept_sock, *listen_sock = PR_NewTCPSocket(); PRFileDesc *layer; PRSocketOptionData sock_opt; if (NULL == listen_sock) { PL_FPrintError(err_out, "PR_NewTCPSocket (server) failed"); PR_ProcessExit(1); } layer = PR_CreateIOLayerStub(emu_layer_ident, &emu_layer_methods); if (NULL == layer) { PL_FPrintError(err_out, "PR_CreateIOLayerStub (server) failed"); PR_ProcessExit(1); } if (PR_PushIOLayer(listen_sock, PR_TOP_IO_LAYER, layer) == PR_FAILURE) { PL_FPrintError(err_out, "PR_PushIOLayer (server) failed"); PR_ProcessExit(1); } sock_opt.option = PR_SockOpt_Reuseaddr; sock_opt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(listen_sock, &sock_opt); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_SetSocketOption (server) failed"); PR_ProcessExit(1); } rv = PR_Bind(listen_sock, listen_addr); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_Bind (server) failed"); PR_ProcessExit(1); } rv = PR_Listen(listen_sock, 10); if (PR_FAILURE == rv) { PL_FPrintError(err_out, "PR_Listen (server) failed"); PR_ProcessExit(1); } bytes = PR_AcceptRead( listen_sock, &accept_sock, &accept_addr, buf, buf_size, accept_timeout); if (-1 == bytes) PL_FPrintError(err_out, "PR_AcceptRead (server) failed"); else { PrintAddress(accept_addr); PR_fprintf( std_out, "(Server) read [0x%p..0x%p) %s\n", buf, &buf[BUF_SIZE], buf); bytes = PR_Write(accept_sock, buf, bytes); rv = PR_Shutdown(accept_sock, PR_SHUTDOWN_BOTH); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Shutdown (server) failed"); } if (-1 != bytes) { rv = PR_Close(accept_sock); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Close (server) failed"); } rv = PR_Close(listen_sock); if (PR_FAILURE == rv) PL_FPrintError(err_out, "PR_Close (server) failed"); } /* AcceptingThread */ int main(int argc, char **argv) { PRHostEnt he; PRStatus status; PRIntn next_index; PRUint16 port_number; char netdb_buf[PR_NETDB_BUF_SIZE]; PRNetAddr client_addr, server_addr; PRThread *client_thread, *server_thread; PRIntervalTime delta = PR_MillisecondsToInterval(500); err_out = PR_STDERR; std_out = PR_STDOUT; accept_timeout = PR_SecondsToInterval(2); emu_layer_ident = PR_GetUniqueIdentity("Emulated AcceptRead"); emu_layer_methods = *PR_GetDefaultIOMethods(); emu_layer_methods.acceptread = emu_AcceptRead; if (argc != 2 && argc != 3) port_number = DEFAULT_PORT; else port_number = (PRUint16)atoi(argv[(argc == 2) ? 1 : 2]); status = PR_InitializeNetAddr(PR_IpAddrAny, port_number, &server_addr); if (PR_SUCCESS != status) { PL_FPrintError(err_out, "PR_InitializeNetAddr failed"); PR_ProcessExit(1); } if (argc < 3) { status = PR_InitializeNetAddr( PR_IpAddrLoopback, port_number, &client_addr); if (PR_SUCCESS != status) { PL_FPrintError(err_out, "PR_InitializeNetAddr failed"); PR_ProcessExit(1); } } else { status = PR_GetHostByName( argv[1], netdb_buf, sizeof(netdb_buf), &he); if (status == PR_FAILURE) { PL_FPrintError(err_out, "PR_GetHostByName failed"); PR_ProcessExit(1); } next_index = PR_EnumerateHostEnt(0, &he, port_number, &client_addr); if (next_index == -1) { PL_FPrintError(err_out, "PR_EnumerateHostEnt failed"); PR_ProcessExit(1); } } for ( write_dally = 0; write_dally < accept_timeout + (2 * delta); write_dally += delta) { PR_fprintf( std_out, "Testing w/ write_dally = %d msec\n", PR_IntervalToMilliseconds(write_dally)); server_thread = PR_CreateThread( PR_USER_THREAD, AcceptingThread, &server_addr, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (server_thread == NULL) { PL_FPrintError(err_out, "PR_CreateThread (server) failed"); PR_ProcessExit(1); } PR_Sleep(delta); /* let the server pot thicken */ client_thread = PR_CreateThread( PR_USER_THREAD, ConnectingThread, &client_addr, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (client_thread == NULL) { PL_FPrintError(err_out, "PR_CreateThread (client) failed"); PR_ProcessExit(1); } if (PR_JoinThread(client_thread) == PR_FAILURE) PL_FPrintError(err_out, "PR_JoinThread (client) failed"); if (PR_JoinThread(server_thread) == PR_FAILURE) PL_FPrintError(err_out, "PR_JoinThread (server) failed"); } return 0; } nspr-4.11/nspr/pr/tests/addrstr.c0000644000000000000000000000425312623070344015130 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prnetdb.h" #include #include #include const char *testaddrs[] = { "::", "::", "::1", "::1", "::ffff", "::ffff", "::1:0", "::0.1.0.0", "::127.0.0.1", "::127.0.0.1", "::FFFF:127.0.0.1", "::ffff:127.0.0.1", "::FFFE:9504:3501", "::fffe:9504:3501", "0:0:1:0:35c:0:0:0", "0:0:1:0:35c::", "0:0:3f4c:0:0:4552:0:0", "::3f4c:0:0:4552:0:0", "0:0:1245:0:0:0:0567:0", "0:0:1245::567:0", "0:1:2:3:4:5:6:7", "0:1:2:3:4:5:6:7", "1:2:3:0:4:5:6:7", "1:2:3:0:4:5:6:7", "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:0", "1:2:3:4:5:6:7:8", "1:2:3:4:5:6:7:8", "1:2:3:4:5:6::7", "1:2:3:4:5:6:0:7", 0 }; const char *badaddrs[] = { "::.1.2.3", "ffff::.1.2.3", "1:2:3:4:5:6:7::8", "1:2:3:4:5:6::7:8", "::ff99.2.3.4", 0 }; int failed_already = 0; int main(int argc, char **argv) { const char **nexttestaddr = testaddrs; const char **nextbadaddr = badaddrs; const char *in, *expected_out; PRNetAddr addr; char buf[256]; PRStatus rv; while ((in = *nexttestaddr++) != 0) { expected_out = *nexttestaddr++; rv = PR_StringToNetAddr(in, &addr); if (rv) { printf("cannot convert %s to addr: %d\n", in, rv); failed_already = 1; continue; } rv = PR_NetAddrToString(&addr, buf, sizeof(buf)); if (rv) { printf("cannot convert %s back to string: %d\n", in, rv); failed_already = 1; continue; } if (strcmp(buf, expected_out)) { /* This is not necessarily an error */ printf("%s expected %s got %s\n", in, expected_out, buf); } } while ((in = *nextbadaddr++) != 0) { if (PR_StringToNetAddr(in, &addr) == PR_SUCCESS) { printf("converted bad addr %s\n", in); failed_already = 1; } } if (failed_already) { printf("FAIL\n"); return 1; } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/affinity.c0000644000000000000000000000365112623070344015277 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "pprthred.h" #include "plgetopt.h" #include #include #include #ifndef XP_BEOS /* * Test PR_GetThreadAffinityMask * The function is called by each of local, global and global bound threads * The test should be run on both single and multi-cpu systems */ static void PR_CALLBACK thread_start(void *arg) { PRUint32 mask = 0; if (PR_GetThreadAffinityMask(PR_GetCurrentThread(), &mask)) printf("\tthread_start: PR_GetCurrentThreadAffinityMask failed\n"); else printf("\tthread_start: AffinityMask = 0x%x\n",mask); } int main(int argc, char **argv) { PRThread *t; printf("main: creating local thread\n"); t = PR_CreateThread(PR_USER_THREAD, thread_start, 0, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == t) { printf("main: cannot create local thread\n"); exit(1); } PR_JoinThread(t); printf("main: creating global thread\n"); t = PR_CreateThread(PR_USER_THREAD, thread_start, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == t) { printf("main: cannot create global thread\n"); exit(1); } PR_JoinThread(t); printf("main: creating global bound thread\n"); t = PR_CreateThread(PR_USER_THREAD, thread_start, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == t) { printf("main: cannot create global bound thread\n"); exit(1); } PR_JoinThread(t); return 0; } #else /* !XP_BEOS */ int main() { printf( "This test is not supported on the BeOS\n" ); return 0; } #endif /* !XP_BEOS */ nspr-4.11/nspr/pr/tests/alarm.c0000644000000000000000000003202112623070344014553 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1996 - Netscape Communications Corporation ** ** Name: alarmtst.c ** ** Description: Test alarms ** ** Modification History: ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ #include "prlog.h" #include "prinit.h" #include "obsolete/pralarm.h" #include "prlock.h" #include "prlong.h" #include "prcvar.h" #include "prinrval.h" #include "prtime.h" /* Used to get the command line option */ #include "plgetopt.h" #include #include #if defined(XP_UNIX) #include #endif static PRIntn debug_mode; static PRIntn failed_already=0; static PRThreadScope thread_scope = PR_LOCAL_THREAD; typedef struct notifyData { PRLock *ml; PRCondVar *child; PRCondVar *parent; PRBool pending; PRUint32 counter; } NotifyData; static void Notifier(void *arg) { NotifyData *notifyData = (NotifyData*)arg; PR_Lock(notifyData->ml); while (notifyData->counter > 0) { while (!notifyData->pending) PR_WaitCondVar(notifyData->child, PR_INTERVAL_NO_TIMEOUT); notifyData->counter -= 1; notifyData->pending = PR_FALSE; PR_NotifyCondVar(notifyData->parent); } PR_Unlock(notifyData->ml); } /* Notifier */ /*********************************************************************** ** PRIVATE FUNCTION: ConditionNotify ** DESCRIPTION: ** ** INPUTS: loops ** OUTPUTS: None ** RETURN: overhead ** SIDE EFFECTS: ** ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: ** ***********************************************************************/ static PRIntervalTime ConditionNotify(PRUint32 loops) { PRThread *thread; NotifyData notifyData; PRIntervalTime timein, overhead; timein = PR_IntervalNow(); notifyData.counter = loops; notifyData.ml = PR_NewLock(); notifyData.child = PR_NewCondVar(notifyData.ml); notifyData.parent = PR_NewCondVar(notifyData.ml); thread = PR_CreateThread( PR_USER_THREAD, Notifier, ¬ifyData, PR_GetThreadPriority(PR_GetCurrentThread()), thread_scope, PR_JOINABLE_THREAD, 0); overhead = PR_IntervalNow() - timein; /* elapsed so far */ PR_Lock(notifyData.ml); while (notifyData.counter > 0) { notifyData.pending = PR_TRUE; PR_NotifyCondVar(notifyData.child); while (notifyData.pending) PR_WaitCondVar(notifyData.parent, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(notifyData.ml); timein = PR_IntervalNow(); (void)PR_JoinThread(thread); PR_DestroyCondVar(notifyData.child); PR_DestroyCondVar(notifyData.parent); PR_DestroyLock(notifyData.ml); overhead += (PR_IntervalNow() - timein); /* more overhead */ return overhead; } /* ConditionNotify */ static PRIntervalTime ConditionTimeout(PRUint32 loops) { PRUintn count; PRIntervalTime overhead, timein = PR_IntervalNow(); PRLock *ml = PR_NewLock(); PRCondVar *cv = PR_NewCondVar(ml); PRIntervalTime interval = PR_MillisecondsToInterval(50); overhead = PR_IntervalNow() - timein; PR_Lock(ml); for (count = 0; count < loops; ++count) { overhead += interval; PR_ASSERT(PR_WaitCondVar(cv, interval) == PR_SUCCESS); } PR_Unlock(ml); timein = PR_IntervalNow(); PR_DestroyCondVar(cv); PR_DestroyLock(ml); overhead += (PR_IntervalNow() - timein); return overhead; } /* ConditionTimeout */ typedef struct AlarmData { PRLock *ml; PRCondVar *cv; PRUint32 rate, late, times; PRIntervalTime duration, timein, period; } AlarmData; static PRBool AlarmFn1(PRAlarmID *id, void *clientData, PRUint32 late) { PRStatus rv = PR_SUCCESS; PRBool keepGoing, resetAlarm; PRIntervalTime interval, now = PR_IntervalNow(); AlarmData *ad = (AlarmData*)clientData; PR_Lock(ad->ml); ad->late += late; ad->times += 1; keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ? PR_TRUE : PR_FALSE; if (!keepGoing) rv = PR_NotifyCondVar(ad->cv); resetAlarm = ((ad->times % 31) == 0) ? PR_TRUE : PR_FALSE; interval = (ad->period + ad->rate - 1) / ad->rate; if (!late && (interval > 10)) { interval &= (now & 0x03) + 1; PR_WaitCondVar(ad->cv, interval); } PR_Unlock(ad->ml); if (rv != PR_SUCCESS) { if (!debug_mode) failed_already=1; else printf("AlarmFn: notify status: FAIL\n"); } if (resetAlarm) { ad->rate += 3; ad->late = ad->times = 0; if (PR_ResetAlarm(id, ad->period, ad->rate) != PR_SUCCESS) { if (!debug_mode) failed_already=1; else printf("AlarmFn: Resetting alarm status: FAIL\n"); keepGoing = PR_FALSE; } } return keepGoing; } /* AlarmFn1 */ static PRIntervalTime Alarms1(PRUint32 loops) { PRAlarm *alarm; AlarmData ad; PRIntervalTime overhead, timein = PR_IntervalNow(); PRIntervalTime duration = PR_SecondsToInterval(3); PRLock *ml = PR_NewLock(); PRCondVar *cv = PR_NewCondVar(ml); ad.ml = ml; ad.cv = cv; ad.rate = 1; ad.times = loops; ad.late = ad.times = 0; ad.duration = duration; ad.timein = PR_IntervalNow(); ad.period = PR_SecondsToInterval(1); alarm = PR_CreateAlarm(); (void)PR_SetAlarm( alarm, ad.period, ad.rate, AlarmFn1, &ad); overhead = PR_IntervalNow() - timein; PR_Lock(ml); while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration) PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(ml); timein = PR_IntervalNow(); (void)PR_DestroyAlarm(alarm); PR_DestroyCondVar(cv); PR_DestroyLock(ml); overhead += (PR_IntervalNow() - timein); return duration + overhead; } /* Alarms1 */ static PRBool AlarmFn2(PRAlarmID *id, void *clientData, PRUint32 late) { PRBool keepGoing; PRStatus rv = PR_SUCCESS; AlarmData *ad = (AlarmData*)clientData; PRIntervalTime interval, now = PR_IntervalNow(); PR_Lock(ad->ml); ad->times += 1; keepGoing = ((PRIntervalTime)(now - ad->timein) < ad->duration) ? PR_TRUE : PR_FALSE; interval = (ad->period + ad->rate - 1) / ad->rate; if (!late && (interval > 10)) { interval &= (now & 0x03) + 1; PR_WaitCondVar(ad->cv, interval); } if (!keepGoing) rv = PR_NotifyCondVar(ad->cv); PR_Unlock(ad->ml); if (rv != PR_SUCCESS) failed_already=1;; return keepGoing; } /* AlarmFn2 */ static PRIntervalTime Alarms2(PRUint32 loops) { PRStatus rv; PRAlarm *alarm; PRIntervalTime overhead, timein = PR_IntervalNow(); AlarmData ad; PRIntervalTime duration = PR_SecondsToInterval(30); PRLock *ml = PR_NewLock(); PRCondVar *cv = PR_NewCondVar(ml); ad.ml = ml; ad.cv = cv; ad.rate = 1; ad.times = loops; ad.late = ad.times = 0; ad.duration = duration; ad.timein = PR_IntervalNow(); ad.period = PR_SecondsToInterval(1); alarm = PR_CreateAlarm(); (void)PR_SetAlarm( alarm, ad.period, ad.rate, AlarmFn2, &ad); overhead = PR_IntervalNow() - timein; PR_Lock(ml); while ((PRIntervalTime)(PR_IntervalNow() - ad.timein) < duration) PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(ml); timein = PR_IntervalNow(); rv = PR_DestroyAlarm(alarm); if (rv != PR_SUCCESS) { if (!debug_mode) failed_already=1; else printf("***Destroying alarm status: FAIL\n"); } PR_DestroyCondVar(cv); PR_DestroyLock(ml); overhead += (PR_IntervalNow() - timein); return duration + overhead; } /* Alarms2 */ static PRIntervalTime Alarms3(PRUint32 loops) { PRIntn i; PRStatus rv; PRAlarm *alarm; AlarmData ad[3]; PRIntervalTime duration = PR_SecondsToInterval(30); PRIntervalTime overhead, timein = PR_IntervalNow(); PRLock *ml = PR_NewLock(); PRCondVar *cv = PR_NewCondVar(ml); for (i = 0; i < 3; ++i) { ad[i].ml = ml; ad[i].cv = cv; ad[i].rate = 1; ad[i].times = loops; ad[i].duration = duration; ad[i].late = ad[i].times = 0; ad[i].timein = PR_IntervalNow(); ad[i].period = PR_SecondsToInterval(1); /* more loops, faster rate => same elapsed time */ ad[i].times = (i + 1) * loops; ad[i].rate = (i + 1) * 10; } alarm = PR_CreateAlarm(); for (i = 0; i < 3; ++i) { (void)PR_SetAlarm( alarm, ad[i].period, ad[i].rate, AlarmFn2, &ad[i]); } overhead = PR_IntervalNow() - timein; PR_Lock(ml); for (i = 0; i < 3; ++i) { while ((PRIntervalTime)(PR_IntervalNow() - ad[i].timein) < duration) PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(ml); timein = PR_IntervalNow(); if (debug_mode) printf ("Alarms3 finished at %u, %u, %u\n", ad[0].timein, ad[1].timein, ad[2].timein); rv = PR_DestroyAlarm(alarm); if (rv != PR_SUCCESS) { if (!debug_mode) failed_already=1; else printf("***Destroying alarm status: FAIL\n"); } PR_DestroyCondVar(cv); PR_DestroyLock(ml); overhead += (duration / 3); overhead += (PR_IntervalNow() - timein); return overhead; } /* Alarms3 */ static PRUint32 TimeThis( const char *msg, PRUint32 (*func)(PRUint32 loops), PRUint32 loops) { PRUint32 overhead, usecs; PRIntervalTime predicted, timein, timeout, ticks; if (debug_mode) printf("Testing %s ...", msg); timein = PR_IntervalNow(); predicted = func(loops); timeout = PR_IntervalNow(); if (debug_mode) printf(" done\n"); ticks = timeout - timein; usecs = PR_IntervalToMicroseconds(ticks); overhead = PR_IntervalToMicroseconds(predicted); if(ticks < predicted) { if (debug_mode) { printf("\tFinished in negative time\n"); printf("\tpredicted overhead was %d usecs\n", overhead); printf("\ttest completed in %d usecs\n\n", usecs); } } else { if (debug_mode) printf( "\ttotal: %d usecs\n\toverhead: %d usecs\n\tcost: %6.3f usecs\n\n", usecs, overhead, ((double)(usecs - overhead) / (double)loops)); } return overhead; } /* TimeThis */ int prmain(int argc, char** argv) { PRUint32 cpu, cpus = 0, loops = 0; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name [-d] */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:c:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* GLOBAL threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'd': /* debug mode */ debug_mode = 1; break; case 'l': /* loop count */ loops = atoi(opt->value); break; case 'c': /* concurrency limit */ cpus = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (cpus == 0) cpus = 1; if (loops == 0) loops = 4; if (debug_mode) printf("Alarm: Using %d loops\n", loops); if (debug_mode) printf("Alarm: Using %d cpu(s)\n", cpus); for (cpu = 1; cpu <= cpus; ++cpu) { if (debug_mode) printf("\nAlarm: Using %d CPU(s)\n", cpu); PR_SetConcurrency(cpu); /* some basic time test */ (void)TimeThis("ConditionNotify", ConditionNotify, loops); (void)TimeThis("ConditionTimeout", ConditionTimeout, loops); (void)TimeThis("Alarms1", Alarms1, loops); (void)TimeThis("Alarms2", Alarms2, loops); (void)TimeThis("Alarms3", Alarms3, loops); } return 0; } int main(int argc, char** argv) { PR_Initialize(prmain, argc, argv, 0); PR_STDIO_INIT(); if (failed_already) return 1; else return 0; } /* main */ /* alarmtst.c */ nspr-4.11/nspr/pr/tests/anonfm.c0000644000000000000000000001757112623070344014752 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: anonfm.c ** Description: Test anonymous file map ** ** Synopsis: anonfm [options] [dirName] ** ** Options: ** -d enable debug mode ** -h display a help message ** -s size of the anonymous memory map, in KBytes. default: 100KBytes. ** -C 1 Operate this process as ClientOne() ** -C 2 Operate this process as ClientTwo() ** ** anonfn.c contains two tests, corresponding to the two protocols for ** passing an anonymous file map to a child process. ** ** ServerOne()/ClientOne() tests the passing of "raw" file map; it uses ** PR_CreateProcess() [for portability of the test case] to create the ** child process, but does not use the PRProcessAttr structure for ** passing the file map data. ** ** ServerTwo()/ClientTwo() tests the passing of the file map using the ** PRProcessAttr structure. ** */ #include #include #include #include #include #include /* ** Test harness infrastructure */ PRLogModuleInfo *lm; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRUint32 failed_already = 0; PRIntn debug = 0; PRIntn client = 0; /* invoke client, style */ char dirName[512] = "."; /* directory name to contain anon mapped file */ PRSize fmSize = (100 * 1024 ); PRUint32 fmMode = 0600; PRFileMapProtect fmProt = PR_PROT_READWRITE; const char *fmEnvName = "nsprFileMapEnvVariable"; /* ** Emit help text for this test */ static void Help( void ) { printf("anonfm [options] [dirName]\n"); printf("-d -- enable debug mode\n"); printf("dirName is alternate directory name. Default: . (current directory)\n"); exit(1); } /* end Help() */ /* ** ClientOne() -- */ static void ClientOne( void ) { PRFileMap *fm; char *fmString; char *addr; PRStatus rc; PR_LOG(lm, msgLevel, ("ClientOne() starting")); fmString = PR_GetEnv( fmEnvName ); if ( NULL == fmString ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv() failed")); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_Getenv(): found: %s", fmString)); fm = PR_ImportFileMapFromString( fmString ); if ( NULL == fm ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_ImportFileMapFromString() failed")); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_ImportFileMapFromString(): fm: %p", fm )); addr = PR_MemMap( fm, LL_ZERO, fmSize ); if ( NULL == addr ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemMap() failed, OSError: %d", PR_GetOSError() )); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemMap(): addr: %p", addr )); /* write to memory map to release server */ *addr = 1; rc = PR_MemUnmap( addr, fmSize ); PR_ASSERT( rc == PR_SUCCESS ); PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemUnap(): success" )); rc = PR_CloseFileMap( fm ); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("ClientOne(): PR_MemUnap() failed, OSError: %d", PR_GetOSError() )); return; } PR_LOG(lm, msgLevel, ("ClientOne(): PR_CloseFileMap(): success" )); return; } /* end ClientOne() */ /* ** ClientTwo() -- */ static void ClientTwo( void ) { failed_already = 1; } /* end ClientTwo() */ /* ** ServerOne() -- */ static void ServerOne( void ) { PRFileMap *fm; PRStatus rc; PRIntn i; char *addr; char fmString[256]; char envBuf[256]; char *child_argv[8]; PRProcess *proc; PRInt32 exit_status; PR_LOG(lm, msgLevel, ("ServerOne() starting")); fm = PR_OpenAnonFileMap( dirName, fmSize, fmProt ); if ( NULL == fm ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_OpenAnonFileMap() failed")); return; } PR_LOG(lm, msgLevel, ("ServerOne(): FileMap: %p", fm )); rc = PR_ExportFileMapAsString( fm, sizeof(fmString), fmString ); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_ExportFileMap() failed")); return; } /* ** put the string into the environment */ PR_snprintf( envBuf, sizeof(envBuf), "%s=%s", fmEnvName, fmString); putenv( envBuf ); addr = PR_MemMap( fm, LL_ZERO, fmSize ); if ( NULL == addr ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_MemMap() failed")); return; } /* set initial value for client */ for (i = 0; i < (PRIntn)fmSize ; i++ ) *(addr+i) = 0x00; PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemMap(): addr: %p", addr )); /* ** set arguments for child process */ child_argv[0] = "anonfm"; child_argv[1] = "-C"; child_argv[2] = "1"; child_argv[3] = NULL; proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); PR_ASSERT( proc ); PR_LOG(lm, msgLevel, ("ServerOne(): PR_CreateProcess(): proc: %x", proc )); /* ** ClientOne() will set the memory to 1 */ PR_LOG(lm, msgLevel, ("ServerOne(): waiting on Client, *addr: %x", *addr )); while( *addr == 0x00 ) { if ( debug ) fprintf(stderr, "."); PR_Sleep(PR_MillisecondsToInterval(300)); } if ( debug ) fprintf(stderr, "\n"); PR_LOG(lm, msgLevel, ("ServerOne(): Client responded" )); rc = PR_WaitProcess( proc, &exit_status ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_MemUnmap( addr, fmSize); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_MemUnmap() failed")); return; } PR_LOG(lm, msgLevel, ("ServerOne(): PR_MemUnmap(): success" )); rc = PR_CloseFileMap(fm); if ( PR_FAILURE == rc ) { failed_already = 1; PR_LOG(lm, msgLevel, ("PR_CloseFileMap() failed")); return; } PR_LOG(lm, msgLevel, ("ServerOne(): PR_CloseFileMap() success" )); return; } /* end ServerOne() */ /* ** ServerTwo() -- */ static void ServerTwo( void ) { PR_LOG(lm, msgLevel, ("ServerTwo(): Not implemented yet" )); } /* end ServerTwo() */ int main(int argc, char **argv) { { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hdC:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'C': /* Client style */ client = atol(opt->value); break; case 's': /* file size */ fmSize = atol( opt->value ) * 1024; break; case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_DEBUG; break; case 'h': /* help message */ Help(); break; default: strcpy(dirName, opt->value); break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ if ( client == 1 ) { ClientOne(); } else if ( client == 2 ) { ClientTwo(); } else { ServerOne(); if ( failed_already ) goto Finished; ServerTwo(); } Finished: if ( debug ) printf("%s\n", (failed_already)? "FAIL" : "PASS"); return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */ /* end anonfm.c */ nspr-4.11/nspr/pr/tests/append.c0000644000000000000000000001007212623070344014730 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: append.c ** Description: Testing File writes where PR_APPEND was used on open ** ** append attempts to verify that a file opened with PR_APPEND ** will always append to the end of file, regardless where the ** current file pointer is positioned. To do this, PR_Seek() is ** called before each write with the position set to beginning of ** file. Subsequent writes should always append. ** The file is read back, summing the integer data written to the ** file. If the expected result is equal, the test passes. ** ** See BugSplat: 4090 */ #include "plgetopt.h" #include "nspr.h" #include #include PRIntn debug = 0; PRIntn verbose = 0; PRBool failedAlready = PR_FALSE; const PRInt32 addedBytes = 1000; const PRInt32 buf = 1; /* constant written to fd, addedBytes times */ PRInt32 inBuf; /* read it back into here */ int main(int argc, char **argv) { PRStatus rc; PRInt32 rv; PRFileDesc *fd; PRIntn i; PRInt32 sum = 0; { /* Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "vd"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; break; case 'v': /* verbose */ verbose = 1; break; default: break; } } PL_DestroyOptState(opt); } /* end block "Get command line options" */ /* ---------------------------------------------------------------------- */ fd = PR_Open( "/tmp/nsprAppend", (PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE | PR_WRONLY), 0666 ); if ( NULL == fd ) { if (debug) printf("PR_Open() failed for writing: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } for ( i = 0; i < addedBytes ; i++ ) { rv = PR_Write( fd, &buf, sizeof(buf)); if ( sizeof(buf) != rv ) { if (debug) printf("PR_Write() failed: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } rv = PR_Seek( fd, 0 , PR_SEEK_SET ); if ( -1 == rv ) { if (debug) printf("PR_Seek() failed: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } } rc = PR_Close( fd ); if ( PR_FAILURE == rc ) { if (debug) printf("PR_Close() failed after writing: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } /* ---------------------------------------------------------------------- */ fd = PR_Open( "/tmp/nsprAppend", PR_RDONLY, 0 ); if ( NULL == fd ) { if (debug) printf("PR_Open() failed for reading: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } for ( i = 0; i < addedBytes ; i++ ) { rv = PR_Read( fd, &inBuf, sizeof(inBuf)); if ( sizeof(inBuf) != rv) { if (debug) printf("PR_Write() failed: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } sum += inBuf; } rc = PR_Close( fd ); if ( PR_FAILURE == rc ) { if (debug) printf("PR_Close() failed after reading: %d\n", PR_GetError()); failedAlready = PR_TRUE; goto Finished; } if ( sum != addedBytes ) { if (debug) printf("Uh Oh! addedBytes: %d. Sum: %d\n", addedBytes, sum); failedAlready = PR_TRUE; goto Finished; } /* ---------------------------------------------------------------------- */ Finished: if (debug || verbose) printf("%s\n", (failedAlready)? "FAILED" : "PASSED" ); return( (failedAlready)? 1 : 0 ); } /* main() */ /* append.c */ nspr-4.11/nspr/pr/tests/atomic.c0000644000000000000000000001421312623070344014736 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prprf.h" #include "pratom.h" /* * TODO: create a macro to generate the six lines of code that are repeated * for every test. Also rewrite the statement * result = result | ((EXPRESSION) ? 0 : 1); * as * result |= !(EXPRESSION); */ int main(int argc, char **argv) { PRInt32 rv, oldval, test, result = 0; PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput); /***********************/ /* Test the functions. */ /***********************/ oldval = test = -2; rv = PR_AtomicIncrement(&test); result = result | ((rv == -1) ? 0 : 1); PR_fprintf( output, "PR_AtomicIncrement(%d) == %d: %s\n", oldval, rv, (rv == -1) ? "PASSED" : "FAILED"); oldval = test; rv = PR_AtomicIncrement(&test); result = result | ((rv == 0) ? 0 : 1); PR_fprintf( output, "PR_AtomicIncrement(%d) == %d: %s\n", oldval, rv, (rv == 0) ? "PASSED" : "FAILED"); oldval = test; rv = PR_AtomicIncrement(&test); result = result | ((rv == 1) ? 0 : 1); PR_fprintf( output, "PR_AtomicIncrement(%d) == %d: %s\n", oldval, rv, (rv == 1) ? "PASSED" : "FAILED"); oldval = test = -2; rv = PR_AtomicAdd(&test,1); result = result | ((rv == -1) ? 0 : 1); PR_fprintf( output, "PR_AtomicAdd(%d,%d) == %d: %s\n", oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED"); oldval = test; rv = PR_AtomicAdd(&test, 4); result = result | ((rv == 3) ? 0 : 1); PR_fprintf( output, "PR_AtomicAdd(%d,%d) == %d: %s\n", oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED"); oldval = test; rv = PR_AtomicAdd(&test, -6); result = result | ((rv == -3) ? 0 : 1); PR_fprintf( output, "PR_AtomicAdd(%d,%d) == %d: %s\n", oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED"); oldval = test = 2; rv = PR_AtomicDecrement(&test); result = result | ((rv == 1) ? 0 : 1); PR_fprintf( output, "PR_AtomicDecrement(%d) == %d: %s\n", oldval, rv, (rv == 1) ? "PASSED" : "FAILED"); oldval = test; rv = PR_AtomicDecrement(&test); result = result | ((rv == 0) ? 0 : 1); PR_fprintf( output, "PR_AtomicDecrement(%d) == %d: %s\n", oldval, rv, (rv == 0) ? "PASSED" : "FAILED"); oldval = test; rv = PR_AtomicDecrement(&test); result = result | ((rv == -1) ? 0 : 1); PR_fprintf( output, "PR_AtomicDecrement(%d) == %d: %s\n", oldval, rv, (rv == -1) ? "PASSED" : "FAILED"); /* set to a different value */ oldval = test = -2; rv = PR_AtomicSet(&test, 2); result = result | (((rv == -2) && (test == 2)) ? 0 : 1); PR_fprintf( output, "PR_AtomicSet(%d, %d) == %d: %s\n", oldval, 2, rv, ((rv == -2) && (test == 2)) ? "PASSED" : "FAILED"); /* set to the same value */ oldval = test = -2; rv = PR_AtomicSet(&test, -2); result = result | (((rv == -2) && (test == -2)) ? 0 : 1); PR_fprintf( output, "PR_AtomicSet(%d, %d) == %d: %s\n", oldval, -2, rv, ((rv == -2) && (test == -2)) ? "PASSED" : "FAILED"); /***********************/ /* Test the macros. */ /***********************/ oldval = test = -2; rv = PR_ATOMIC_INCREMENT(&test); result = result | ((rv == -1) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_INCREMENT(%d) == %d: %s\n", oldval, rv, (rv == -1) ? "PASSED" : "FAILED"); oldval = test; rv = PR_ATOMIC_INCREMENT(&test); result = result | ((rv == 0) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_INCREMENT(%d) == %d: %s\n", oldval, rv, (rv == 0) ? "PASSED" : "FAILED"); oldval = test; rv = PR_ATOMIC_INCREMENT(&test); result = result | ((rv == 1) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_INCREMENT(%d) == %d: %s\n", oldval, rv, (rv == 1) ? "PASSED" : "FAILED"); oldval = test = -2; rv = PR_ATOMIC_ADD(&test,1); result = result | ((rv == -1) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_ADD(%d,%d) == %d: %s\n", oldval, 1, rv, (rv == -1) ? "PASSED" : "FAILED"); oldval = test; rv = PR_ATOMIC_ADD(&test, 4); result = result | ((rv == 3) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_ADD(%d,%d) == %d: %s\n", oldval, 4, rv, (rv == 3) ? "PASSED" : "FAILED"); oldval = test; rv = PR_ATOMIC_ADD(&test, -6); result = result | ((rv == -3) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_ADD(%d,%d) == %d: %s\n", oldval, -6, rv, (rv == -3) ? "PASSED" : "FAILED"); oldval = test = 2; rv = PR_ATOMIC_DECREMENT(&test); result = result | ((rv == 1) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_DECREMENT(%d) == %d: %s\n", oldval, rv, (rv == 1) ? "PASSED" : "FAILED"); oldval = test; rv = PR_ATOMIC_DECREMENT(&test); result = result | ((rv == 0) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_DECREMENT(%d) == %d: %s\n", oldval, rv, (rv == 0) ? "PASSED" : "FAILED"); oldval = test; rv = PR_ATOMIC_DECREMENT(&test); result = result | ((rv == -1) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_DECREMENT(%d) == %d: %s\n", oldval, rv, (rv == -1) ? "PASSED" : "FAILED"); /* set to a different value */ oldval = test = -2; rv = PR_ATOMIC_SET(&test, 2); result = result | (((rv == -2) && (test == 2)) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_SET(%d, %d) == %d: %s\n", oldval, 2, rv, ((rv == -2) && (test == 2)) ? "PASSED" : "FAILED"); /* set to the same value */ oldval = test = -2; rv = PR_ATOMIC_SET(&test, -2); result = result | (((rv == -2) && (test == -2)) ? 0 : 1); PR_fprintf( output, "PR_ATOMIC_SET(%d, %d) == %d: %s\n", oldval, -2, rv, ((rv == -2) && (test == -2)) ? "PASSED" : "FAILED"); PR_fprintf( output, "Atomic operations test %s\n", (result == 0) ? "PASSED" : "FAILED"); return result; } /* main */ /* atomic.c */ nspr-4.11/nspr/pr/tests/attach.c0000644000000000000000000002122112623070344014723 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1996 - Netscape Communications Corporation ** ** Name: attach.c ** ** Description: Platform-specific code to create a native thread. The native thread will ** repeatedly call PR_AttachThread and PR_DetachThread. The ** primordial thread waits for this new thread to finish. ** ** Modification History: ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 Revert to return code 0 and 1. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "nspr.h" #include "pprthred.h" #include "plgetopt.h" #include #ifdef WIN32 #include #include #elif defined(_PR_PTHREADS) #include #include "md/_pth.h" #elif defined(IRIX) #include #include #include #include #elif defined(SOLARIS) #include #elif defined(OS2) #define INCL_DOS #define INCL_ERRORS #include #include #elif defined(XP_BEOS) #include #endif #define DEFAULT_COUNT 1000 PRIntn failed_already=0; PRIntn debug_mode; int count; static void AttachDetach(void) { PRThread *me; PRInt32 index; for (index=0;indexoption) { case 'd': /* debug mode */ debug_mode = 1; break; case 'c': /* loop count */ count = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); #if defined(WIN16) printf("attach: This test is not valid for Win16\n"); goto exit_now; #endif if(0 == count) count = DEFAULT_COUNT; /* * To force the implicit initialization of nspr20 */ PR_SetError(0, 0); PR_STDIO_INIT(); /* * Platform-specific code to create a native thread. The native * thread will repeatedly call PR_AttachThread and PR_DetachThread. * The primordial thread waits for this new thread to finish. */ #ifdef _PR_PTHREADS rv = _PT_PTHREAD_ATTR_INIT(&attr); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #ifndef _PR_DCETHREADS rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #endif /* !_PR_DCETHREADS */ rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL); if (rv != 0) { fprintf(stderr, "thread creation failed: error code %d\n", rv); failed_already=1; goto exit_now; } else { if (debug_mode) printf ("thread creation succeeded \n"); } rv = _PT_PTHREAD_ATTR_DESTROY(&attr); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } rv = pthread_join(threadID, NULL); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #elif defined(SOLARIS) rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID); if (rv != 0) { if(!debug_mode) { failed_already=1; goto exit_now; } else fprintf(stderr, "thread creation failed: error code %d\n", rv); } rv = thr_join(threadID, NULL, NULL); if (debug_mode) PR_ASSERT(0 == rv); else if (0 != rv) { failed_already=1; goto exit_now; } #elif defined(WIN32) hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION, &threadID); if (hThread == 0) { fprintf(stderr, "thread creation failed: error code %d\n", GetLastError()); failed_already=1; goto exit_now; } rv = WaitForSingleObject(hThread, INFINITE); if (debug_mode)PR_ASSERT(rv != WAIT_FAILED); else if (rv == WAIT_FAILED) { failed_already=1; goto exit_now; } #elif defined(IRIX) threadID = sproc(threadStartFunc, PR_SALL, NULL); if (threadID == -1) { fprintf(stderr, "thread creation failed: error code %d\n", errno); failed_already=1; goto exit_now; } else { if (debug_mode) printf ("thread creation succeeded \n"); sleep(3); goto exit_now; } rv = waitpid(threadID, NULL, 0); if (debug_mode) PR_ASSERT(rv != -1); else if (rv != -1) { failed_already=1; goto exit_now; } #elif defined(OS2) threadID = (TID) _beginthread((void *)threadStartFunc, NULL, 32768, NULL); if (threadID == -1) { fprintf(stderr, "thread creation failed: error code %d\n", errno); failed_already=1; goto exit_now; } rv = DosWaitThread(&threadID, DCWW_WAIT); if (debug_mode) { PR_ASSERT(rv == NO_ERROR); } else if (rv != NO_ERROR) { failed_already=1; goto exit_now; } #elif defined(XP_BEOS) threadID = spawn_thread(threadStartFunc, NULL, B_NORMAL_PRIORITY, NULL); if (threadID <= B_ERROR) { fprintf(stderr, "thread creation failed: error code %08lx\n", threadID); failed_already = 1; goto exit_now; } if (resume_thread(threadID) != B_OK) { fprintf(stderr, "failed starting thread: error code %08lx\n", threadID); failed_already = 1; goto exit_now; } waitRV = wait_for_thread(threadID, &threadRV); if (debug_mode) PR_ASSERT(waitRV == B_OK); else if (waitRV != B_OK) { failed_already = 1; goto exit_now; } #else if (!debug_mode) failed_already=1; else printf("The attach test does not apply to this platform because\n" "either this platform does not have native threads or the\n" "test needs to be written for this platform.\n"); goto exit_now; #endif exit_now: if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/bigfile.c0000644000000000000000000002367412623070344015076 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prmem.h" #include "prprf.h" #include "prinit.h" #include "prerror.h" #include "prthread.h" #include "plerror.h" #include "plgetopt.h" #define DEFAULT_COUNT 10 #define DEFAULT_FILESIZE 1 #define BUFFER_SIZE 1000000 typedef enum {v_silent, v_whisper, v_shout} Verbosity; static void Verbose(Verbosity, const char*, const char*, PRIntn); #define VERBOSE(_l, _m) Verbose(_l, _m, __FILE__, __LINE__) static PRIntn test_result = 2; static PRFileDesc *output = NULL; static PRIntn verbose = v_silent; static PRIntn filesize = DEFAULT_FILESIZE; static PRIntn Usage(void) { PR_fprintf(output, "Bigfile test usage:\n"); PR_fprintf(output, ">bigfile [-G] [-d] [-v[*v]] [-s ] \n"); PR_fprintf(output, "\td\tdebug mode (equivalent to -vvv)\t(false)\n"); PR_fprintf(output, "\tv\tAdditional levels of output\t(none)\n"); PR_fprintf(output, "\tk\tKeep data file after exit\t(false)\n"); PR_fprintf(output, "\ts \tFile size in megabytes\t\t(1 megabyte)\n"); PR_fprintf(output, "\t\tName of test file\t(none)\n"); return 2; /* nothing happened */ } /* Usage */ static PRStatus DeleteIfFound(const char *filename) { PRStatus rv; VERBOSE(v_shout, "Checking for existing file"); rv = PR_Access(filename, PR_ACCESS_WRITE_OK); if (PR_SUCCESS == rv) { VERBOSE(v_shout, "Deleting existing file"); rv = PR_Delete(filename); if (PR_FAILURE == rv) VERBOSE(v_shout, "Cannot delete big file"); } else if (PR_FILE_NOT_FOUND_ERROR != PR_GetError()) VERBOSE(v_shout, "Cannot access big file"); else rv = PR_SUCCESS; return rv; } /* DeleteIfFound */ static PRIntn Error(const char *msg, const char *filename) { PRInt32 error = PR_GetError(); if (NULL != msg) { if (0 == error) PR_fprintf(output, msg); else PL_FPrintError(output, msg); } (void)DeleteIfFound(filename); if (v_shout == verbose) PR_Abort(); return 1; } /* Error */ static void Verbose( Verbosity level, const char *msg, const char *file, PRIntn line) { if (level <= verbose) PR_fprintf(output, "[%s : %d]: %s\n", file, line, msg); } /* Verbose */ static void PrintInfo(PRFileInfo64 *info, const char *filename) { PRExplodedTime tm; char ctime[40], mtime[40]; static const char *types[] = {"FILE", "DIRECTORY", "OTHER"}; PR_fprintf( output, "[%s : %d]: File info for %s\n", __FILE__, __LINE__, filename); PR_fprintf( output, " type: %s, size: %llu bytes,\n", types[info->type - 1], info->size); PR_ExplodeTime(info->creationTime, PR_GMTParameters, &tm); (void)PR_FormatTime(ctime, sizeof(ctime), "%c GMT", &tm); PR_ExplodeTime(info->modifyTime, PR_GMTParameters, &tm); (void)PR_FormatTime(mtime, sizeof(mtime), "%c GMT", &tm); PR_fprintf( output, " creation: %s,\n modify: %s\n", ctime, mtime); } /* PrintInfo */ int main(int argc, char **argv) { PRStatus rv; char *buffer; PLOptStatus os; PRInt32 loop, bytes; PRFileInfo small_info; PRFileInfo64 big_info; PRBool keep = PR_FALSE; PRFileDesc *file = NULL; const char *filename = NULL; PRIntn count = DEFAULT_COUNT; PRInt64 filesize64, big_answer, big_size, one_meg, zero_meg, big_fragment; PRInt64 sevenFox = LL_INIT(0,0x7fffffff); PLOptState *opt = PL_CreateOptState(argc, argv, "dtvhs:"); output = PR_GetSpecialFD(PR_StandardError); PR_STDIO_INIT(); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: filename = opt->value; break; case 'd': /* debug mode */ verbose = v_shout; break; case 'k': /* keep file */ keep = PR_TRUE; break; case 'v': /* verbosity */ if (v_shout > verbose) verbose += 1; break; case 'c': /* loop counter */ count = atoi(opt->value); break; case 's': /* filesize */ filesize = atoi(opt->value); break; case 'h': /* confused */ default: return Usage(); } } PL_DestroyOptState(opt); if (0 == count) count = DEFAULT_COUNT; if (0 == filesize) filesize = DEFAULT_FILESIZE; if (NULL == filename) { #ifdef SYMBIAN #define FILE_NAME "c:\\data\\bigfile.dat" #else #define FILE_NAME "bigfile.dat" #endif if (DEFAULT_FILESIZE != filesize) return Usage(); else filename = FILE_NAME; } if (PR_FAILURE == DeleteIfFound(filename)) return 1; test_result = 0; LL_I2L(zero_meg, 0); LL_I2L(one_meg, 1000000); LL_I2L(filesize64, filesize); buffer = (char*)PR_MALLOC(BUFFER_SIZE); LL_I2L(big_fragment, BUFFER_SIZE); LL_MUL(filesize64, filesize64, one_meg); for (loop = 0; loop < BUFFER_SIZE; ++loop) buffer[loop] = (char)loop; VERBOSE(v_whisper, "Creating big file"); file = PR_Open(filename, PR_CREATE_FILE | PR_WRONLY, 0666); if (NULL == file) return Error("PR_Open()", filename); VERBOSE(v_whisper, "Testing available space in empty file"); big_answer = file->methods->available64(file); if (!LL_IS_ZERO(big_answer)) return Error("empty available64()", filename); LL_SUB(big_size, filesize64, one_meg); VERBOSE(v_whisper, "Creating sparse big file by seeking to end"); big_answer = file->methods->seek64(file, big_size, PR_SEEK_SET); if (!LL_EQ(big_answer, big_size)) return Error("seek", filename); VERBOSE(v_whisper, "Writing block at end of sparse file"); bytes = file->methods->write(file, buffer, BUFFER_SIZE); if (bytes != BUFFER_SIZE) return Error("write", filename); VERBOSE(v_whisper, "Testing available space at end of sparse file"); big_answer = file->methods->available64(file); if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename); VERBOSE(v_whisper, "Getting big info on sparse big file"); rv = file->methods->fileInfo64(file, &big_info); if (PR_FAILURE == rv) return Error("fileInfo64()", filename); if (v_shout <= verbose) PrintInfo(&big_info, filename); VERBOSE(v_whisper, "Getting small info on sparse big file"); rv = file->methods->fileInfo(file, &small_info); if (LL_CMP(sevenFox, <, filesize64) && (PR_SUCCESS == rv)) { VERBOSE(v_whisper, "Should have failed and didn't"); return Error("fileInfo()", filename); } else if (LL_CMP(sevenFox, >, filesize64) && (PR_FAILURE == rv)) { VERBOSE(v_whisper, "Should have succeeded and didn't"); return Error("fileInfo()", filename); } VERBOSE(v_whisper, "Rewinding big file"); big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET); if (!LL_IS_ZERO(big_answer)) return Error("rewind seek64()", filename); VERBOSE(v_whisper, "Establishing available space in rewound file"); big_answer = file->methods->available64(file); if (LL_NE(filesize64, big_answer)) return Error("bof available64()", filename); VERBOSE(v_whisper, "Closing big file"); rv = file->methods->close(file); if (PR_FAILURE == rv) return Error("close()", filename); VERBOSE(v_whisper, "Reopening big file"); file = PR_Open(filename, PR_RDWR, 0666); if (NULL == file) return Error("open failed", filename); VERBOSE(v_whisper, "Checking available data in reopened file"); big_answer = file->methods->available64(file); if (LL_NE(filesize64, big_answer)) return Error("reopened available64()", filename); big_answer = zero_meg; VERBOSE(v_whisper, "Rewriting every byte of big file data"); do { bytes = file->methods->write(file, buffer, BUFFER_SIZE); if (bytes != BUFFER_SIZE) return Error("write", filename); LL_ADD(big_answer, big_answer, big_fragment); } while (LL_CMP(big_answer, <, filesize64)); VERBOSE(v_whisper, "Checking position at eof"); big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_CUR); if (LL_NE(big_answer, filesize64)) return Error("file size error", filename); VERBOSE(v_whisper, "Testing available space at eof"); big_answer = file->methods->available64(file); if (!LL_IS_ZERO(big_answer)) return Error("eof available64()", filename); VERBOSE(v_whisper, "Rewinding full file"); big_answer = file->methods->seek64(file, zero_meg, PR_SEEK_SET); if (!LL_IS_ZERO(big_answer)) return Error("bof seek64()", filename); VERBOSE(v_whisper, "Testing available space in rewound file"); big_answer = file->methods->available64(file); if (LL_NE(big_answer, filesize64)) return Error("bof available64()", filename); VERBOSE(v_whisper, "Seeking to end of big file"); big_answer = file->methods->seek64(file, filesize64, PR_SEEK_SET); if (LL_NE(big_answer, filesize64)) return Error("eof seek64()", filename); VERBOSE(v_whisper, "Getting info on big file while it's open"); rv = file->methods->fileInfo64(file, &big_info); if (PR_FAILURE == rv) return Error("fileInfo64()", filename); if (v_shout <= verbose) PrintInfo(&big_info, filename); VERBOSE(v_whisper, "Closing big file"); rv = file->methods->close(file); if (PR_FAILURE == rv) return Error("close()", filename); VERBOSE(v_whisper, "Getting info on big file after it's closed"); rv = PR_GetFileInfo64(filename, &big_info); if (PR_FAILURE == rv) return Error("fileInfo64()", filename); if (v_shout <= verbose) PrintInfo(&big_info, filename); VERBOSE(v_whisper, "Deleting big file"); rv = PR_Delete(filename); if (PR_FAILURE == rv) return Error("PR_Delete()", filename); PR_DELETE(buffer); return test_result; } /* main */ /* bigfile.c */ nspr-4.11/nspr/pr/tests/bigfile2.c0000644000000000000000000000522212623070344015145 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include #include #include #ifdef _WIN32 #include #endif #define TEST_FILE_NAME "bigfile2.txt" #ifdef WINCE #define TEST_FILE_NAME_FOR_CREATEFILE L"bigfile2.txt" #else #define TEST_FILE_NAME_FOR_CREATEFILE TEST_FILE_NAME #endif #define MESSAGE "Hello world!" #define MESSAGE_SIZE 13 int main(int argc, char **argv) { PRFileDesc *fd; PRInt64 offset, position; PRInt32 nbytes; char buf[MESSAGE_SIZE]; #ifdef _WIN32 HANDLE hFile; LARGE_INTEGER li; #endif /* _WIN32 */ LL_I2L(offset, 1); LL_SHL(offset, offset, 32); fd = PR_Open(TEST_FILE_NAME, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0666); if (fd == NULL) { fprintf(stderr, "PR_Open failed\n"); exit(1); } position = PR_Seek64(fd, offset, PR_SEEK_SET); if (!LL_GE_ZERO(position)) { fprintf(stderr, "PR_Seek64 failed\n"); exit(1); } PR_ASSERT(LL_EQ(position, offset)); strcpy(buf, MESSAGE); nbytes = PR_Write(fd, buf, sizeof(buf)); if (nbytes != sizeof(buf)) { fprintf(stderr, "PR_Write failed\n"); exit(1); } if (PR_Close(fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } memset(buf, 0, sizeof(buf)); #ifdef _WIN32 hFile = CreateFile(TEST_FILE_NAME_FOR_CREATEFILE, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFile failed\n"); exit(1); } li.QuadPart = offset; li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN); if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { fprintf(stderr, "SetFilePointer failed\n"); exit(1); } PR_ASSERT(li.QuadPart == offset); if (ReadFile(hFile, buf, sizeof(buf), &nbytes, NULL) == 0) { fprintf(stderr, "ReadFile failed\n"); exit(1); } PR_ASSERT(nbytes == sizeof(buf)); if (strcmp(buf, MESSAGE)) { fprintf(stderr, "corrupt data:$%s$\n", buf); exit(1); } if (CloseHandle(hFile) == 0) { fprintf(stderr, "CloseHandle failed\n"); exit(1); } #endif /* _WIN32 */ if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { fprintf(stderr, "PR_Delete failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/bigfile3.c0000644000000000000000000000515012623070344015146 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include #include #include #ifdef _WIN32 #include #endif #define TEST_FILE_NAME "bigfile3.txt" #ifdef WINCE #define TEST_FILE_NAME_FOR_CREATEFILE L"bigfile3.txt" #else #define TEST_FILE_NAME_FOR_CREATEFILE TEST_FILE_NAME #endif #define MESSAGE "Hello world!" #define MESSAGE_SIZE 13 int main(int argc, char **argv) { PRFileDesc *fd; PRInt64 offset, position; PRInt32 nbytes; char buf[MESSAGE_SIZE]; #ifdef _WIN32 HANDLE hFile; LARGE_INTEGER li; #endif /* _WIN32 */ LL_I2L(offset, 1); LL_SHL(offset, offset, 32); #ifdef _WIN32 hFile = CreateFile(TEST_FILE_NAME_FOR_CREATEFILE, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "CreateFile failed\n"); exit(1); } li.QuadPart = offset; li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN); if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { fprintf(stderr, "SetFilePointer failed\n"); exit(1); } PR_ASSERT(li.QuadPart == offset); strcpy(buf, MESSAGE); if (WriteFile(hFile, buf, sizeof(buf), &nbytes, NULL) == 0) { fprintf(stderr, "WriteFile failed\n"); exit(1); } PR_ASSERT(nbytes == sizeof(buf)); if (CloseHandle(hFile) == 0) { fprintf(stderr, "CloseHandle failed\n"); exit(1); } #endif /* _WIN32 */ memset(buf, 0, sizeof(buf)); fd = PR_Open(TEST_FILE_NAME, PR_RDONLY, 0666); if (fd == NULL) { fprintf(stderr, "PR_Open failed\n"); exit(1); } position = PR_Seek64(fd, offset, PR_SEEK_SET); if (!LL_GE_ZERO(position)) { fprintf(stderr, "PR_Seek64 failed\n"); exit(1); } PR_ASSERT(LL_EQ(position, offset)); nbytes = PR_Read(fd, buf, sizeof(buf)); if (nbytes != sizeof(buf)) { fprintf(stderr, "PR_Read failed\n"); exit(1); } if (strcmp(buf, MESSAGE)) { fprintf(stderr, "corrupt data:$%s$\n", buf); exit(1); } if (PR_Close(fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { fprintf(stderr, "PR_Delete failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/bug1test.c0000644000000000000000000001317612623070344015227 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Attached is a test program that uses the nspr1 to demonstrate a bug under NT4.0. The fix has already been mentioned (add a ResetEvent just before leaving the critical section in _PR_CondWait in hwmon.c). */ #include "prthread.h" #include "prtypes.h" #include "prinit.h" #include "prmon.h" #include "prlog.h" typedef struct Arg_s { PRInt32 a, b; } Arg_t; PRMonitor* gMonitor; // the monitor PRInt32 gReading; // number of read locks PRInt32 gWriteWaiting; // number of threads waiting for write lock PRInt32 gReadWaiting; // number of threads waiting for read lock PRInt32 gCounter; // a counter // stats PRInt32 gReads; // number of successful reads PRInt32 gMaxReads; // max number of simultaneous reads PRInt32 gMaxWriteWaits; // max number of writes that waited for read PRInt32 gMaxReadWaits; // max number of reads that waited for write wait void spin (PRInt32 aDelay) { PRInt32 index; PRInt32 delay = aDelay * 1000; PR_Sleep(0); // randomize delay a bit delay = (delay / 2) + (PRInt32)((float)delay * ((float)rand () / (float)RAND_MAX)); for (index = 0; index < delay * 10; index++) // consume a bunch of cpu cycles ; PR_Sleep(0); } void doWriteThread (void* arg) { PRInt32 last; Arg_t *args = (Arg_t*)arg; PRInt32 aWorkDelay = args->a, aWaitDelay = args->b; PR_Sleep(0); while (1) { // -- enter write lock PR_EnterMonitor (gMonitor); if (0 < gReading) // wait for read locks to go away { PRIntervalTime fiveSecs = PR_SecondsToInterval(5); gWriteWaiting++; if (gWriteWaiting > gMaxWriteWaits) // stats gMaxWriteWaits = gWriteWaiting; while (0 < gReading) PR_Wait (gMonitor, fiveSecs); gWriteWaiting--; } // -- write lock entered last = gCounter; gCounter++; spin (aWorkDelay); PR_ASSERT (gCounter == (last + 1)); // test invariance // -- exit write lock // if (0 < gReadWaiting) // notify waiting reads (do it anyway to show off the CondWait bug) PR_NotifyAll (gMonitor); PR_ExitMonitor (gMonitor); // -- write lock exited spin (aWaitDelay); } } void doReadThread (void* arg) { PRInt32 last; Arg_t *args = (Arg_t*)arg; PRInt32 aWorkDelay = args->a, aWaitDelay = args->b; PR_Sleep(0); while (1) { // -- enter read lock PR_EnterMonitor (gMonitor); if (0 < gWriteWaiting) // give up the monitor to waiting writes { PRIntervalTime fiveSecs = PR_SecondsToInterval(5); gReadWaiting++; if (gReadWaiting > gMaxReadWaits) // stats gMaxReadWaits = gReadWaiting; while (0 < gWriteWaiting) PR_Wait (gMonitor, fiveSecs); gReadWaiting--; } gReading++; gReads++; // stats if (gReading > gMaxReads) // stats gMaxReads = gReading; PR_ExitMonitor (gMonitor); // -- read lock entered last = gCounter; spin (aWorkDelay); PR_ASSERT (gCounter == last); // test invariance // -- exit read lock PR_EnterMonitor (gMonitor); // read unlock gReading--; // if ((0 == gReading) && (0 < gWriteWaiting)) // notify waiting writes (do it anyway to show off the CondWait bug) PR_NotifyAll (gMonitor); PR_ExitMonitor (gMonitor); // -- read lock exited spin (aWaitDelay); } } void fireThread ( char* aName, void (*aProc)(void *arg), Arg_t *aArg) { PRThread *thread = PR_CreateThread( PR_USER_THREAD, aProc, aArg, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); } int pseudoMain (int argc, char** argv, char *pad) { PRInt32 lastWriteCount = gCounter; PRInt32 lastReadCount = gReads; Arg_t a1 = {500, 250}; Arg_t a2 = {500, 500}; Arg_t a3 = {250, 500}; Arg_t a4 = {750, 250}; Arg_t a5 = {100, 750}; Arg_t a6 = {100, 500}; Arg_t a7 = {100, 750}; gMonitor = PR_NewMonitor (); fireThread ("R1", doReadThread, &a1); fireThread ("R2", doReadThread, &a2); fireThread ("R3", doReadThread, &a3); fireThread ("R4", doReadThread, &a4); fireThread ("W1", doWriteThread, &a5); fireThread ("W2", doWriteThread, &a6); fireThread ("W3", doWriteThread, &a7); fireThread ("R5", doReadThread, &a1); fireThread ("R6", doReadThread, &a2); fireThread ("R7", doReadThread, &a3); fireThread ("R8", doReadThread, &a4); fireThread ("W4", doWriteThread, &a5); fireThread ("W5", doWriteThread, &a6); fireThread ("W6", doWriteThread, &a7); while (1) { PRInt32 writeCount, readCount; PRIntervalTime fiveSecs = PR_SecondsToInterval(5); PR_Sleep (fiveSecs); // get out of the way // print some stats, not threadsafe, informative only writeCount = gCounter; readCount = gReads; printf ("\ntick %d writes (+%d), %d reads (+%d) [max %d, %d, %d]", writeCount, writeCount - lastWriteCount, readCount, readCount - lastReadCount, gMaxReads, gMaxWriteWaits, gMaxReadWaits); lastWriteCount = writeCount; lastReadCount = readCount; gMaxReads = gMaxWriteWaits = gMaxReadWaits = 0; } return 0; } static void padStack (int argc, char** argv) { char pad[512]; /* Work around bug in nspr on windoze */ pseudoMain (argc, argv, pad); } int main(int argc, char **argv) { PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); padStack (argc, argv); } /* bug1test.c */ nspr-4.11/nspr/pr/tests/cleanup.c0000644000000000000000000000657112623070344015121 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prprf.h" #include "prio.h" #include "prinit.h" #include "prthread.h" #include "prinrval.h" #include "plgetopt.h" #include static void PR_CALLBACK Thread(void *sleep) { PR_Sleep(PR_SecondsToInterval((PRUint32)sleep)); printf("Thread exiting\n"); } static void Help(void) { PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); PR_fprintf(err, "Cleanup usage: [-g] [-s n] [-t n] [-c n] [-h]\n"); PR_fprintf(err, "\t-c Call cleanup before exiting (default: false)\n"); PR_fprintf(err, "\t-G Use global threads only (default: local)\n"); PR_fprintf(err, "\t-t n Number of threads involved (default: 1)\n"); PR_fprintf(err, "\t-s n Seconds thread(s) should dally (defaut: 10)\n"); PR_fprintf(err, "\t-S n Seconds main() should dally (defaut: 5)\n"); PR_fprintf(err, "\t-C n Value to set concurrency (default 1)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ int main(int argc, char **argv) { PLOptStatus os; PRBool cleanup = PR_FALSE; PRThreadScope type = PR_LOCAL_THREAD; PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); PLOptState *opt = PL_CreateOptState(argc, argv, "Ghs:S:t:cC:"); PRIntn concurrency = 1, child_sleep = 10, main_sleep = 5, threads = 1; PR_STDIO_INIT(); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'c': /* call PR_Cleanup() before exiting */ cleanup = PR_TRUE; break; case 'G': /* local vs global threads */ type = PR_GLOBAL_THREAD; break; case 's': /* time to sleep */ child_sleep = atoi(opt->value); break; case 'S': /* time to sleep */ main_sleep = atoi(opt->value); break; case 'C': /* number of cpus to create */ concurrency = atoi(opt->value); break; case 't': /* number of threads to create */ threads = atoi(opt->value); break; case 'h': /* user wants some guidance */ Help(); /* so give him an earful */ return 2; /* but not a lot else */ break; default: break; } } PL_DestroyOptState(opt); PR_fprintf(err, "Cleanup settings\n"); PR_fprintf(err, "\tThread type: %s\n", (PR_LOCAL_THREAD == type) ? "LOCAL" : "GLOBAL"); PR_fprintf(err, "\tConcurrency: %d\n", concurrency); PR_fprintf(err, "\tNumber of threads: %d\n", threads); PR_fprintf(err, "\tThread sleep: %d\n", child_sleep); PR_fprintf(err, "\tMain sleep: %d\n", main_sleep); PR_fprintf(err, "\tCleanup will %sbe called\n\n", (cleanup) ? "" : "NOT "); PR_SetConcurrency(concurrency); while (threads-- > 0) (void)PR_CreateThread( PR_USER_THREAD, Thread, (void*)child_sleep, PR_PRIORITY_NORMAL, type, PR_UNJOINABLE_THREAD, 0); PR_Sleep(PR_SecondsToInterval(main_sleep)); if (cleanup) PR_Cleanup(); PR_fprintf(err, "main() exiting\n"); return 0; } /* main */ nspr-4.11/nspr/pr/tests/cltsrv.c0000644000000000000000000011402612623070344015002 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * * Notes: * [1] lth. The call to Sleep() is a hack to get the test case to run * on Windows 95. Without it, the test case fails with an error * WSAECONNRESET following a recv() call. The error is caused by the * server side thread termination without a shutdown() or closesocket() * call. Windows docmunentation suggests that this is predicted * behavior; that other platforms get away with it is ... serindipity. * The test case should shutdown() or closesocket() before * thread termination. I didn't have time to figure out where or how * to do it. The Sleep() call inserts enough delay to allow the * client side to recv() all his data before the server side thread * terminates. Whew! ... * ** Modification History: * 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. * The debug mode will print all of the printfs associated with this test. * The regress mode will be the default mode. Since the regress tool limits * the output to a one line status:PASS or FAIL,all of the printf statements * have been handled with an if (debug_mode) statement. */ #include "prclist.h" #include "prcvar.h" #include "prerror.h" #include "prinit.h" #include "prinrval.h" #include "prio.h" #include "prlock.h" #include "prlog.h" #include "prtime.h" #include "prmem.h" #include "prnetdb.h" #include "prprf.h" #include "prthread.h" #include "pprio.h" #include "primpl.h" #include "plstr.h" #include "plerror.h" #include "plgetopt.h" #include #include #if defined(XP_UNIX) #include #endif /* ** This is the beginning of the test */ #define RECV_FLAGS 0 #define SEND_FLAGS 0 #define DEFAULT_LOW 0 #define DEFAULT_HIGH 0 #define BUFFER_SIZE 1024 #define DEFAULT_BACKLOG 5 #define DEFAULT_PORT 12849 #define DEFAULT_CLIENTS 1 #define ALLOWED_IN_ACCEPT 1 #define DEFAULT_CLIPPING 1000 #define DEFAULT_WORKERS_MIN 1 #define DEFAULT_WORKERS_MAX 1 #define DEFAULT_SERVER "localhost" #define DEFAULT_EXECUTION_TIME 10 #define DEFAULT_CLIENT_TIMEOUT 4000 #define DEFAULT_SERVER_TIMEOUT 4000 #define DEFAULT_SERVER_PRIORITY PR_PRIORITY_HIGH typedef enum CSState_e {cs_init, cs_run, cs_stop, cs_exit} CSState_t; static void PR_CALLBACK Worker(void *arg); typedef struct CSPool_s CSPool_t; typedef struct CSWorker_s CSWorker_t; typedef struct CSServer_s CSServer_t; typedef enum Verbosity { TEST_LOG_ALWAYS, TEST_LOG_ERROR, TEST_LOG_WARNING, TEST_LOG_NOTICE, TEST_LOG_INFO, TEST_LOG_STATUS, TEST_LOG_VERBOSE } Verbosity; static PRInt32 domain = AF_INET; static PRInt32 protocol = 6; /* TCP */ static PRFileDesc *debug_out = NULL; static PRBool debug_mode = PR_FALSE; static PRBool pthread_stats = PR_FALSE; static Verbosity verbosity = TEST_LOG_ALWAYS; static PRThreadScope thread_scope = PR_LOCAL_THREAD; struct CSWorker_s { PRCList element; /* list of the server's workers */ PRThread *thread; /* this worker objects thread */ CSServer_t *server; /* back pointer to server structure */ }; struct CSPool_s { PRCondVar *exiting; PRCondVar *acceptComplete; PRUint32 accepting, active, workers; }; struct CSServer_s { PRCList list; /* head of worker list */ PRLock *ml; PRThread *thread; /* the main server thread */ PRCondVar *stateChange; PRUint16 port; /* port we're listening on */ PRUint32 backlog; /* size of our listener backlog */ PRFileDesc *listener; /* the fd accepting connections */ CSPool_t pool; /* statistics on worker threads */ CSState_t state; /* the server's state */ struct /* controlling worker counts */ { PRUint32 minimum, maximum, accepting; } workers; /* statistics */ PRIntervalTime started, stopped; PRUint32 operations, bytesTransferred; }; typedef struct CSDescriptor_s { PRInt32 size; /* size of transfer */ char filename[60]; /* filename, null padded */ } CSDescriptor_t; typedef struct CSClient_s { PRLock *ml; PRThread *thread; PRCondVar *stateChange; PRNetAddr serverAddress; CSState_t state; /* statistics */ PRIntervalTime started, stopped; PRUint32 operations, bytesTransferred; } CSClient_t; #define TEST_LOG(l, p, a) \ do { \ if (debug_mode || (p <= verbosity)) printf a; \ } while (0) PRLogModuleInfo *cltsrv_log_file = NULL; #define MY_ASSERT(_expr) \ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__)) #define TEST_ASSERT(_expr) \ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__)) static void _MY_Assert(const char *s, const char *file, PRIntn ln) { PL_PrintError(NULL); PR_Assert(s, file, ln); } /* _MY_Assert */ static PRBool Aborted(PRStatus rv) { return ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) ? PR_TRUE : PR_FALSE; } static void TimeOfDayMessage(const char *msg, PRThread* me) { char buffer[100]; PRExplodedTime tod; PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod); (void)PR_FormatTime(buffer, sizeof(buffer), "%H:%M:%S", &tod); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("%s(0x%p): %s\n", msg, me, buffer)); } /* TimeOfDayMessage */ static void PR_CALLBACK Client(void *arg) { PRStatus rv; PRIntn index; char buffer[1024]; PRFileDesc *fd = NULL; PRUintn clipping = DEFAULT_CLIPPING; PRThread *me = PR_GetCurrentThread(); CSClient_t *client = (CSClient_t*)arg; CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t); PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT); for (index = 0; index < sizeof(buffer); ++index) buffer[index] = (char)index; client->started = PR_IntervalNow(); PR_Lock(client->ml); client->state = cs_run; PR_NotifyCondVar(client->stateChange); PR_Unlock(client->ml); TimeOfDayMessage("Client started at", me); while (cs_run == client->state) { PRInt32 bytes, descbytes, filebytes, netbytes; (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer)); TEST_LOG(cltsrv_log_file, TEST_LOG_INFO, ("\tClient(0x%p): connecting to server at %s\n", me, buffer)); fd = PR_Socket(domain, SOCK_STREAM, protocol); TEST_ASSERT(NULL != fd); rv = PR_Connect(fd, &client->serverAddress, timeout); if (PR_FAILURE == rv) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): conection failed (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } memset(descriptor, 0, sizeof(*descriptor)); descriptor->size = PR_htonl(descbytes = rand() % clipping); PR_snprintf( descriptor->filename, sizeof(descriptor->filename), "CS%p%p-%p.dat", client->started, me, client->operations); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes)); bytes = PR_Send( fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout); if (sizeof(CSDescriptor_t) != bytes) { if (Aborted(PR_FAILURE)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): send descriptor timeout\n", me)); goto retry; } } TEST_ASSERT(sizeof(*descriptor) == bytes); netbytes = 0; while (netbytes < descbytes) { filebytes = sizeof(buffer); if ((descbytes - netbytes) < filebytes) filebytes = descbytes - netbytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): sending %d bytes\n", me, filebytes)); bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout); if (filebytes != bytes) { if (Aborted(PR_FAILURE)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): send data timeout\n", me)); goto retry; } } TEST_ASSERT(bytes == filebytes); netbytes += bytes; } filebytes = 0; while (filebytes < descbytes) { netbytes = sizeof(buffer); if ((descbytes - filebytes) < netbytes) netbytes = descbytes - filebytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): receiving %d bytes\n", me, netbytes)); bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout); if (-1 == bytes) { if (Aborted(PR_FAILURE)) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive data aborted\n", me)); goto aborted; } else if (PR_IO_TIMEOUT_ERROR == PR_GetError()) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive data timeout\n", me)); else TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto retry; } if (0 == bytes) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tClient(0x%p): unexpected end of stream\n", PR_GetCurrentThread())); break; } filebytes += bytes; } rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); retry: (void)PR_Close(fd); fd = NULL; TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("\tClient(0x%p): disconnected from server\n", me)); PR_Lock(client->ml); client->operations += 1; client->bytesTransferred += 2 * descbytes; rv = PR_WaitCondVar(client->stateChange, rand() % clipping); PR_Unlock(client->ml); if (Aborted(rv)) break; } aborted: client->stopped = PR_IntervalNow(); PR_ClearInterrupt(); if (NULL != fd) rv = PR_Close(fd); PR_Lock(client->ml); client->state = cs_exit; PR_NotifyCondVar(client->stateChange); PR_Unlock(client->ml); PR_DELETE(descriptor); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("\tClient(0x%p): stopped after %u operations and %u bytes\n", PR_GetCurrentThread(), client->operations, client->bytesTransferred)); } /* Client */ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server) { PRStatus drv, rv; char buffer[1024]; PRFileDesc *file = NULL; PRThread * me = PR_GetCurrentThread(); PRInt32 bytes, descbytes, netbytes, filebytes = 0; CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t); PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): receiving desciptor\n", me)); bytes = PR_Recv( fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout); if (-1 == bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto exit; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): receive timeout\n", me)); } goto exit; } if (0 == bytes) { rv = PR_FAILURE; TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): unexpected end of file\n", me)); goto exit; } descbytes = PR_ntohl(descriptor->size); TEST_ASSERT(sizeof(*descriptor) == bytes); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n", me, descbytes, descriptor->filename)); file = PR_Open( descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666); if (NULL == file) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): open file timeout\n", me)); goto aborted; } } TEST_ASSERT(NULL != file); filebytes = 0; while (filebytes < descbytes) { netbytes = sizeof(buffer); if ((descbytes - filebytes) < netbytes) netbytes = descbytes - filebytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes)); bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout); if (-1 == bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): receive data timeout\n", me)); goto aborted; } /* * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED) * on NT here. This is equivalent to ECONNRESET on Unix. * -wtc */ TEST_LOG( cltsrv_log_file, TEST_LOG_WARNING, ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } if(0 == bytes) { TEST_LOG( cltsrv_log_file, TEST_LOG_WARNING, ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me)); rv = PR_FAILURE; goto aborted; } filebytes += bytes; netbytes = bytes; /* The byte count for PR_Write should be positive */ MY_ASSERT(netbytes > 0); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes)); bytes = PR_Write(file, buffer, netbytes); if (netbytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): write file timeout\n", me)); goto aborted; } } TEST_ASSERT(bytes > 0); } PR_Lock(server->ml); server->operations += 1; server->bytesTransferred += filebytes; PR_Unlock(server->ml); rv = PR_Close(file); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); file = NULL; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename)); file = PR_Open(descriptor->filename, PR_RDONLY, 0); if (NULL == file) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): open file timeout\n", PR_GetCurrentThread())); goto aborted; } TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } TEST_ASSERT(NULL != file); netbytes = 0; while (netbytes < descbytes) { filebytes = sizeof(buffer); if ((descbytes - netbytes) < filebytes) filebytes = descbytes - netbytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes)); bytes = PR_Read(file, buffer, filebytes); if (filebytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): read file timeout\n", me)); else TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } TEST_ASSERT(bytes > 0); netbytes += bytes; filebytes = bytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes)); bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout); if (filebytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): send data timeout\n", me)); goto aborted; } break; } TEST_ASSERT(bytes > 0); } PR_Lock(server->ml); server->bytesTransferred += filebytes; PR_Unlock(server->ml); rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH); if (Aborted(rv)) goto aborted; rv = PR_Close(file); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); file = NULL; aborted: PR_ClearInterrupt(); if (NULL != file) PR_Close(file); drv = PR_Delete(descriptor->filename); TEST_ASSERT(PR_SUCCESS == drv); exit: TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): Finished\n", me)); PR_DELETE(descriptor); #if defined(WIN95) PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */ #endif return rv; } /* ProcessRequest */ static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool) { CSWorker_t *worker = PR_NEWZAP(CSWorker_t); worker->server = server; PR_INIT_CLIST(&worker->element); worker->thread = PR_CreateThread( PR_USER_THREAD, Worker, worker, DEFAULT_SERVER_PRIORITY, thread_scope, PR_UNJOINABLE_THREAD, 0); if (NULL == worker->thread) { PR_DELETE(worker); return PR_FAILURE; } TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS, ("\tCreateWorker(0x%p): create new worker (0x%p)\n", PR_GetCurrentThread(), worker->thread)); return PR_SUCCESS; } /* CreateWorker */ static void PR_CALLBACK Worker(void *arg) { PRStatus rv; PRNetAddr from; PRFileDesc *fd = NULL; PRThread *me = PR_GetCurrentThread(); CSWorker_t *worker = (CSWorker_t*)arg; CSServer_t *server = worker->server; CSPool_t *pool = &server->pool; TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1)); PR_Lock(server->ml); PR_APPEND_LINK(&worker->element, &server->list); pool->workers += 1; /* define our existance */ while (cs_run == server->state) { while (pool->accepting >= server->workers.accepting) { TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): waiting for accept slot[%d]\n", me, pool->accepting)); rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT); if (Aborted(rv) || (cs_run != server->state)) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tWorker(0x%p): has been %s\n", me, (Aborted(rv) ? "interrupted" : "stopped"))); goto exit; } } pool->accepting += 1; /* how many are really in accept */ PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): calling accept\n", me)); fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT); PR_Lock(server->ml); pool->accepting -= 1; PR_NotifyCondVar(pool->acceptComplete); if ((NULL == fd) && Aborted(PR_FAILURE)) { if (NULL != server->listener) { PR_Close(server->listener); server->listener = NULL; } goto exit; } if (NULL != fd) { /* ** Create another worker of the total number of workers is ** less than the minimum specified or we have none left in ** accept() AND we're not over the maximum. ** This sort of presumes that the number allowed in accept ** is at least as many as the minimum. Otherwise we'll keep ** creating new threads and deleting them soon after. */ PRBool another = ((pool->workers < server->workers.minimum) || ((0 == pool->accepting) && (pool->workers < server->workers.maximum))) ? PR_TRUE : PR_FALSE; pool->active += 1; PR_Unlock(server->ml); if (another) (void)CreateWorker(server, pool); rv = ProcessRequest(fd, server); if (PR_SUCCESS != rv) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tWorker(0x%p): server process ended abnormally\n", me)); (void)PR_Close(fd); fd = NULL; PR_Lock(server->ml); pool->active -= 1; } } exit: PR_ClearInterrupt(); PR_Unlock(server->ml); if (NULL != fd) { (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH); (void)PR_Close(fd); } TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): exiting [%u]\n", PR_GetCurrentThread(), pool->workers)); PR_Lock(server->ml); pool->workers -= 1; /* undefine our existance */ PR_REMOVE_AND_INIT_LINK(&worker->element); PR_NotifyCondVar(pool->exiting); PR_Unlock(server->ml); PR_DELETE(worker); /* destruction of the "worker" object */ } /* Worker */ static void PR_CALLBACK Server(void *arg) { PRStatus rv; PRNetAddr serverAddress; PRThread *me = PR_GetCurrentThread(); CSServer_t *server = (CSServer_t*)arg; PRSocketOptionData sockOpt; server->listener = PR_Socket(domain, SOCK_STREAM, protocol); sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(server->listener, &sockOpt); TEST_ASSERT(PR_SUCCESS == rv); memset(&serverAddress, 0, sizeof(serverAddress)); if (PR_AF_INET6 != domain) rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress); else rv = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, DEFAULT_PORT, &serverAddress); rv = PR_Bind(server->listener, &serverAddress); TEST_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(server->listener, server->backlog); TEST_ASSERT(PR_SUCCESS == rv); server->started = PR_IntervalNow(); TimeOfDayMessage("Server started at", me); PR_Lock(server->ml); server->state = cs_run; PR_NotifyCondVar(server->stateChange); PR_Unlock(server->ml); /* ** Create the first worker (actually, a thread that accepts ** connections and then processes the work load as needed). ** From this point on, additional worker threads are created ** as they are needed by existing worker threads. */ rv = CreateWorker(server, &server->pool); TEST_ASSERT(PR_SUCCESS == rv); /* ** From here on this thread is merely hanging around as the contact ** point for the main test driver. It's just waiting for the driver ** to declare the test complete. */ TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tServer(0x%p): waiting for state change\n", me)); PR_Lock(server->ml); while ((cs_run == server->state) && !Aborted(rv)) { rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(server->ml); PR_ClearInterrupt(); TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("\tServer(0x%p): shutting down workers\n", me)); /* ** Get all the worker threads to exit. They know how to ** clean up after themselves, so this is just a matter of ** waiting for clorine in the pool to take effect. During ** this stage we're ignoring interrupts. */ server->workers.minimum = server->workers.maximum = 0; PR_Lock(server->ml); while (!PR_CLIST_IS_EMPTY(&server->list)) { PRCList *head = PR_LIST_HEAD(&server->list); CSWorker_t *worker = (CSWorker_t*)head; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker)); rv = PR_Interrupt(worker->thread); TEST_ASSERT(PR_SUCCESS == rv); PR_REMOVE_AND_INIT_LINK(head); } while (server->pool.workers > 0) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tServer(0x%p): waiting for %u workers to exit\n", me, server->pool.workers)); (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT); } server->state = cs_exit; PR_NotifyCondVar(server->stateChange); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("\tServer(0x%p): stopped after %u operations and %u bytes\n", me, server->operations, server->bytesTransferred)); if (NULL != server->listener) PR_Close(server->listener); server->stopped = PR_IntervalNow(); } /* Server */ static void WaitForCompletion(PRIntn execution) { while (execution > 0) { PRIntn dally = (execution > 30) ? 30 : execution; PR_Sleep(PR_SecondsToInterval(dally)); if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n"); execution -= dally; } } /* WaitForCompletion */ static void Help(void) { PR_fprintf(debug_out, "cltsrv test program usage:\n"); PR_fprintf(debug_out, "\t-a threads allowed in accept (5)\n"); PR_fprintf(debug_out, "\t-b backlock for listen (5)\n"); PR_fprintf(debug_out, "\t-c number of clients to create (1)\n"); PR_fprintf(debug_out, "\t-f low water mark for fd caching (0)\n"); PR_fprintf(debug_out, "\t-F high water mark for fd caching (0)\n"); PR_fprintf(debug_out, "\t-w minimal number of server threads (1)\n"); PR_fprintf(debug_out, "\t-W maximum number of server threads (1)\n"); PR_fprintf(debug_out, "\t-e duration of the test in seconds (10)\n"); PR_fprintf(debug_out, "\t-s dsn name of server (localhost)\n"); PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n"); PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n"); PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n"); PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n"); PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n"); PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n"); PR_fprintf(debug_out, "\t-h this message\n"); } /* Help */ static Verbosity IncrementVerbosity(void) { PRIntn verboge = (PRIntn)verbosity + 1; return (Verbosity)verboge; } /* IncrementVerbosity */ int main(int argc, char** argv) { PRUintn index; PRBool boolean; CSClient_t *client; PRStatus rv, joinStatus; CSServer_t *server = NULL; PRUintn backlog = DEFAULT_BACKLOG; PRUintn clients = DEFAULT_CLIENTS; const char *serverName = DEFAULT_SERVER; PRBool serverIsLocal = PR_TRUE; PRUintn accepting = ALLOWED_IN_ACCEPT; PRUintn workersMin = DEFAULT_WORKERS_MIN; PRUintn workersMax = DEFAULT_WORKERS_MAX; PRIntn execution = DEFAULT_EXECUTION_TIME; PRIntn low = DEFAULT_LOW, high = DEFAULT_HIGH; /* * -G use global threads * -a threads allowed in accept * -b backlock for listen * -c number of clients to create * -f low water mark for caching FDs * -F high water mark for caching FDs * -w minimal number of server threads * -W maximum number of server threads * -e duration of the test in seconds * -s dsn name of server (implies no server here) * -v verbosity */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:f:F:w:W:e:s:vdhp"); debug_out = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'X': /* use XTP as transport */ protocol = 36; break; case '6': /* Use IPv6 */ domain = PR_AF_INET6; break; case 'a': /* the value for accepting */ accepting = atoi(opt->value); break; case 'b': /* the value for backlock */ backlog = atoi(opt->value); break; case 'c': /* number of client threads */ clients = atoi(opt->value); break; case 'f': /* low water fd cache */ low = atoi(opt->value); break; case 'F': /* low water fd cache */ high = atoi(opt->value); break; case 'w': /* minimum server worker threads */ workersMin = atoi(opt->value); break; case 'W': /* maximum server worker threads */ workersMax = atoi(opt->value); break; case 'e': /* program execution time in seconds */ execution = atoi(opt->value); break; case 's': /* server's address */ serverName = opt->value; break; case 'v': /* verbosity */ verbosity = IncrementVerbosity(); break; case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'p': /* pthread mode */ pthread_stats = PR_TRUE; break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE; if (0 == execution) execution = DEFAULT_EXECUTION_TIME; if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX; if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN; if (0 == accepting) accepting = ALLOWED_IN_ACCEPT; if (0 == backlog) backlog = DEFAULT_BACKLOG; if (workersMin > accepting) accepting = workersMin; PR_STDIO_INIT(); TimeOfDayMessage("Client/Server started at", PR_GetCurrentThread()); cltsrv_log_file = PR_NewLogModule("cltsrv_log"); MY_ASSERT(NULL != cltsrv_log_file); boolean = PR_SetLogFile("cltsrv.log"); MY_ASSERT(boolean); rv = PR_SetFDCacheSize(low, high); PR_ASSERT(PR_SUCCESS == rv); if (serverIsLocal) { /* Establish the server */ TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("main(0x%p): starting server\n", PR_GetCurrentThread())); server = PR_NEWZAP(CSServer_t); PR_INIT_CLIST(&server->list); server->state = cs_init; server->ml = PR_NewLock(); server->backlog = backlog; server->port = DEFAULT_PORT; server->workers.minimum = workersMin; server->workers.maximum = workersMax; server->workers.accepting = accepting; server->stateChange = PR_NewCondVar(server->ml); server->pool.exiting = PR_NewCondVar(server->ml); server->pool.acceptComplete = PR_NewCondVar(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): creating server thread\n", PR_GetCurrentThread())); server->thread = PR_CreateThread( PR_USER_THREAD, Server, server, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 0); TEST_ASSERT(NULL != server->thread); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): waiting for server init\n", PR_GetCurrentThread())); PR_Lock(server->ml); while (server->state == cs_init) PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): server init complete (port #%d)\n", PR_GetCurrentThread(), server->port)); } if (clients != 0) { /* Create all of the clients */ PRHostEnt host; char buffer[BUFFER_SIZE]; client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t)); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): creating %d client threads\n", PR_GetCurrentThread(), clients)); if (!serverIsLocal) { rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host); if (PR_SUCCESS != rv) { PL_FPrintError(PR_STDERR, "PR_GetHostByName"); return 2; } } for (index = 0; index < clients; ++index) { client[index].state = cs_init; client[index].ml = PR_NewLock(); if (serverIsLocal) { if (PR_AF_INET6 != domain) (void)PR_InitializeNetAddr( PR_IpAddrLoopback, DEFAULT_PORT, &client[index].serverAddress); else rv = PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, DEFAULT_PORT, &client[index].serverAddress); } else { (void)PR_EnumerateHostEnt( 0, &host, DEFAULT_PORT, &client[index].serverAddress); } client[index].stateChange = PR_NewCondVar(client[index].ml); TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("main(0x%p): creating client threads\n", PR_GetCurrentThread())); client[index].thread = PR_CreateThread( PR_USER_THREAD, Client, &client[index], PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); TEST_ASSERT(NULL != client[index].thread); PR_Lock(client[index].ml); while (cs_init == client[index].state) PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(client[index].ml); } } /* Then just let them go at it for a bit */ TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("main(0x%p): waiting for execution interval (%d seconds)\n", PR_GetCurrentThread(), execution)); WaitForCompletion(execution); TimeOfDayMessage("Shutting down", PR_GetCurrentThread()); if (clients != 0) { for (index = 0; index < clients; ++index) { TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS, ("main(0x%p): notifying client(0x%p) to stop\n", PR_GetCurrentThread(), client[index].thread)); PR_Lock(client[index].ml); if (cs_run == client[index].state) { client[index].state = cs_stop; PR_Interrupt(client[index].thread); while (cs_stop == client[index].state) PR_WaitCondVar( client[index].stateChange, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(client[index].ml); TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): joining client(0x%p)\n", PR_GetCurrentThread(), client[index].thread)); joinStatus = PR_JoinThread(client[index].thread); TEST_ASSERT(PR_SUCCESS == joinStatus); PR_DestroyCondVar(client[index].stateChange); PR_DestroyLock(client[index].ml); } PR_DELETE(client); } if (NULL != server) { /* All clients joined - retrieve the server */ TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): notifying server(0x%p) to stop\n", PR_GetCurrentThread(), server->thread)); PR_Lock(server->ml); server->state = cs_stop; PR_Interrupt(server->thread); while (cs_exit != server->state) PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): joining server(0x%p)\n", PR_GetCurrentThread(), server->thread)); joinStatus = PR_JoinThread(server->thread); TEST_ASSERT(PR_SUCCESS == joinStatus); PR_DestroyCondVar(server->stateChange); PR_DestroyCondVar(server->pool.exiting); PR_DestroyCondVar(server->pool.acceptComplete); PR_DestroyLock(server->ml); PR_DELETE(server); } TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("main(0x%p): test complete\n", PR_GetCurrentThread())); PT_FPrintStats(debug_out, "\nPThread Statistics\n"); TimeOfDayMessage("Test exiting at", PR_GetCurrentThread()); PR_Cleanup(); return 0; } /* main */ /* cltsrv.c */ nspr-4.11/nspr/pr/tests/concur.c0000644000000000000000000000736612623070344014766 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: concur.c ** Description: test of adding and removing concurrency options */ #include "prcvar.h" #include "prinit.h" #include "prinrval.h" #include "prlock.h" #include "prprf.h" #include "prmem.h" #include "prlog.h" #include "plgetopt.h" #include "private/pprio.h" #include #define DEFAULT_RANGE 10 #define DEFAULT_LOOPS 100 static PRThreadScope thread_scope = PR_LOCAL_THREAD; typedef struct Context { PRLock *ml; PRCondVar *cv; PRIntn want, have; } Context; /* ** Make the instance of 'context' static (not on the stack) ** for Win16 threads */ static Context context = {NULL, NULL, 0, 0}; static void PR_CALLBACK Dull(void *arg) { Context *context = (Context*)arg; PR_Lock(context->ml); context->have += 1; while (context->want >= context->have) PR_WaitCondVar(context->cv, PR_INTERVAL_NO_TIMEOUT); context->have -= 1; PR_Unlock(context->ml); } /* Dull */ PRIntn PR_CALLBACK Concur(PRIntn argc, char **argv) { PRUintn cpus; PLOptStatus os; PRThread **threads; PRBool debug = PR_FALSE; PRUintn range = DEFAULT_RANGE; PRStatus rc; PRUintn cnt; PRUintn loops = DEFAULT_LOOPS; PRIntervalTime hundredMills = PR_MillisecondsToInterval(100); PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:r:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* GLOBAL threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'd': /* debug mode */ debug = PR_TRUE; break; case 'r': /* range limit */ range = atoi(opt->value); break; case 'l': /* loop counter */ loops = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (0 == range) range = DEFAULT_RANGE; if (0 == loops) loops = DEFAULT_LOOPS; context.ml = PR_NewLock(); context.cv = PR_NewCondVar(context.ml); if (debug) PR_fprintf( PR_STDERR, "Testing with %d CPUs and %d interations\n", range, loops); threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * range); while (--loops > 0) { for (cpus = 1; cpus <= range; ++cpus) { PR_SetConcurrency(cpus); context.want = cpus; threads[cpus - 1] = PR_CreateThread( PR_USER_THREAD, Dull, &context, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); } PR_Sleep(hundredMills); for (cpus = range; cpus > 0; cpus--) { PR_SetConcurrency(cpus); context.want = cpus - 1; PR_Lock(context.ml); PR_NotifyCondVar(context.cv); PR_Unlock(context.ml); } for(cnt = 0; cnt < range; cnt++) { rc = PR_JoinThread(threads[cnt]); PR_ASSERT(rc == PR_SUCCESS); } } if (debug) PR_fprintf( PR_STDERR, "Waiting for %d thread(s) to exit\n", context.have); while (context.have > 0) PR_Sleep(hundredMills); if (debug) PR_fprintf( PR_STDERR, "Finished [want: %d, have: %d]\n", context.want, context.have); PR_DestroyLock(context.ml); PR_DestroyCondVar(context.cv); PR_DELETE(threads); PR_fprintf(PR_STDERR, "PASSED\n"); return 0; } /* Concur */ int main(int argc, char **argv) { PR_STDIO_INIT(); return PR_Initialize(Concur, argc, argv, 0); } /* main */ /* concur.c */ nspr-4.11/nspr/pr/tests/cvar.c0000644000000000000000000001540712623070344014423 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1996 - Netscape Communications Corporation ** ** Name: cvar.c ** ** Description: Tests Condition Variable Operations ** ** Modification History: ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 Revert to return code 0 and 1. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ #include "nspr.h" /* Used to get the command line option */ #include "plgetopt.h" #include #include #include PRMonitor *mon; #define DEFAULT_COUNT 1000 PRInt32 count = 0; PRIntn debug_mode; #define kQSIZE 1 typedef struct { PRLock *bufLock; int startIdx; int numFull; PRCondVar *notFull; PRCondVar *notEmpty; void *data[kQSIZE]; } CircBuf; static PRBool failed = PR_FALSE; /* ** NewCB creates and initializes a new circular buffer. */ static CircBuf* NewCB(void) { CircBuf *cbp; cbp = PR_NEW(CircBuf); if (cbp == NULL) return (NULL); cbp->bufLock = PR_NewLock(); cbp->startIdx = 0; cbp->numFull = 0; cbp->notFull = PR_NewCondVar(cbp->bufLock); cbp->notEmpty = PR_NewCondVar(cbp->bufLock); return (cbp); } /* ** DeleteCB frees a circular buffer. */ static void DeleteCB(CircBuf *cbp) { PR_DestroyLock(cbp->bufLock); PR_DestroyCondVar(cbp->notFull); PR_DestroyCondVar(cbp->notEmpty); PR_DELETE(cbp); } /* ** PutCBData puts new data on the queue. If the queue is full, it waits ** until there is room. */ static void PutCBData(CircBuf *cbp, void *data) { PR_Lock(cbp->bufLock); /* wait while the buffer is full */ while (cbp->numFull == kQSIZE) PR_WaitCondVar(cbp->notFull,PR_INTERVAL_NO_TIMEOUT); cbp->data[(cbp->startIdx + cbp->numFull) % kQSIZE] = data; cbp->numFull += 1; /* let a waiting reader know that there is data */ PR_NotifyCondVar(cbp->notEmpty); PR_Unlock(cbp->bufLock); } /* ** GetCBData gets the oldest data on the queue. If the queue is empty, it waits ** until new data appears. */ static void* GetCBData(CircBuf *cbp) { void *data; PR_Lock(cbp->bufLock); /* wait while the buffer is empty */ while (cbp->numFull == 0) PR_WaitCondVar(cbp->notEmpty,PR_INTERVAL_NO_TIMEOUT); data = cbp->data[cbp->startIdx]; cbp->startIdx =(cbp->startIdx + 1) % kQSIZE; cbp->numFull -= 1; /* let a waiting writer know that there is room */ PR_NotifyCondVar(cbp->notFull); PR_Unlock(cbp->bufLock); return (data); } /************************************************************************/ static int alive; static void PR_CALLBACK CXReader(void *arg) { CircBuf *cbp = (CircBuf *)arg; PRInt32 i, n; void *data; n = count / 2; for (i = 0; i < n; i++) { data = GetCBData(cbp); if ((int)data != i) if (debug_mode) printf("data mismatch at for i = %d usec\n", i); } PR_EnterMonitor(mon); --alive; PR_Notify(mon); PR_ExitMonitor(mon); } static void PR_CALLBACK CXWriter(void *arg) { CircBuf *cbp = (CircBuf *)arg; PRInt32 i, n; n = count / 2; for (i = 0; i < n; i++) PutCBData(cbp, (void *)i); PR_EnterMonitor(mon); --alive; PR_Notify(mon); PR_ExitMonitor(mon); } static void CondWaitContextSwitch(PRThreadScope scope1, PRThreadScope scope2) { PRThread *t1, *t2; CircBuf *cbp; PR_EnterMonitor(mon); alive = 2; cbp = NewCB(); t1 = PR_CreateThread(PR_USER_THREAD, CXReader, cbp, PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t1); t2 = PR_CreateThread(PR_USER_THREAD, CXWriter, cbp, PR_PRIORITY_NORMAL, scope2, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t2); /* Wait for both of the threads to exit */ while (alive) { PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } DeleteCB(cbp); PR_ExitMonitor(mon); } static void CondWaitContextSwitchUU(void) { CondWaitContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD); } static void CondWaitContextSwitchUK(void) { CondWaitContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); } static void CondWaitContextSwitchKK(void) { CondWaitContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); } /************************************************************************/ static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) printf("%40s: %6.2f usec\n", msg, d / count); if (0 == d) failed = PR_TRUE; } static PRIntn PR_CALLBACK RealMain(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name [-d] [-c n] */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dc:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; case 'c': /* loop count */ count = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (0 == count) count = DEFAULT_COUNT; mon = PR_NewMonitor(); Measure(CondWaitContextSwitchUU, "cond var wait context switch- user/user"); Measure(CondWaitContextSwitchUK, "cond var wait context switch- user/kernel"); Measure(CondWaitContextSwitchKK, "cond var wait context switch- kernel/kernel"); PR_DestroyMonitor(mon); if (debug_mode) printf("%s\n", (failed) ? "FAILED" : "PASSED"); if(failed) return 1; else return 0; } int main(int argc, char *argv[]) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/cvar2.c0000644000000000000000000007142412623070344014506 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1996 - Netscape Communications Corporation ** ** Name: cvar2.c ** ** Description: Simple test creates several local and global threads; ** half use a single,shared condvar, and the ** other half have their own condvar. The main thread then loops ** notifying them to wakeup. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ #include "nspr.h" #include "plerror.h" #include "plgetopt.h" #include #include #include int _debug_on = 0; #define DPRINTF(arg) if (_debug_on) printf arg #define DEFAULT_COUNT 100 #define DEFAULT_THREADS 5 PRInt32 count = DEFAULT_COUNT; typedef struct threadinfo { PRThread *thread; PRInt32 id; PRBool internal; PRInt32 *tcount; PRLock *lock; PRCondVar *cvar; PRIntervalTime timeout; PRInt32 loops; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *exitcount; } threadinfo; /* ** Make exitcount, tcount static. for Win16. */ static PRInt32 exitcount=0; static PRInt32 tcount=0; /* Thread that gets notified; many threads share the same condvar */ void PR_CALLBACK SharedCondVarThread(void *_info) { threadinfo *info = (threadinfo *)_info; PRInt32 index; for (index=0; indexloops; index++) { PR_Lock(info->lock); if (*info->tcount == 0) PR_WaitCondVar(info->cvar, info->timeout); #if 0 printf("shared thread %ld notified in loop %ld\n", info->id, index); #endif (*info->tcount)--; PR_Unlock(info->lock); PR_Lock(info->exitlock); (*info->exitcount)++; PR_NotifyCondVar(info->exitcvar); PR_Unlock(info->exitlock); } #if 0 printf("shared thread %ld terminating\n", info->id); #endif } /* Thread that gets notified; no other threads use the same condvar */ void PR_CALLBACK PrivateCondVarThread(void *_info) { threadinfo *info = (threadinfo *)_info; PRInt32 index; for (index=0; indexloops; index++) { PR_Lock(info->lock); if (*info->tcount == 0) { DPRINTF(("PrivateCondVarThread: thread 0x%lx waiting on cvar = 0x%lx\n", PR_GetCurrentThread(), info->cvar)); PR_WaitCondVar(info->cvar, info->timeout); } #if 0 printf("solo thread %ld notified in loop %ld\n", info->id, index); #endif (*info->tcount)--; PR_Unlock(info->lock); PR_Lock(info->exitlock); (*info->exitcount)++; PR_NotifyCondVar(info->exitcvar); DPRINTF(("PrivateCondVarThread: thread 0x%lx notified exitcvar = 0x%lx cnt = %ld\n", PR_GetCurrentThread(), info->exitcvar,(*info->exitcount))); PR_Unlock(info->exitlock); } #if 0 printf("solo thread %ld terminating\n", info->id); #endif } void CreateTestThread(threadinfo *info, PRInt32 id, PRLock *lock, PRCondVar *cvar, PRInt32 loops, PRIntervalTime timeout, PRInt32 *tcount, PRLock *exitlock, PRCondVar *exitcvar, PRInt32 *exitcount, PRBool shared, PRThreadScope scope) { info->id = id; info->internal = (shared) ? PR_FALSE : PR_TRUE; info->lock = lock; info->cvar = cvar; info->loops = loops; info->timeout = timeout; info->tcount = tcount; info->exitlock = exitlock; info->exitcvar = exitcvar; info->exitcount = exitcount; info->thread = PR_CreateThread( PR_USER_THREAD, shared?SharedCondVarThread:PrivateCondVarThread, info, PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (!info->thread) PL_PrintError("error creating thread\n"); } void CondVarTestSUU(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg); exitcount -= arg; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg); index++) PR_JoinThread(list[index].thread); PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); } void CondVarTestSUK(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg); exitcount -= arg; PR_Unlock(exitlock); #if 0 printf("threads ready\n"); #endif } /* Join all the threads */ for(index=0; index<(arg); index++) PR_JoinThread(list[index].thread); PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); } void CondVarTestPUU(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *tcount, *saved_tcount; exitcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg); exitcount -= arg; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg); index++) { DPRINTF(("CondVarTestPUU: joining thread 0x%lx\n",list[index].thread)); PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); PR_DELETE(saved_tcount); } void CondVarTestPUK(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *tcount, *saved_tcount; exitcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); saved_tcount = tcount = (PRInt32 *)PR_CALLOC(sizeof(*tcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg); exitcount -= arg; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg); index++) { PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); PR_DELETE(saved_tcount); } void CondVarTest(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *ptcount, *saved_ptcount; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); saved_ptcount = ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg*4); exitcount -= arg*4; PR_Unlock(exitlock); #if 0 printf("threads ready\n"); #endif } /* Join all the threads */ for(index=0; index<(arg*4); index++) { PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); PR_DELETE(saved_ptcount); } void CondVarTimeoutTest(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg*4); exitcount -= arg*4; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg*4); index++) { PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DestroyCondVar(exitcvar); PR_DestroyLock(exitlock); PR_DELETE(list); } void CondVarMixedTest(void *_arg) { PRInt32 arg = (PRInt32)_arg; PRInt32 index, loops; threadinfo *list; PRLock *sharedlock; PRCondVar *sharedcvar; PRLock *exitlock; PRCondVar *exitcvar; PRInt32 *ptcount; exitcount=0; tcount=0; list = (threadinfo *)PR_MALLOC(sizeof(threadinfo) * (arg * 4)); ptcount = (PRInt32 *)PR_CALLOC(sizeof(*ptcount) * (arg * 4)); sharedlock = PR_NewLock(); sharedcvar = PR_NewCondVar(sharedlock); exitlock = PR_NewLock(); exitcvar = PR_NewCondVar(exitlock); /* Create the threads */ for(index=0; index= arg*4); exitcount -= arg*4; PR_Unlock(exitlock); } /* Join all the threads */ for(index=0; index<(arg*4); index++) { PR_JoinThread(list[index].thread); if (list[index].internal) { PR_Lock(list[index].lock); PR_DestroyCondVar(list[index].cvar); PR_Unlock(list[index].lock); PR_DestroyLock(list[index].lock); } } PR_DestroyCondVar(sharedcvar); PR_DestroyLock(sharedlock); PR_DELETE(list); } void CondVarCombinedTest(void *arg) { PRThread *threads[3]; threads[0] = PR_CreateThread(PR_USER_THREAD, CondVarTest, (void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); threads[1] = PR_CreateThread(PR_USER_THREAD, CondVarTimeoutTest, (void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); threads[2] = PR_CreateThread(PR_USER_THREAD, CondVarMixedTest, (void *)arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); PR_JoinThread(threads[0]); PR_JoinThread(threads[1]); PR_JoinThread(threads[2]); } /************************************************************************/ static void Measure(void (*func)(void *), PRInt32 arg, const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)((void *)arg); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); printf("%40s: %6.2f usec\n", msg, d / count); } static PRIntn PR_CALLBACK RealMain(int argc, char **argv) { PRInt32 threads, default_threads = DEFAULT_THREADS; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "vc:t:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'v': /* debug mode */ _debug_on = 1; break; case 'c': /* loop counter */ count = atoi(opt->value); break; case 't': /* number of threads involved */ default_threads = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (0 == count) count = DEFAULT_COUNT; if (0 == default_threads) default_threads = DEFAULT_THREADS; printf("\n\ CondVar Test: \n\ \n\ Simple test creates several local and global threads; half use a single,\n\ shared condvar, and the other half have their own condvar. The main \n\ thread then loops notifying them to wakeup. \n\ \n\ The timeout test is very similar except that the threads are not \n\ notified. They will all wakeup on a 1 second timeout. \n\ \n\ The mixed test combines the simple test and the timeout test; every \n\ third thread is notified, the other threads are expected to timeout \n\ correctly. \n\ \n\ Lastly, the combined test creates a thread for each of the above three \n\ cases and they all run simultaneously. \n\ \n\ This test is run with %d, %d, %d, and %d threads of each type.\n\n", default_threads, default_threads*2, default_threads*3, default_threads*4); PR_SetConcurrency(2); for (threads = default_threads; threads < default_threads*5; threads+=default_threads) { printf("\n%ld Thread tests\n", threads); Measure(CondVarTestSUU, threads, "Condvar simple test shared UU"); Measure(CondVarTestSUK, threads, "Condvar simple test shared UK"); Measure(CondVarTestPUU, threads, "Condvar simple test priv UU"); Measure(CondVarTestPUK, threads, "Condvar simple test priv UK"); Measure(CondVarTest, threads, "Condvar simple test All"); Measure(CondVarTimeoutTest, threads, "Condvar timeout test"); #if 0 Measure(CondVarMixedTest, threads, "Condvar mixed timeout test"); Measure(CondVarCombinedTest, threads, "Combined condvar test"); #endif } printf("PASS\n"); return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/dbmalloc.c0000644000000000000000000001642212623070344015243 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dbmalloc.c ** ** Description: Testing malloc (OBSOLETE) ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ #include #include #include #include #include "nspr.h" void usage ( void ) { fprintf(stderr, "Usage: dbmalloc ('-m'|'-s') '-f' num_fails ('-d'|'-n') filename [...]\n"); exit(0); } typedef struct node_struct { struct node_struct *next, *prev; int line; char value[4]; } node_t, *node_pt; node_pt get_node(const char *line) { node_pt rv; int l = strlen(line); rv = (node_pt)PR_MALLOC(sizeof(node_t) + l + 1 - 4); if( (node_pt)0 == rv ) return (node_pt)0; memcpy(&rv->value[0], line, l+1); rv->next = rv->prev = (node_pt)0; return rv; } void dump ( const char *name, node_pt node, int mf, int debug ) { if( (node_pt)0 != node->prev ) dump(name, node->prev, mf, debug); if( 0 != debug ) printf("[%s]: %6d: %s", name, node->line, node->value); if( node->line == mf ) fprintf(stderr, "[%s]: Line %d was allocated!\n", name, node->line); if( (node_pt)0 != node->next ) dump(name, node->next, mf, debug); return; } void release ( node_pt node ) { if( (node_pt)0 != node->prev ) release(node->prev); if( (node_pt)0 != node->next ) release(node->next); PR_DELETE(node); } int t2 ( const char *name, int mf, int debug ) { int rv; FILE *fp; int l = 0; node_pt head = (node_pt)0; char buffer[ BUFSIZ ]; fp = fopen(name, "r"); if( (FILE *)0 == fp ) { fprintf(stderr, "[%s]: Cannot open \"%s.\"\n", name, name); return -1; } /* fgets mallocs a buffer, first time through. */ if( (char *)0 == fgets(buffer, BUFSIZ, fp) ) { fprintf(stderr, "[%s]: \"%s\" is empty.\n", name, name); (void)fclose(fp); return -1; } rewind(fp); if( PR_SUCCESS != PR_ClearMallocCount() ) { fprintf(stderr, "[%s]: Cannot clear malloc count.\n", name); (void)fclose(fp); return -1; } if( PR_SUCCESS != PR_SetMallocCountdown(mf) ) { fprintf(stderr, "[%s]: Cannot set malloc countdown to %d\n", name, mf); (void)fclose(fp); return -1; } while( fgets(buffer, BUFSIZ, fp) ) { node_pt n; node_pt *w = &head; if( (strlen(buffer) == (BUFSIZ-1)) && (buffer[BUFSIZ-2] != '\n') ) buffer[BUFSIZ-2] == '\n'; l++; n = get_node(buffer); if( (node_pt)0 == n ) { printf("[%s]: Line %d: malloc failure!\n", name, l); continue; } n->line = l; while( 1 ) { int comp; if( (node_pt)0 == *w ) { *w = n; break; } comp = strcmp((*w)->value, n->value); if( comp < 0 ) w = &(*w)->next; else w = &(*w)->prev; } } (void)fclose(fp); dump(name, head, mf, debug); rv = PR_GetMallocCount(); PR_ClearMallocCountdown(); release(head); return rv; } int nf = 0; int debug = 0; void test ( const char *name ) { int n, i; extern int nf, debug; printf("[%s]: starting test 0\n", name); n = t2(name, 0, debug); if( -1 == n ) return; printf("[%s]: test 0 had %ld allocations.\n", name, n); if( 0 >= n ) return; for( i = 0; i < nf; i++ ) { int which = rand() % n; if( 0 == which ) printf("[%s]: starting test %d -- no allocation should fail\n", name, i+1); else printf("[%s]: starting test %d -- allocation %d should fail\n", name, i+1, which); (void)t2(name, which, debug); printf("[%s]: test %d done.\n", name, i+1); } return; } int main(int argc, char **argv) { int okay = 0; int multithread = 0; struct threadlist { struct threadlist *next; PRThread *thread; } *threadhead = (struct threadlist *)0; extern int nf, debug; srand(time(0)); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); printf("[main]: We %s using the debugging malloc.\n", PR_IsDebuggingMalloc() ? "ARE" : "ARE NOT"); while( argv++, --argc ) { if( '-' == argv[0][0] ) { switch( argv[0][1] ) { case 'f': nf = atoi(argv[0][2] ? &argv[0][2] : --argc ? *++argv : "0"); break; case 'd': debug = 1; break; case 'n': debug = 0; break; case 'm': multithread = 1; break; case 's': multithread = 0; break; default: usage(); break; } } else { FILE *fp = fopen(*argv, "r"); if( (FILE *)0 == fp ) { fprintf(stderr, "Cannot open \"%s.\"\n", *argv); continue; } okay++; (void)fclose(fp); if( multithread ) { struct threadlist *n; n = (struct threadlist *)malloc(sizeof(struct threadlist)); if( (struct threadlist *)0 == n ) { fprintf(stderr, "This is getting tedious. \"%s\"\n", *argv); continue; } n->next = threadhead; n->thread = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))test, *argv, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if( (PRThread *)0 == n->thread ) { fprintf(stderr, "Can't create thread for \"%s.\"\n", *argv); continue; } else { threadhead = n; } } else { test(*argv); } } } if( okay == 0 ) usage(); else while( (struct threadlist *)0 != threadhead ) { struct threadlist *x = threadhead->next; (void)PR_JoinThread(threadhead->thread); PR_DELETE(threadhead); threadhead = x; } return 0; } nspr-4.11/nspr/pr/tests/dbmalloc1.c0000644000000000000000000000466612623070344015333 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dbmalloc1.c (OBSOLETE) ** ** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** ** 12-June-97 AGarcia Revert to return code 0 and 1, remove debug option (obsolete). ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ #include #include #include "nspr.h" PRIntn failed_already=0; PRIntn debug_mode; /* variable used for both r1 and r2 tests */ int should_fail =0; int actually_failed=0; void r1 ( void ) { int i; actually_failed=0; for( i = 0; i < 5; i++ ) { void *x = PR_MALLOC(128); if( (void *)0 == x ) { if (debug_mode) printf("\tMalloc %d failed.\n", i+1); actually_failed = 1; } PR_DELETE(x); } if (((should_fail != actually_failed) & (!debug_mode))) failed_already=1; return; } void r2 ( void ) { int i; for( i = 0; i <= 5; i++ ) { should_fail =0; if( 0 == i ) { if (debug_mode) printf("No malloc should fail:\n"); } else { if (debug_mode) printf("Malloc %d should fail:\n", i); should_fail = 1; } PR_SetMallocCountdown(i); r1(); PR_ClearMallocCountdown(); } } int main(int argc, char **argv) { /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); r2(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/dceemu.c0000644000000000000000000000554412623070344014733 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: dceemu.c ** Description: testing the DCE emulation api ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 Revert to return code 0 and 1, remove debug option (obsolete). **/ /*********************************************************************** ** Includes ***********************************************************************/ #include "prlog.h" #include "prinit.h" #include "prpdce.h" #include #include #if defined(_PR_DCETHREADS) PRIntn failed_already=0; PRIntn debug_mode=0; static PRIntn prmain(PRIntn argc, char **argv) { PRStatus rv; PRLock *ml = PR_NewLock(); PRCondVar *cv = PRP_NewNakedCondVar(); PRIntervalTime tenmsecs = PR_MillisecondsToInterval(10); rv = PRP_TryLock(ml); PR_ASSERT(PR_SUCCESS == rv); if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1; rv = PRP_TryLock(ml); PR_ASSERT(PR_FAILURE == rv); if ((rv != PR_FAILURE) & (!debug_mode)) failed_already=1; rv = PRP_NakedNotify(cv); PR_ASSERT(PR_SUCCESS == rv); if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1; rv = PRP_NakedBroadcast(cv); PR_ASSERT(PR_SUCCESS == rv); if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1; rv = PRP_NakedWait(cv, ml, tenmsecs); PR_ASSERT(PR_SUCCESS == rv); if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1; PR_Unlock(ml); rv = PRP_NakedNotify(cv); PR_ASSERT(PR_SUCCESS == rv); if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1; rv = PRP_NakedBroadcast(cv); PR_ASSERT(PR_SUCCESS == rv); if ((rv != PR_SUCCESS) & (!debug_mode)) failed_already=1; PRP_DestroyNakedCondVar(cv); PR_DestroyLock(ml); if (debug_mode) printf("Test succeeded\n"); return 0; } /* prmain */ #endif /* #if defined(_PR_DCETHREADS) */ int main(int argc, char **argv) { #if defined(_PR_DCETHREADS) PR_Initialize(prmain, argc, argv, 0); if(failed_already) return 1; else return 0; #else return 0; #endif } /* main */ /* decemu.c */ nspr-4.11/nspr/pr/tests/depend.c0000644000000000000000000000774612623070344014736 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1996 - Netscape Communications Corporation ** ** ** Name: depend.c ** Description: Test to enumerate the dependencies * ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ #include "prinit.h" /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include #include static void PrintVersion( const char *msg, const PRVersion* info, PRIntn tab) { static const len = 20; static const char *tabs = {" "}; tab *= 2; if (tab > len) tab = len; printf("%s", &tabs[len - tab]); printf("%s ", msg); printf("%s ", info->id); printf("%d.%d", info->major, info->minor); if (0 != info->patch) printf(".p%d", info->patch); printf("\n"); } /* PrintDependency */ static void ChaseDependents(const PRVersionInfo *info, PRIntn tab) { PrintVersion("exports", &info->selfExport, tab); if (NULL != info->importEnumerator) { const PRDependencyInfo *dependent = NULL; while (NULL != (dependent = info->importEnumerator(dependent))) { const PRVersionInfo *import = dependent->exportInfoFn(); PrintVersion("imports", &dependent->importNeeded, tab); ChaseDependents(import, tab + 1); } } } /* ChaseDependents */ static PRVersionInfo hack_export; static PRVersionInfo dummy_export; static PRDependencyInfo dummy_imports[2]; static const PRVersionInfo *HackExportInfo(void) { hack_export.selfExport.major = 11; hack_export.selfExport.minor = 10; hack_export.selfExport.patch = 200; hack_export.selfExport.id = "Hack"; hack_export.importEnumerator = NULL; return &hack_export; } static const PRDependencyInfo *DummyImports( const PRDependencyInfo *previous) { if (NULL == previous) return &dummy_imports[0]; else if (&dummy_imports[0] == previous) return &dummy_imports[1]; else if (&dummy_imports[1] == previous) return NULL; } /* DummyImports */ static const PRVersionInfo *DummyLibVersion(void) { dummy_export.selfExport.major = 1; dummy_export.selfExport.minor = 0; dummy_export.selfExport.patch = 0; dummy_export.selfExport.id = "Dumbass application"; dummy_export.importEnumerator = DummyImports; dummy_imports[0].importNeeded.major = 2; dummy_imports[0].importNeeded.minor = 0; dummy_imports[0].importNeeded.patch = 0; dummy_imports[0].importNeeded.id = "Netscape Portable Runtime"; dummy_imports[0].exportInfoFn = PR_ExportInfo; dummy_imports[1].importNeeded.major = 5; dummy_imports[1].importNeeded.minor = 1; dummy_imports[1].importNeeded.patch = 2; dummy_imports[1].importNeeded.id = "Hack Library"; dummy_imports[1].exportInfoFn = HackExportInfo; return &dummy_export; } /* DummyLibVersion */ int main(int argc, char **argv) { PRIntn tab = 0; const PRVersionInfo *info = DummyLibVersion(); const char *buildDate = __DATE__, *buildTime = __TIME__; printf("Depend.c build time is %s %s\n", buildDate, buildTime); if (NULL != info) ChaseDependents(info, tab); return 0; } /* main */ /* depend.c */ nspr-4.11/nspr/pr/tests/dll/.cvsignore0000644000000000000000000000001112623070344016060 0ustar 00000000000000Makefile nspr-4.11/nspr/pr/tests/dll/Makefile.in0000644000000000000000000000311512623070344016135 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = ../../.. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk CSRCS = mygetval.c mysetval.c INCLUDES = -I$(dist_includedir) OBJS = $(OBJDIR)/mygetval.$(OBJ_SUFFIX) \ $(OBJDIR)/mysetval.$(OBJ_SUFFIX) ifeq ($(OS_TARGET), WIN16) W16OBJS = $(subst $(space),$(comma)$(space),$(OBJS)) endif ifeq ($(OS_ARCH), WINNT) ifeq ($(OS_TARGET), WIN16) # do nothing else RES=$(OBJDIR)/my.res RESNAME=../../../pr/src/nspr.rc endif endif ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) IMPORT_LIBRARY = $(OBJDIR)/my.$(LIB_SUFFIX) SHARED_LIBRARY = $(OBJDIR)/my.dll ifeq ($(OS_ARCH), OS2) MAPFILE = $(OBJDIR)/my.def GARBAGE += $(MAPFILE) MKSHLIB += $(MAPFILE) endif TARGETS = $(SHARED_LIBRARY) $(IMPORT_LIBRARY) else ifdef MKSHLIB SHARED_LIBRARY = $(OBJDIR)/libmy.$(DLL_SUFFIX) endif TARGETS = $(SHARED_LIBRARY) endif # # To create a loadable module on Darwin, we must override # -dynamiclib with -bundle. # ifeq ($(OS_ARCH),Darwin) DSO_LDOPTS = -bundle endif include $(topsrcdir)/config/rules.mk ifeq ($(OS_TARGET), WIN16) # Note: The Win16 target: my.dll requires these macros # to be overridden to build the test .dll # default values in win16...mk are for release targets. # OS_DLL_OPTION = NOCASEEXACT OS_LIB_FLAGS = -irn endif ifdef SHARED_LIBRARY export:: $(TARGETS) clean:: rm -rf $(TARGETS) endif nspr-4.11/nspr/pr/tests/dll/my.def0000644000000000000000000000213312623070344015174 0ustar 00000000000000;+# ;+# This Source Code Form is subject to the terms of the Mozilla Public ;+# License, v. 2.0. If a copy of the MPL was not distributed with this ;+# file, You can obtain one at http://mozilla.org/MPL/2.0/. ;+# ;+# OK, this file is meant to support SUN, LINUX, AIX, OS/2 and WINDOWS ;+# 1. For all unix platforms, the string ";-" means "remove this line" ;+# 2. For all unix platforms, the string " DATA " will be removed from any ;+# line on which it occurs. ;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. ;+# On AIX, lines containing ";+" will be removed. ;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. ;+# 5. For all unix platforms, after the above processing has taken place, ;+# all characters after the first ";" on the line will be removed. ;+# And for AIX, the first ";" will also be removed. ;+# This file is passed directly to windows. Since ';' is a comment, all UNIX ;+# directives are hidden behind ";", ";+", and ";-" ;+# ;+MY_1.0 { ;+ global: LIBRARY my ;- EXPORTS ;- My_GetValue; My_SetValue; ;+ local: *; ;+}; nspr-4.11/nspr/pr/tests/dll/mygetval.c0000644000000000000000000000115212623070344016063 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #if defined(WIN16) #include #endif #include "prtypes.h" extern PRIntn my_global; PR_IMPLEMENT(PRIntn) My_GetValue() { return my_global; } #if defined(WIN16) int CALLBACK LibMain( HINSTANCE hInst, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine ) { return TRUE; } #endif /* WIN16 */ nspr-4.11/nspr/pr/tests/dll/mysetval.c0000644000000000000000000000061712623070344016104 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prtypes.h" PRIntn my_global = 0; PR_IMPLEMENT(void) My_SetValue(PRIntn val) { my_global = val; } nspr-4.11/nspr/pr/tests/dlltest.c0000644000000000000000000001373212623070344015142 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dlltest.c ** ** Description: test dll functionality. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 Revert to return code 0 and 1. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ #include "prinit.h" #include "prlink.h" #include "prmem.h" #include "prerror.h" #include "plstr.h" #include #include typedef PRIntn (PR_CALLBACK *GetFcnType)(void); typedef void (PR_CALLBACK *SetFcnType)(PRIntn); PRIntn failed_already=0; PRIntn debug_mode; int main(int argc, char** argv) { PRLibrary *lib, *lib2; /* two handles to the same library */ GetFcnType getFcn; SetFcnType setFcn; PRIntn value; PRStatus status; char *libName; if (argc >= 2 && PL_strcmp(argv[1], "-d") == 0) { debug_mode = 1; } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); /* * Test 1: load the library, look up the symbols, call the functions, * and check the results. */ libName = PR_GetLibraryName("dll", "my"); if (debug_mode) printf("Loading library %s\n", libName); lib = PR_LoadLibrary(libName); PR_FreeLibraryName(libName); if (lib == NULL) { PRInt32 textLength = PR_GetErrorTextLength(); char *text = (char*)PR_MALLOC(textLength + 1); text[0] = '\0'; (void)PR_GetErrorText(text); fprintf( stderr, "PR_LoadLibrary failed (%d, %d, %s)\n", PR_GetError(), PR_GetOSError(), text); if (!debug_mode) failed_already=1; } getFcn = (GetFcnType) PR_FindSymbol(lib, "My_GetValue"); setFcn = (SetFcnType) PR_FindFunctionSymbol(lib, "My_SetValue"); (*setFcn)(888); value = (*getFcn)(); if (value != 888) { fprintf(stderr, "Test 1 failed: set value to 888, but got %d\n", value); if (!debug_mode) failed_already=1; } if (debug_mode) printf("Test 1 passed\n"); /* * Test 2: get a second handle to the same library (this should increment * the reference count), look up the symbols, call the functions, and * check the results. */ getFcn = (GetFcnType) PR_FindSymbolAndLibrary("My_GetValue", &lib2); if (NULL == getFcn || lib != lib2) { fprintf(stderr, "Test 2 failed: handles for the same library are not " "equal: handle 1: %p, handle 2: %p\n", lib, lib2); if (!debug_mode) failed_already=1; } setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue"); value = (*getFcn)(); if (value != 888) { fprintf(stderr, "Test 2 failed: value should be 888, but got %d\n", value); if (!debug_mode) failed_already=1; } (*setFcn)(777); value = (*getFcn)(); if (value != 777) { fprintf(stderr, "Test 2 failed: set value to 777, but got %d\n", value); if (!debug_mode) failed_already=1; goto exit_now; } if (debug_mode) printf("Test 2 passed\n"); /* * Test 3: unload the library. The library should still be accessible * via the second handle. do the same things as above. */ status = PR_UnloadLibrary(lib); if (PR_FAILURE == status) { fprintf(stderr, "Test 3 failed: cannot unload library: (%d, %d)\n", PR_GetError(), PR_GetOSError()); if (!debug_mode) failed_already=1; goto exit_now; } getFcn = (GetFcnType) PR_FindFunctionSymbol(lib2, "My_GetValue"); setFcn = (SetFcnType) PR_FindSymbol(lib2, "My_SetValue"); (*setFcn)(666); value = (*getFcn)(); if (value != 666) { fprintf(stderr, "Test 3 failed: set value to 666, but got %d\n", value); if (!debug_mode) failed_already=1; goto exit_now; } if (debug_mode) printf("Test 3 passed\n"); /* * Test 4: unload the library, testing the reference count mechanism. */ status = PR_UnloadLibrary(lib2); if (PR_FAILURE == status) { fprintf(stderr, "Test 4 failed: cannot unload library: (%d, %d)\n", PR_GetError(), PR_GetOSError()); if (!debug_mode) failed_already=1; goto exit_now; } getFcn = (GetFcnType) PR_FindFunctionSymbolAndLibrary("My_GetValue", &lib2); if (NULL != getFcn) { fprintf(stderr, "Test 4 failed: how can we find a symbol " "in an already unloaded library?\n"); if (!debug_mode) failed_already=1; goto exit_now; } if (debug_mode) { printf("Test 4 passed\n"); } /* ** Test 5: LoadStaticLibrary() */ { PRStaticLinkTable slt[10]; PRLibrary *lib; lib = PR_LoadStaticLibrary( "my.dll", slt ); if ( lib == NULL ) { fprintf(stderr, "Test 5: LoadStatiLibrary() failed\n" ); goto exit_now; } if (debug_mode) { printf("Test 5 passed\n"); } } goto exit_now; exit_now: PR_Cleanup(); if (failed_already) { printf("FAILED\n"); return 1; } else { printf("PASSED\n"); return 0; } } nspr-4.11/nspr/pr/tests/dtoa.c0000644000000000000000000001372712623070344014422 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /****************************************************************************** * * This file contains a test program for the function conversion functions * for double precision code: * PR_strtod * PR_dtoa * PR_cnvtf * * This file was ns/nspr/tests/dtoa.c, created by rrj on 1996/06/22. * *****************************************************************************/ #include #include #include #include #include #include "prprf.h" #include "prdtoa.h" static int failed_already = 0; int main(int argc, char **argv) { double num; double num1; double zero = 0.0; char cnvt[50]; char *thousands; num = 1e24; num1 = PR_strtod("1e24",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","1e24"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("1e+24",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = 0.001e7; num1 = PR_strtod("0.001e7",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","0.001e7"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("10000",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = 0.0000000000000753; num1 = PR_strtod("0.0000000000000753",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n", "0.0000000000000753"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("7.53e-14",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = 1.867e73; num1 = PR_strtod("1.867e73",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","1.867e73"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("1.867e+73",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = -1.867e73; num1 = PR_strtod("-1.867e73",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","-1.867e73"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("-1.867e+73",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = -1.867e-73; num1 = PR_strtod("-1.867e-73",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","-1.867e-73"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("-1.867e-73",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } /* Testing for infinity */ num = 1.0 / zero; num1 = PR_strtod("1.867e765",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","1.867e765"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("Infinity",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = -1.0 / zero; num1 = PR_strtod("-1.867e765",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n","-1.867e765"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("-Infinity",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } /* Testing for NaN. PR_strtod can't parse "NaN" and "Infinity" */ num = zero / zero; PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("NaN",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = - zero / zero; PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("NaN",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = 1.0000000001e21; num1 = PR_strtod("1.0000000001e21",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n", "1.0000000001e21"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("1.0000000001e+21",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } num = -1.0000000001e-21; num1 = PR_strtod("-1.0000000001e-21",NULL); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n", "-1.0000000001e-21"); failed_already = 1; } PR_cnvtf(cnvt,sizeof(cnvt),20,num); if(strcmp("-1.0000000001e-21",cnvt) != 0){ fprintf(stderr,"Failed to convert numeric value %lf %s\n",num,cnvt); failed_already = 1; } /* * Bug 414772: should not exit with "Zero passed to d2b" in debug * build. */ num1 = PR_strtod("4e-356",NULL); /* * A very long input with ~384K digits. * Bug 516396: Should not crash. * Bug 521306: Should return 0 without converting the input. */ #define LENGTH (384 * 1024) thousands = (char *)malloc(LENGTH); thousands[0] = '0'; thousands[1] = '.'; memset(&thousands[2], '1', LENGTH - 3); thousands[LENGTH - 1] = '\0'; num = 0; num1 = PR_strtod(thousands,NULL); free(thousands); if(num1 != num){ fprintf(stderr,"Failed to convert numeric value %s\n", "0.1111111111111111..."); failed_already = 1; } if (failed_already) { printf("FAILED\n"); } else { printf("PASSED\n"); } return failed_already; } nspr-4.11/nspr/pr/tests/env.c0000644000000000000000000002326312623070344014257 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: env.c ** Description: Testing environment variable operations ** */ #include "prenv.h" #include "prmem.h" #include "plgetopt.h" #include #include #include PRIntn debug = 0; PRIntn verbose = 0; PRBool failedAlready = PR_FALSE; #define ENVNAME "NSPR_ENVIRONMENT_TEST_VARIABLE" #define ENVVALUE "The expected result" #define ENVBUFSIZE 256 char *envBuf; /* buffer pointer. We leak memory here on purpose! */ static char * NewBuffer( size_t size ) { char *buf = malloc( size ); if ( NULL == buf ) { printf("env: NewBuffer() failed\n"); exit(1); } return(buf); } /* end NewBuffer() */ int main(int argc, char **argv) { char *value; PRStatus rc; { /* Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "vd"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; break; case 'v': /* verbose */ verbose = 1; break; default: break; } } PL_DestroyOptState(opt); } /* end block "Get command line options" */ #if 0 { /* ** This uses Windows native environment manipulation ** as an experiment. Note the separation of namespace! */ BOOL rv; DWORD size; rv = SetEnvironmentVariable( ENVNAME, ENVVALUE ); if ( rv == 0 ) { if (debug) printf("env: Shit! SetEnvironmentVariable() failed\n"); failedAlready = PR_TRUE; } if (verbose) printf("env: SetEnvironmentVariable() worked\n"); size = GetEnvironmentVariable( ENVNAME, envBuf, ENVBUFSIZE ); if ( size == 0 ) { if (debug) printf("env: Shit! GetEnvironmentVariable() failed. Found: %s\n", envBuf ); failedAlready = PR_TRUE; } if (verbose) printf("env: GetEnvironmentVariable() worked. Found: %s\n", envBuf); value = PR_GetEnv( ENVNAME ); if ( (NULL == value ) || (strcmp( value, ENVVALUE))) { if (debug) printf( "env: PR_GetEnv() failed retrieving WinNative. Found: %s\n", value); failedAlready = PR_TRUE; } if (verbose) printf("env: PR_GetEnv() worked. Found: %s\n", value); } #endif /* set an environment variable, read it back */ envBuf = NewBuffer( ENVBUFSIZE ); sprintf( envBuf, ENVNAME "=" ENVVALUE ); rc = PR_SetEnv( envBuf ); if ( PR_FAILURE == rc ) { if (debug) printf( "env: PR_SetEnv() failed setting\n"); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_SetEnv() worked.\n"); } value = PR_GetEnv( ENVNAME ); if ( (NULL == value ) || (strcmp( value, ENVVALUE))) { if (debug) printf( "env: PR_GetEnv() Failed after setting\n" ); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_GetEnv() worked after setting it. Found: %s\n", value ); } /* ---------------------------------------------------------------------- */ /* check that PR_DuplicateEnvironment() agrees with PR_GetEnv() */ { #if defined(XP_UNIX) && (!defined(DARWIN) || defined(HAVE_CRT_EXTERNS_H)) static const PRBool expect_failure = PR_FALSE; #else static const PRBool expect_failure = PR_TRUE; #endif char **i, **dupenv = PR_DuplicateEnvironment(); if ( NULL == dupenv ) { if (expect_failure) { if (verbose) printf("env: PR_DuplicateEnvironment failed, " "as expected on this platform.\n"); } else { if (debug) printf("env: PR_DuplicateEnvironment() failed.\n"); failedAlready = PR_TRUE; } } else { unsigned found = 0; if (expect_failure) { if (debug) printf("env: PR_DuplicateEnvironment() succeeded, " "but failure is expected on this platform.\n"); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_DuplicateEnvironment() succeeded.\n"); } for (i = dupenv; *i; i++) { char *equals = strchr(*i, '='); if ( equals == NULL ) { if (debug) printf("env: PR_DuplicateEnvironment() returned a string" " with no '=': %s\n", *i); failedAlready = PR_TRUE; } else { /* We own this string, so we can temporarily alter it */ /* *i is the null-terminated name; equals + 1 is the value */ *equals = '\0'; if ( strcmp(*i, ENVNAME) == 0) { found++; if (verbose) printf("env: PR_DuplicateEnvironment() found " ENVNAME " (%u so far).\n", found); } /* Multiple values for the same name can't happen, according to POSIX. */ value = PR_GetEnv(*i); if ( value == NULL ) { if (debug) printf("env: PR_DuplicateEnvironment() returned a name" " which PR_GetEnv() failed to find: %s\n", *i); failedAlready = PR_TRUE; } else if ( strcmp(equals + 1, value) != 0) { if (debug) printf("env: PR_DuplicateEnvironment() returned the wrong" " value for %s: expected %s; found %s\n", *i, value, equals + 1); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_DuplicateEnvironment() agreed with" " PR_GetEnv() about %s\n", *i); } } PR_Free(*i); } PR_Free(dupenv); if (found != 1) { if (debug) printf("env: PR_DuplicateEnvironment() found %u entries for " ENVNAME " (expected 1)\n", found); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_DuplicateEnvironment() found 1 entry for " ENVNAME "\n"); } } } /* ---------------------------------------------------------------------- */ /* un-set the variable, using RAW name... should not work */ envBuf = NewBuffer( ENVBUFSIZE ); sprintf( envBuf, ENVNAME ); rc = PR_SetEnv( envBuf ); if ( PR_FAILURE == rc ) { if (verbose) printf( "env: PR_SetEnv() not un-set using RAW name. Good!\n"); } else { if (debug) printf("env: PR_SetEnv() un-set using RAW name. Bad!\n" ); failedAlready = PR_TRUE; } value = PR_GetEnv( ENVNAME ); if ( NULL == value ) { if (debug) printf("env: PR_GetEnv() after un-set using RAW name. Bad!\n" ); failedAlready = PR_TRUE; } else { if (verbose) printf( "env: PR_GetEnv() after RAW un-set found: %s\n", value ); } /* ---------------------------------------------------------------------- */ /* set it again ... */ envBuf = NewBuffer( ENVBUFSIZE ); sprintf( envBuf, ENVNAME "=" ENVVALUE ); rc = PR_SetEnv( envBuf ); if ( PR_FAILURE == rc ) { if (debug) printf( "env: PR_SetEnv() failed setting the second time.\n"); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_SetEnv() worked.\n"); } /* un-set the variable using the form name= */ envBuf = NewBuffer( ENVBUFSIZE ); sprintf( envBuf, ENVNAME "=" ); rc = PR_SetEnv( envBuf ); if ( PR_FAILURE == rc ) { if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n"); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" ); } value = PR_GetEnv( ENVNAME ); if (( NULL == value ) || ( 0x00 == *value )) { if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" ); } else { if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value ); failedAlready = PR_TRUE; } /* ---------------------------------------------------------------------- */ /* un-set the variable using the form name= */ envBuf = NewBuffer( ENVBUFSIZE ); sprintf( envBuf, ENVNAME "999=" ); rc = PR_SetEnv( envBuf ); if ( PR_FAILURE == rc ) { if (debug) printf( "env: PR_SetEnv() failed un-setting using name=\n"); failedAlready = PR_TRUE; } else { if (verbose) printf("env: PR_SetEnv() un-set using name= worked\n" ); } value = PR_GetEnv( ENVNAME "999" ); if (( NULL == value ) || ( 0x00 == *value )) { if (verbose) printf("env: PR_GetEnv() after un-set using name= worked\n" ); } else { if (debug) printf( "env: PR_GetEnv() after un-set using name=. Found: %s\n", value ); failedAlready = PR_TRUE; } /* ---------------------------------------------------------------------- */ if (debug || verbose) printf("\n%s\n", (failedAlready)? "FAILED" : "PASSED" ); return( (failedAlready)? 1 : 0 ); } /* main() */ /* env.c */ nspr-4.11/nspr/pr/tests/errcodes.c0000644000000000000000000001250012623070344015265 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: errcodes.c ** ** Description: print nspr error codes ** */ #include "prerror.h" #include "plgetopt.h" #include static int _debug_on = 0; struct errinfo { PRErrorCode errcode; char *errname; }; struct errinfo errcodes[] = { {PR_OUT_OF_MEMORY_ERROR, "PR_OUT_OF_MEMORY_ERROR"}, {PR_BAD_DESCRIPTOR_ERROR, "PR_BAD_DESCRIPTOR_ERROR"}, {PR_WOULD_BLOCK_ERROR, "PR_WOULD_BLOCK_ERROR"}, {PR_ACCESS_FAULT_ERROR, "PR_ACCESS_FAULT_ERROR"}, {PR_INVALID_METHOD_ERROR, "PR_INVALID_METHOD_ERROR"}, {PR_ILLEGAL_ACCESS_ERROR, "PR_ILLEGAL_ACCESS_ERROR"}, {PR_UNKNOWN_ERROR, "PR_UNKNOWN_ERROR"}, {PR_PENDING_INTERRUPT_ERROR, "PR_PENDING_INTERRUPT_ERROR"}, {PR_NOT_IMPLEMENTED_ERROR, "PR_NOT_IMPLEMENTED_ERROR"}, {PR_IO_ERROR, "PR_IO_ERROR"}, {PR_IO_TIMEOUT_ERROR, "PR_IO_TIMEOUT_ERROR"}, {PR_IO_PENDING_ERROR, "PR_IO_PENDING_ERROR"}, {PR_DIRECTORY_OPEN_ERROR, "PR_DIRECTORY_OPEN_ERROR"}, {PR_INVALID_ARGUMENT_ERROR, "PR_INVALID_ARGUMENT_ERROR"}, {PR_ADDRESS_NOT_AVAILABLE_ERROR, "PR_ADDRESS_NOT_AVAILABLE_ERROR"}, {PR_ADDRESS_NOT_SUPPORTED_ERROR, "PR_ADDRESS_NOT_SUPPORTED_ERROR"}, {PR_IS_CONNECTED_ERROR, "PR_IS_CONNECTED_ERROR"}, {PR_BAD_ADDRESS_ERROR, "PR_BAD_ADDRESS_ERROR"}, {PR_ADDRESS_IN_USE_ERROR, "PR_ADDRESS_IN_USE_ERROR"}, {PR_CONNECT_REFUSED_ERROR, "PR_CONNECT_REFUSED_ERROR"}, {PR_NETWORK_UNREACHABLE_ERROR, "PR_NETWORK_UNREACHABLE_ERROR"}, {PR_CONNECT_TIMEOUT_ERROR, "PR_CONNECT_TIMEOUT_ERROR"}, {PR_NOT_CONNECTED_ERROR, "PR_NOT_CONNECTED_ERROR"}, {PR_LOAD_LIBRARY_ERROR, "PR_LOAD_LIBRARY_ERROR"}, {PR_UNLOAD_LIBRARY_ERROR, "PR_UNLOAD_LIBRARY_ERROR"}, {PR_FIND_SYMBOL_ERROR, "PR_FIND_SYMBOL_ERROR"}, {PR_INSUFFICIENT_RESOURCES_ERROR, "PR_INSUFFICIENT_RESOURCES_ERROR"}, {PR_DIRECTORY_LOOKUP_ERROR, "PR_DIRECTORY_LOOKUP_ERROR"}, {PR_TPD_RANGE_ERROR, "PR_TPD_RANGE_ERROR"}, {PR_PROC_DESC_TABLE_FULL_ERROR, "PR_PROC_DESC_TABLE_FULL_ERROR"}, {PR_SYS_DESC_TABLE_FULL_ERROR, "PR_SYS_DESC_TABLE_FULL_ERROR"}, {PR_NOT_SOCKET_ERROR, "PR_NOT_SOCKET_ERROR"}, {PR_NOT_TCP_SOCKET_ERROR, "PR_NOT_TCP_SOCKET_ERROR"}, {PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "PR_SOCKET_ADDRESS_IS_BOUND_ERROR"}, {PR_NO_ACCESS_RIGHTS_ERROR, "PR_NO_ACCESS_RIGHTS_ERROR"}, {PR_OPERATION_NOT_SUPPORTED_ERROR, "PR_OPERATION_NOT_SUPPORTED_ERROR"}, {PR_PROTOCOL_NOT_SUPPORTED_ERROR, "PR_PROTOCOL_NOT_SUPPORTED_ERROR"}, {PR_REMOTE_FILE_ERROR, "PR_REMOTE_FILE_ERROR"}, {PR_BUFFER_OVERFLOW_ERROR, "PR_BUFFER_OVERFLOW_ERROR"}, {PR_CONNECT_RESET_ERROR, "PR_CONNECT_RESET_ERROR"}, {PR_RANGE_ERROR, "PR_RANGE_ERROR"}, {PR_DEADLOCK_ERROR, "PR_DEADLOCK_ERROR"}, {PR_FILE_IS_LOCKED_ERROR, "PR_FILE_IS_LOCKED_ERROR"}, {PR_FILE_TOO_BIG_ERROR, "PR_FILE_TOO_BIG_ERROR"}, {PR_NO_DEVICE_SPACE_ERROR, "PR_NO_DEVICE_SPACE_ERROR"}, {PR_PIPE_ERROR, "PR_PIPE_ERROR"}, {PR_NO_SEEK_DEVICE_ERROR, "PR_NO_SEEK_DEVICE_ERROR"}, {PR_IS_DIRECTORY_ERROR, "PR_IS_DIRECTORY_ERROR"}, {PR_LOOP_ERROR, "PR_LOOP_ERROR"}, {PR_NAME_TOO_LONG_ERROR, "PR_NAME_TOO_LONG_ERROR"}, {PR_FILE_NOT_FOUND_ERROR, "PR_FILE_NOT_FOUND_ERROR"}, {PR_NOT_DIRECTORY_ERROR, "PR_NOT_DIRECTORY_ERROR"}, {PR_READ_ONLY_FILESYSTEM_ERROR, "PR_READ_ONLY_FILESYSTEM_ERROR"}, {PR_DIRECTORY_NOT_EMPTY_ERROR, "PR_DIRECTORY_NOT_EMPTY_ERROR"}, {PR_FILESYSTEM_MOUNTED_ERROR, "PR_FILESYSTEM_MOUNTED_ERROR"}, {PR_NOT_SAME_DEVICE_ERROR, "PR_NOT_SAME_DEVICE_ERROR"}, {PR_DIRECTORY_CORRUPTED_ERROR, "PR_DIRECTORY_CORRUPTED_ERROR"}, {PR_FILE_EXISTS_ERROR, "PR_FILE_EXISTS_ERROR"}, {PR_MAX_DIRECTORY_ENTRIES_ERROR, "PR_MAX_DIRECTORY_ENTRIES_ERROR"}, {PR_INVALID_DEVICE_STATE_ERROR, "PR_INVALID_DEVICE_STATE_ERROR"}, {PR_DEVICE_IS_LOCKED_ERROR, "PR_DEVICE_IS_LOCKED_ERROR"}, {PR_NO_MORE_FILES_ERROR, "PR_NO_MORE_FILES_ERROR"}, {PR_END_OF_FILE_ERROR, "PR_END_OF_FILE_ERROR"}, {PR_FILE_SEEK_ERROR, "PR_FILE_SEEK_ERROR"}, {PR_FILE_IS_BUSY_ERROR, "PR_FILE_IS_BUSY_ERROR"}, {PR_IN_PROGRESS_ERROR, "PR_IN_PROGRESS_ERROR"}, {PR_ALREADY_INITIATED_ERROR, "PR_ALREADY_INITIATED_ERROR"}, {PR_GROUP_EMPTY_ERROR, "PR_GROUP_EMPTY_ERROR"}, {PR_INVALID_STATE_ERROR, "PR_INVALID_STATE_ERROR"}, {PR_NETWORK_DOWN_ERROR, "PR_NETWORK_DOWN_ERROR"}, {PR_SOCKET_SHUTDOWN_ERROR, "PR_SOCKET_SHUTDOWN_ERROR"}, {PR_CONNECT_ABORTED_ERROR, "PR_CONNECT_ABORTED_ERROR"}, {PR_HOST_UNREACHABLE_ERROR, "PR_HOST_UNREACHABLE_ERROR"} }; int main(int argc, char **argv) { int count, errnum; /* * -d debug mode */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); count = sizeof(errcodes)/sizeof(errcodes[0]); printf("\nNumber of error codes = %d\n\n",count); for (errnum = 0; errnum < count; errnum++) { printf("%-40s = %d\n",errcodes[errnum].errname, errcodes[errnum].errcode); } return 0; } nspr-4.11/nspr/pr/tests/errset.c0000644000000000000000000001410112623070344014762 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: errset.c ** ** Description: errset.c exercises the functions in prerror.c. ** This code is a unit test of the prerror.c capability. ** ** Note: There's some fluff in here. The guts of the test ** were plagerized from another test. So, sue me. ** ** */ #include "prerror.h" #include "plgetopt.h" #include "prlog.h" #include #include static int _debug_on = 0; struct errinfo { PRErrorCode errcode; char *errname; }; struct errinfo errcodes[] = { {PR_OUT_OF_MEMORY_ERROR, "PR_OUT_OF_MEMORY_ERROR"}, {PR_UNKNOWN_ERROR, "An intentionally long error message text intended to force a delete of the current errorString buffer and get another one."}, {PR_BAD_DESCRIPTOR_ERROR, "PR_BAD_DESCRIPTOR_ERROR"}, {PR_WOULD_BLOCK_ERROR, "PR_WOULD_BLOCK_ERROR"}, {PR_ACCESS_FAULT_ERROR, "PR_ACCESS_FAULT_ERROR"}, {PR_INVALID_METHOD_ERROR, "PR_INVALID_METHOD_ERROR"}, {PR_ILLEGAL_ACCESS_ERROR, "PR_ILLEGAL_ACCESS_ERROR"}, {PR_UNKNOWN_ERROR, "PR_UNKNOWN_ERROR"}, {PR_PENDING_INTERRUPT_ERROR, "PR_PENDING_INTERRUPT_ERROR"}, {PR_NOT_IMPLEMENTED_ERROR, "PR_NOT_IMPLEMENTED_ERROR"}, {PR_IO_ERROR, "PR_IO_ERROR"}, {PR_IO_TIMEOUT_ERROR, "PR_IO_TIMEOUT_ERROR"}, {PR_IO_PENDING_ERROR, "PR_IO_PENDING_ERROR"}, {PR_DIRECTORY_OPEN_ERROR, "PR_DIRECTORY_OPEN_ERROR"}, {PR_INVALID_ARGUMENT_ERROR, "PR_INVALID_ARGUMENT_ERROR"}, {PR_ADDRESS_NOT_AVAILABLE_ERROR, "PR_ADDRESS_NOT_AVAILABLE_ERROR"}, {PR_ADDRESS_NOT_SUPPORTED_ERROR, "PR_ADDRESS_NOT_SUPPORTED_ERROR"}, {PR_IS_CONNECTED_ERROR, "PR_IS_CONNECTED_ERROR"}, {PR_BAD_ADDRESS_ERROR, "PR_BAD_ADDRESS_ERROR"}, {PR_ADDRESS_IN_USE_ERROR, "PR_ADDRESS_IN_USE_ERROR"}, {PR_CONNECT_REFUSED_ERROR, "PR_CONNECT_REFUSED_ERROR"}, {PR_NETWORK_UNREACHABLE_ERROR, "PR_NETWORK_UNREACHABLE_ERROR"}, {PR_CONNECT_TIMEOUT_ERROR, "PR_CONNECT_TIMEOUT_ERROR"}, {PR_NOT_CONNECTED_ERROR, "PR_NOT_CONNECTED_ERROR"}, {PR_LOAD_LIBRARY_ERROR, "PR_LOAD_LIBRARY_ERROR"}, {PR_UNLOAD_LIBRARY_ERROR, "PR_UNLOAD_LIBRARY_ERROR"}, {PR_FIND_SYMBOL_ERROR, "PR_FIND_SYMBOL_ERROR"}, {PR_INSUFFICIENT_RESOURCES_ERROR, "PR_INSUFFICIENT_RESOURCES_ERROR"}, {PR_DIRECTORY_LOOKUP_ERROR, "PR_DIRECTORY_LOOKUP_ERROR"}, {PR_TPD_RANGE_ERROR, "PR_TPD_RANGE_ERROR"}, {PR_PROC_DESC_TABLE_FULL_ERROR, "PR_PROC_DESC_TABLE_FULL_ERROR"}, {PR_SYS_DESC_TABLE_FULL_ERROR, "PR_SYS_DESC_TABLE_FULL_ERROR"}, {PR_NOT_SOCKET_ERROR, "PR_NOT_SOCKET_ERROR"}, {PR_NOT_TCP_SOCKET_ERROR, "PR_NOT_TCP_SOCKET_ERROR"}, {PR_SOCKET_ADDRESS_IS_BOUND_ERROR, "PR_SOCKET_ADDRESS_IS_BOUND_ERROR"}, {PR_NO_ACCESS_RIGHTS_ERROR, "PR_NO_ACCESS_RIGHTS_ERROR"}, {PR_OPERATION_NOT_SUPPORTED_ERROR, "PR_OPERATION_NOT_SUPPORTED_ERROR"}, {PR_PROTOCOL_NOT_SUPPORTED_ERROR, "PR_PROTOCOL_NOT_SUPPORTED_ERROR"}, {PR_REMOTE_FILE_ERROR, "PR_REMOTE_FILE_ERROR"}, {PR_BUFFER_OVERFLOW_ERROR, "PR_BUFFER_OVERFLOW_ERROR"}, {PR_CONNECT_RESET_ERROR, "PR_CONNECT_RESET_ERROR"}, {PR_RANGE_ERROR, "PR_RANGE_ERROR"}, {PR_DEADLOCK_ERROR, "PR_DEADLOCK_ERROR"}, {PR_FILE_IS_LOCKED_ERROR, "PR_FILE_IS_LOCKED_ERROR"}, {PR_FILE_TOO_BIG_ERROR, "PR_FILE_TOO_BIG_ERROR"}, {PR_NO_DEVICE_SPACE_ERROR, "PR_NO_DEVICE_SPACE_ERROR"}, {PR_PIPE_ERROR, "PR_PIPE_ERROR"}, {PR_NO_SEEK_DEVICE_ERROR, "PR_NO_SEEK_DEVICE_ERROR"}, {PR_IS_DIRECTORY_ERROR, "PR_IS_DIRECTORY_ERROR"}, {PR_LOOP_ERROR, "PR_LOOP_ERROR"}, {PR_NAME_TOO_LONG_ERROR, "PR_NAME_TOO_LONG_ERROR"}, {PR_FILE_NOT_FOUND_ERROR, "PR_FILE_NOT_FOUND_ERROR"}, {PR_NOT_DIRECTORY_ERROR, "PR_NOT_DIRECTORY_ERROR"}, {PR_READ_ONLY_FILESYSTEM_ERROR, "PR_READ_ONLY_FILESYSTEM_ERROR"}, {PR_DIRECTORY_NOT_EMPTY_ERROR, "PR_DIRECTORY_NOT_EMPTY_ERROR"}, {PR_FILESYSTEM_MOUNTED_ERROR, "PR_FILESYSTEM_MOUNTED_ERROR"}, {PR_NOT_SAME_DEVICE_ERROR, "PR_NOT_SAME_DEVICE_ERROR"}, {PR_DIRECTORY_CORRUPTED_ERROR, "PR_DIRECTORY_CORRUPTED_ERROR"}, {PR_FILE_EXISTS_ERROR, "PR_FILE_EXISTS_ERROR"}, {PR_MAX_DIRECTORY_ENTRIES_ERROR, "PR_MAX_DIRECTORY_ENTRIES_ERROR"}, {PR_INVALID_DEVICE_STATE_ERROR, "PR_INVALID_DEVICE_STATE_ERROR"}, {PR_DEVICE_IS_LOCKED_ERROR, "PR_DEVICE_IS_LOCKED_ERROR"}, {PR_NO_MORE_FILES_ERROR, "PR_NO_MORE_FILES_ERROR"}, {PR_END_OF_FILE_ERROR, "PR_END_OF_FILE_ERROR"}, {PR_FILE_SEEK_ERROR, "PR_FILE_SEEK_ERROR"}, {PR_FILE_IS_BUSY_ERROR, "PR_FILE_IS_BUSY_ERROR"}, {PR_IN_PROGRESS_ERROR, "PR_IN_PROGRESS_ERROR"}, {PR_ALREADY_INITIATED_ERROR, "PR_ALREADY_INITIATED_ERROR"}, {PR_GROUP_EMPTY_ERROR, "PR_GROUP_EMPTY_ERROR"}, {PR_INVALID_STATE_ERROR, "PR_INVALID_STATE_ERROR"}, {PR_NETWORK_DOWN_ERROR, "PR_NETWORK_DOWN_ERROR"}, {PR_SOCKET_SHUTDOWN_ERROR, "PR_SOCKET_SHUTDOWN_ERROR"}, {PR_CONNECT_ABORTED_ERROR, "PR_CONNECT_ABORTED_ERROR"}, {PR_HOST_UNREACHABLE_ERROR, "PR_HOST_UNREACHABLE_ERROR"} }; int main(int argc, char **argv) { int count, errnum; /* * -d debug mode */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); count = sizeof(errcodes)/sizeof(errcodes[0]); printf("\nNumber of error codes = %d\n\n",count); for (errnum = 0; errnum < count; errnum++) { PRInt32 len1, len2, err; char msg[256]; PR_SetError( errnum, -5 ); err = PR_GetError(); PR_ASSERT( err == errnum ); err = PR_GetOSError(); PR_ASSERT( err == -5 ); PR_SetErrorText( strlen(errcodes[errnum].errname), errcodes[errnum].errname ); len1 = PR_GetErrorTextLength(); len2 = PR_GetErrorText( msg ); PR_ASSERT( len1 == len2 ); printf("%5.5d -- %s\n", errnum, msg ); } return 0; } nspr-4.11/nspr/pr/tests/exit.c0000644000000000000000000000540512623070344014436 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prprf.h" #include "prinit.h" #include "prthread.h" #include "prproces.h" #include "prinrval.h" #include "plgetopt.h" #include static PRInt32 dally = 0; static PRFileDesc *err = NULL; static PRBool verbose = PR_FALSE, force = PR_FALSE; static void Help(void) { PR_fprintf(err, "Usage: [-t s] [-h]\n"); PR_fprintf(err, "\t-d Verbose output (default: FALSE)\n"); PR_fprintf(err, "\t-x Forced termination (default: FALSE)\n"); PR_fprintf(err, "\t-t Time for thread to block (default: 10 seconds)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ static void Dull(void *arg) { PR_Sleep(PR_SecondsToInterval(dally)); if (verbose && force) PR_fprintf(err, "If you see this, the test failed\n"); } /* Dull */ static PRIntn PR_CALLBACK RealMain(PRIntn argc, char **argv) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "ht:dx"); err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* verbosity */ verbose = PR_TRUE; break; case 'x': /* force exit */ force = PR_TRUE; break; case 't': /* seconds to dally in child */ dally = atoi(opt->value); break; case 'h': /* user wants some guidance */ default: Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); if (0 == dally) dally = 10; /* * Create LOCAL and GLOBAL threads */ (void)PR_CreateThread( PR_USER_THREAD, Dull, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); (void)PR_CreateThread( PR_USER_THREAD, Dull, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (verbose) PR_fprintf( err, "Main is exiting now. Program should exit %s.\n", (force) ? "immediately" : "after child dally time"); if (force) { PR_ProcessExit(0); if (verbose) { PR_fprintf(err, "You should not have gotten here.\n"); return 1; } } return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/fdcach.c0000644000000000000000000001351012623070344014671 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: fdcach.c * Description: * This test verifies that the fd cache and stack are working * correctly. */ #include "nspr.h" #include #include /* * Define ORDER_PRESERVED if the implementation of PR_SetFDCacheSize * preserves the ordering of the fd's when moving them between the * cache and the stack. */ #define ORDER_PRESERVED 1 /* * NUM_FDS must be <= FD_CACHE_SIZE. */ #define FD_CACHE_SIZE 1024 #define NUM_FDS 20 int main(int argc, char **argv) { int i; PRFileDesc *fds[NUM_FDS]; PRFileDesc *savefds[NUM_FDS]; int numfds = sizeof(fds)/sizeof(fds[0]); /* * Switch between cache and stack when they are empty. * Then start with the fd cache. */ PR_SetFDCacheSize(0, FD_CACHE_SIZE); PR_SetFDCacheSize(0, 0); PR_SetFDCacheSize(0, FD_CACHE_SIZE); /* Add some fd's to the fd cache. */ for (i = 0; i < numfds; i++) { savefds[i] = PR_NewTCPSocket(); if (NULL == savefds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } } for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } /* * Create some fd's. These fd's should come from * the fd cache. Verify the FIFO ordering of the fd * cache. */ for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (fds[i] != savefds[i]) { fprintf(stderr, "fd cache malfunctioned\n"); exit(1); } } /* Put the fd's back to the fd cache. */ for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } /* Switch to the fd stack. */ PR_SetFDCacheSize(0, 0); /* * Create some fd's. These fd's should come from * the fd stack. */ for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } #ifdef ORDER_PRESERVED if (fds[i] != savefds[numfds-1-i]) { fprintf(stderr, "fd stack malfunctioned\n"); exit(1); } #else savefds[numfds-1-i] = fds[i]; #endif } /* Put the fd's back to the fd stack. */ for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } /* * Now create some fd's and verify the LIFO ordering of * the fd stack. */ for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (fds[i] != savefds[numfds-1-i]) { fprintf(stderr, "fd stack malfunctioned\n"); exit(1); } } /* Put the fd's back to the fd stack. */ for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } /* Switch to the fd cache. */ PR_SetFDCacheSize(0, FD_CACHE_SIZE); for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } #ifdef ORDER_PRESERVED if (fds[i] != savefds[i]) { fprintf(stderr, "fd cache malfunctioned\n"); exit(1); } #else savefds[i] = fds[i]; #endif } for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (fds[i] != savefds[i]) { fprintf(stderr, "fd cache malfunctioned\n"); exit(1); } } for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } /* Switch to the fd stack. */ PR_SetFDCacheSize(0, 0); for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } #ifdef ORDER_PRESERVED if (fds[i] != savefds[numfds-1-i]) { fprintf(stderr, "fd stack malfunctioned\n"); exit(1); } #else savefds[numfds-1-i]; #endif } for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } for (i = 0; i < numfds; i++) { fds[i] = PR_NewTCPSocket(); if (NULL == fds[i]) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (fds[i] != savefds[numfds-1-i]) { fprintf(stderr, "fd stack malfunctioned\n"); exit(1); } } for (i = 0; i < numfds; i++) { if (PR_Close(savefds[i]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } PR_Cleanup(); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/fileio.c0000644000000000000000000001146512623070344014737 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: fileio.c ** ** Description: Program to copy one file to another. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 Revert to return code 0 and 1, remove debug option (obsolete). ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ #include "prinit.h" #include "prthread.h" #include "prlock.h" #include "prcvar.h" #include "prmon.h" #include "prmem.h" #include "prio.h" #include "prlog.h" #include #include "obsolete/prsem.h" #define TBSIZE 1024 static PRUint8 tbuf[TBSIZE]; static PRFileDesc *t1, *t2; PRIntn failed_already=0; PRIntn debug_mode; static void InitialSetup(void) { PRUintn i; PRInt32 nWritten, rv; t1 = PR_Open("t1.tmp", PR_CREATE_FILE | PR_RDWR, 0); PR_ASSERT(t1 != NULL); for (i=0; i= 0) { buf[i].nbytes = nbytes; PR_PostSem(fullBufs); i = (i + 1) % 2; } } while (nbytes > 0); } static void PR_CALLBACK writer(void *arg) { PRUintn i = 0; PRInt32 nbytes; do { (void) PR_WaitSem(fullBufs); nbytes = buf[i].nbytes; if (nbytes > 0) { nbytes = PR_Write((PRFileDesc*)arg, buf[i].data, nbytes); PR_PostSem(emptyBufs); i = (i + 1) % 2; } } while (nbytes > 0); } int main(int argc, char **argv) { PRThread *r, *w; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); emptyBufs = PR_NewSem(2); /* two empty buffers */ fullBufs = PR_NewSem(0); /* zero full buffers */ /* Create initial temp file setup */ InitialSetup(); /* create the reader thread */ r = PR_CreateThread(PR_USER_THREAD, reader, t1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); w = PR_CreateThread(PR_USER_THREAD, writer, t2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); /* Do the joining for both threads */ (void) PR_JoinThread(r); (void) PR_JoinThread(w); /* Do the verification and clean up */ VerifyAndCleanup(); PR_DestroySem(emptyBufs); PR_DestroySem(fullBufs); PR_Cleanup(); if(failed_already) { printf("Fail\n"); return 1; } else { printf("PASS\n"); return 0; } } nspr-4.11/nspr/pr/tests/foreign.c0000644000000000000000000002300412623070344015111 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: foreign.c ** Description: Testing various functions w/ foreign threads ** ** We create a thread and get it to call exactly one runtime function. ** The thread is allowed to be created by some other environment that ** NSPR, but it does not announce itself to the runtime prior to calling ** in. ** ** The goal: try to survive. ** */ #include "prcvar.h" #include "prenv.h" #include "prerror.h" #include "prinit.h" #include "prinrval.h" #include "prio.h" #include "prlock.h" #include "prlog.h" #include "prmem.h" #include "prthread.h" #include "prtypes.h" #include "prprf.h" #include "plgetopt.h" #include #include static enum { thread_nspr, thread_pthread, thread_sproc, thread_win32 } thread_provider; typedef void (*StartFn)(void*); typedef struct StartObject { StartFn start; void *arg; } StartObject; static PRFileDesc *output; static int _debug_on = 0; #define DEFAULT_THREAD_COUNT 10 #define DPRINTF(arg) if (_debug_on) PR_fprintf arg #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include #include "md/_pth.h" static void *pthread_start(void *arg) { StartFn start = ((StartObject*)arg)->start; void *data = ((StartObject*)arg)->arg; PR_Free(arg); start(data); return NULL; } /* pthread_start */ #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ #if defined(IRIX) && !defined(_PR_PTHREADS) #include #include static void sproc_start(void *arg, PRSize size) { StartObject *so = (StartObject*)arg; StartFn start = so->start; void *data = so->arg; PR_Free(so); start(data); } /* sproc_start */ #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */ #if defined(WIN32) #include #include /* for _beginthreadex() */ static PRUintn __stdcall windows_start(void *arg) { StartObject *so = (StartObject*)arg; StartFn start = so->start; void *data = so->arg; PR_Free(so); start(data); return 0; } /* windows_start */ #endif /* defined(WIN32) */ static PRStatus NSPRPUB_TESTS_CreateThread(StartFn start, void *arg) { PRStatus rv; switch (thread_provider) { case thread_nspr: { PRThread *thread = PR_CreateThread( PR_USER_THREAD, start, arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS; } break; case thread_pthread: #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) { int rv; pthread_t id; pthread_attr_t tattr; StartObject *start_object; start_object = PR_NEW(StartObject); PR_ASSERT(NULL != start_object); start_object->start = start; start_object->arg = arg; rv = _PT_PTHREAD_ATTR_INIT(&tattr); PR_ASSERT(0 == rv); rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); PR_ASSERT(0 == rv); rv = pthread_attr_setstacksize(&tattr, 64 * 1024); PR_ASSERT(0 == rv); rv = _PT_PTHREAD_CREATE(&id, tattr, pthread_start, start_object); (void)_PT_PTHREAD_ATTR_DESTROY(&tattr); return (0 == rv) ? PR_SUCCESS : PR_FAILURE; } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; break; #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ case thread_sproc: #if defined(IRIX) && !defined(_PR_PTHREADS) { PRInt32 pid; StartObject *start_object; start_object = PR_NEW(StartObject); PR_ASSERT(NULL != start_object); start_object->start = start; start_object->arg = arg; pid = sprocsp( sproc_start, PR_SALL, start_object, NULL, 64 * 1024); rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE; } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */ break; case thread_win32: #if defined(WIN32) { void *th; PRUintn id; StartObject *start_object; start_object = PR_NEW(StartObject); PR_ASSERT(NULL != start_object); start_object->start = start; start_object->arg = arg; th = (void*)_beginthreadex( NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */ 0U, /* DWORD - initial thread stack size, in bytes */ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */ start_object, /* LPVOID - argument for new thread */ STACK_SIZE_PARAM_IS_A_RESERVATION, /*DWORD dwCreationFlags - creation flags */ &id /* LPDWORD - pointer to returned thread identifier */ ); rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS; } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; #endif break; default: PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; } return rv; } /* NSPRPUB_TESTS_CreateThread */ static void PR_CALLBACK lazyEntry(void *arg) { PR_ASSERT(NULL == arg); } /* lazyEntry */ static void OneShot(void *arg) { PRUintn pdkey; PRLock *lock; PRFileDesc *fd; PRDir *dir; PRFileDesc *pair[2]; PRIntn test = (PRIntn)arg; for (test = 0; test < 12; ++test) { switch (test) { case 0: lock = PR_NewLock(); DPRINTF((output,"Thread[0x%x] called PR_NewLock\n", PR_GetCurrentThread())); PR_DestroyLock(lock); break; case 1: (void)PR_SecondsToInterval(1); DPRINTF((output,"Thread[0x%x] called PR_SecondsToInterval\n", PR_GetCurrentThread())); break; case 2: (void)PR_CreateThread( PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); DPRINTF((output,"Thread[0x%x] called PR_CreateThread\n", PR_GetCurrentThread())); break; case 3: fd = PR_Open("foreign.tmp", PR_CREATE_FILE | PR_RDWR, 0666); DPRINTF((output,"Thread[0x%x] called PR_Open\n", PR_GetCurrentThread())); PR_Close(fd); break; case 4: fd = PR_NewUDPSocket(); DPRINTF((output,"Thread[0x%x] called PR_NewUDPSocket\n", PR_GetCurrentThread())); PR_Close(fd); break; case 5: fd = PR_NewTCPSocket(); DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocket\n", PR_GetCurrentThread())); PR_Close(fd); break; case 6: #ifdef SYMBIAN #define TEMP_DIR "c:\\data\\" #else #define TEMP_DIR "/tmp/" #endif dir = PR_OpenDir(TEMP_DIR); DPRINTF((output,"Thread[0x%x] called PR_OpenDir\n", PR_GetCurrentThread())); PR_CloseDir(dir); break; case 7: (void)PR_NewThreadPrivateIndex(&pdkey, NULL); DPRINTF((output,"Thread[0x%x] called PR_NewThreadPrivateIndex\n", PR_GetCurrentThread())); break; case 8: (void)PR_GetEnv("PATH"); DPRINTF((output,"Thread[0x%x] called PR_GetEnv\n", PR_GetCurrentThread())); break; case 9: (void)PR_NewTCPSocketPair(pair); DPRINTF((output,"Thread[0x%x] called PR_NewTCPSocketPair\n", PR_GetCurrentThread())); PR_Close(pair[0]); PR_Close(pair[1]); break; case 10: PR_SetConcurrency(2); DPRINTF((output,"Thread[0x%x] called PR_SetConcurrency\n", PR_GetCurrentThread())); break; case 11: PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_HIGH); DPRINTF((output,"Thread[0x%x] called PR_SetThreadPriority\n", PR_GetCurrentThread())); break; default: break; } /* switch() */ } } /* OneShot */ int main(int argc, char **argv) { PRStatus rv; PRInt32 thread_cnt = DEFAULT_THREAD_COUNT; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dt:"); #if defined(WIN32) thread_provider = thread_win32; #elif defined(_PR_PTHREADS) thread_provider = thread_pthread; #elif defined(IRIX) thread_provider = thread_sproc; #else thread_provider = thread_nspr; #endif while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; case 't': /* thread count */ thread_cnt = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_SetConcurrency(2); output = PR_GetSpecialFD(PR_StandardOutput); while (thread_cnt-- > 0) { rv = NSPRPUB_TESTS_CreateThread(OneShot, (void*)thread_cnt); PR_ASSERT(PR_SUCCESS == rv); PR_Sleep(PR_MillisecondsToInterval(5)); } PR_Sleep(PR_SecondsToInterval(3)); return (PR_SUCCESS == PR_Cleanup()) ? 0 : 1; } /* main */ /* foreign.c */ nspr-4.11/nspr/pr/tests/forktest.c0000644000000000000000000002016512623070344015326 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: forktest.c ** ** Description: UNIX test for fork functions. ** ** Modification History: ** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** 12-June-97 AGarcic - Revert to return code 0 and 1, remove debug option (obsolete). ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include #include #include PRIntn failed_already=0; #ifdef XP_UNIX #include #include #include #include static char *message = "Hello world!"; static void ClientThreadFunc(void *arg) { PRNetAddr addr; PRFileDesc *sock = NULL; PRInt32 tmp = (PRInt32)arg; /* * Make sure the PR_Accept call will block */ printf("Wait one second before connect\n"); fflush(stdout); PR_Sleep(PR_SecondsToInterval(1)); addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = 0; if ((sock = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "failed to create TCP socket: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } if (PR_Bind(sock, &addr) != PR_SUCCESS) { fprintf(stderr, "PR_Bind failed: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } addr.inet.ip = PR_htonl(INADDR_LOOPBACK); addr.inet.port = PR_htons((PRInt16)tmp); printf("Connecting to port %hu\n", PR_ntohs(addr.inet.port)); fflush(stdout); if (PR_Connect(sock, &addr, PR_SecondsToInterval(5)) != PR_SUCCESS) { fprintf(stderr, "PR_Connect failed: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } printf("Writing message \"%s\"\n", message); fflush(stdout); if (PR_Send(sock, message, strlen(message) + 1, 0, PR_INTERVAL_NO_TIMEOUT) == -1) { fprintf(stderr, "PR_Send failed: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } finish: if (sock) { PR_Close(sock); } return; } /* * DoIO -- * This function creates a thread that acts as a client and itself. * acts as a server. Then it joins the client thread. */ static void DoIO(void) { PRThread *clientThread; PRFileDesc *listenSock = NULL; PRFileDesc *sock = NULL; PRNetAddr addr; PRInt32 nBytes; char buf[128]; listenSock = PR_NewTCPSocket(); if (!listenSock) { fprintf(stderr, "failed to create a TCP socket: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = 0; if (PR_Bind(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "failed to bind socket: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "failed to get socket port number: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } if (PR_Listen(listenSock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, (void *) PR_ntohs(addr.inet.port), PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "Cannot create client thread: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already = 1; goto finish; } printf("Accepting connection at port %hu\n", PR_ntohs(addr.inet.port)); fflush(stdout); sock = PR_Accept(listenSock, &addr, PR_SecondsToInterval(5)); if (!sock) { fprintf(stderr, "PR_Accept failed: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } nBytes = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (nBytes == -1) { fprintf(stderr, "PR_Recv failed: error code %d\n", PR_GetError()); failed_already = 1; goto finish; } /* * Make sure it has proper null byte to mark end of string */ buf[sizeof(buf) - 1] = '\0'; printf("Received \"%s\" from the client\n", buf); fflush(stdout); if (!strcmp(buf, message)) { PR_JoinThread(clientThread); printf("The message is received correctly\n"); fflush(stdout); } else { fprintf(stderr, "The message should be \"%s\"\n", message); failed_already = 1; } finish: if (listenSock) { PR_Close(listenSock); } if (sock) { PR_Close(sock); } return; } #ifdef _PR_DCETHREADS #include pid_t PR_UnixFork1(void) { pid_t parent = getpid(); int rv = syscall(SYS_fork); if (rv == -1) { return (pid_t) -1; } else { /* For each process, rv is the pid of the other process */ if (rv == parent) { /* the child */ return 0; } else { /* the parent */ return rv; } } } #elif defined(SOLARIS) /* * It seems like that in Solaris 2.4 one must call fork1() if the * the child process is going to use thread functions. Solaris 2.5 * doesn't have this problem. Calling fork() also works. */ pid_t PR_UnixFork1(void) { return fork1(); } #else pid_t PR_UnixFork1(void) { return fork(); } #endif /* PR_DCETHREADS */ int main(int argc, char **argv) { pid_t pid; int rv; /* main test program */ DoIO(); pid = PR_UnixFork1(); if (pid == (pid_t) -1) { fprintf(stderr, "Fork failed: errno %d\n", errno); failed_already=1; return 1; } else if (pid > 0) { int childStatus; printf("Fork succeeded. Parent process continues.\n"); DoIO(); if ((rv = waitpid(pid, &childStatus, 0)) != pid) { #if defined(IRIX) && !defined(_PR_PTHREADS) /* * nspr may handle SIGCLD signal */ if ((rv < 0) && (errno == ECHILD)) { } else #endif { fprintf(stderr, "waitpid failed: %d\n", errno); failed_already = 1; } } else if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0) { failed_already = 1; } printf("Parent process exits.\n"); if (!failed_already) { printf("PASSED\n"); } else { printf("FAILED\n"); } return failed_already; } else { #if defined(IRIX) && !defined(_PR_PTHREADS) extern void _PR_IRIX_CHILD_PROCESS(void); _PR_IRIX_CHILD_PROCESS(); #endif printf("Fork succeeded. Child process continues.\n"); DoIO(); printf("Child process exits.\n"); return failed_already; } } #else /* XP_UNIX */ int main( int argc, char *argv[] ) { printf("The fork test is applicable to Unix only.\n"); return 0; } #endif /* XP_UNIX */ nspr-4.11/nspr/pr/tests/formattm.c0000644000000000000000000000272512623070344015320 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* A test program for PR_FormatTime and PR_FormatTimeUSEnglish */ #include "prtime.h" #include int main(int argc, char **argv) { char buffer[256]; char small_buffer[8]; PRTime now; PRExplodedTime tod; now = PR_Now(); PR_ExplodeTime(now, PR_LocalTimeParameters, &tod); if (PR_FormatTime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Z %Y", &tod) != 0) { printf("%s\n", buffer); } else { fprintf(stderr, "PR_FormatTime(buffer) failed\n"); return 1; } small_buffer[0] = '?'; if (PR_FormatTime(small_buffer, sizeof(small_buffer), "%a %b %d %H:%M:%S %Z %Y", &tod) == 0) { if (small_buffer[0] != '\0') { fprintf(stderr, "PR_FormatTime(small_buffer) did not output " "an empty string on failure\n"); return 1; } printf("%s\n", small_buffer); } else { fprintf(stderr, "PR_FormatTime(small_buffer) succeeded " "unexpectedly\n"); return 1; } (void)PR_FormatTimeUSEnglish(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Z %Y", &tod); printf("%s\n", buffer); return 0; } nspr-4.11/nspr/pr/tests/freeif.c0000644000000000000000000000164112623070344014723 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A test to see if the macros PR_DELETE and PR_FREEIF are * properly defined. (See Bugzilla bug #39110.) */ #include "nspr.h" #include #include static void Noop(void) { } static void Fail(void) { printf("FAIL\n"); exit(1); } int main(int argc, char **argv) { int foo = 1; char *ptr = NULL; /* this fails to compile with the old definition of PR_DELETE */ if (foo) PR_DELETE(ptr); else Noop(); /* this nests incorrectly with the old definition of PR_FREEIF */ if (foo) PR_FREEIF(ptr); else Fail(); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/fsync.c0000644000000000000000000000721612623070344014611 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prmem.h" #include "prprf.h" #include "prinrval.h" #include "plerror.h" #include "plgetopt.h" static PRFileDesc *err = NULL; static void Help(void) { PR_fprintf(err, "Usage: [-S] [-K ] [-h] \n"); PR_fprintf(err, "\t-c Nuber of iterations (default: 10)\n"); PR_fprintf(err, "\t-S Sync the file (default: FALSE)\n"); PR_fprintf(err, "\t-K Size of file (K bytes) (default: 10)\n"); PR_fprintf(err, "\t Name of file to write (default: /usr/tmp/sync.dat)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ int main(int argc, char **argv) { PRStatus rv; PLOptStatus os; PRUint8 *buffer; PRFileDesc *file = NULL; const char *filename = "sync.dat"; PRUint32 index, loops, iterations = 10, filesize = 10; PRIntn flags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE; PLOptState *opt = PL_CreateOptState(argc, argv, "hSK:c:"); PRIntervalTime time, total = 0, shortest = 0x7fffffff, longest = 0; err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* Name of file to create */ filename = opt->value; break; case 'S': /* Use sych option on file */ flags |= PR_SYNC; break; case 'K': /* Size of file to write */ filesize = atoi(opt->value); break; case 'c': /* Number of iterations */ iterations = atoi(opt->value); break; case 'h': /* user wants some guidance */ default: /* user needs some guidance */ Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); file = PR_Open(filename, flags, 0666); if (NULL == file) { PL_FPrintError(err, "Failed to open file"); return 1; } buffer = (PRUint8*)PR_CALLOC(1024); if (NULL == buffer) { PL_FPrintError(err, "Cannot allocate buffer"); return 1; } for (index = 0; index < sizeof(buffer); ++index) buffer[index] = (PRUint8)index; for (loops = 0; loops < iterations; ++loops) { time = PR_IntervalNow(); for (index = 0; index < filesize; ++index) { PR_Write(file, buffer, 1024); } time = (PR_IntervalNow() - time); total += time; if (time < shortest) shortest = time; else if (time > longest) longest = time; if (0 != PR_Seek(file, 0, PR_SEEK_SET)) { PL_FPrintError(err, "Rewinding file"); return 1; } } total = total / iterations; PR_fprintf( err, "%u iterations over a %u kbyte %sfile: %u [%u] %u\n", iterations, filesize, ((flags & PR_SYNC) ? "SYNCH'd " : ""), PR_IntervalToMicroseconds(shortest), PR_IntervalToMicroseconds(total), PR_IntervalToMicroseconds(longest)); PR_DELETE(buffer); rv = PR_Close(file); if (PR_SUCCESS != rv) { PL_FPrintError(err, "Closing file failed"); return 1; } rv = PR_Delete(filename); if (PR_SUCCESS != rv) { PL_FPrintError(err, "Deleting file failed"); return 1; } return 0; } nspr-4.11/nspr/pr/tests/getai.c0000644000000000000000000000167612623070344014564 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include #include int main(int argc, char **argv) { PRAddrInfo *ai; void *iter; PRNetAddr addr; ai = PR_GetAddrInfoByName(argv[1], PR_AF_UNSPEC, PR_AI_ADDRCONFIG); if (ai == NULL) { fprintf(stderr, "PR_GetAddrInfoByName failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("%s\n", PR_GetCanonNameFromAddrInfo(ai)); iter = NULL; while ((iter = PR_EnumerateAddrInfo(iter, ai, 0, &addr)) != NULL) { char buf[128]; PR_NetAddrToString(&addr, buf, sizeof buf); printf("%s\n", buf); } PR_FreeAddrInfo(ai); return 0; } nspr-4.11/nspr/pr/tests/gethost.c0000644000000000000000000001751012623070344015142 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: gethost.c * * Description: tests various functions in prnetdb.h * * Usage: gethost [-6] [hostname] */ #include "prio.h" #include "prnetdb.h" #include "plgetopt.h" #include #include #define DEFAULT_HOST_NAME "mcom.com" static void Help(void) { fprintf(stderr, "Usage: gethost [-h] [hostname]\n"); fprintf(stderr, "\t-h help\n"); fprintf(stderr, "\thostname Name of host (default: %s)\n", DEFAULT_HOST_NAME); } /* Help */ /* * Prints the contents of a PRHostEnt structure */ void PrintHostent(const PRHostEnt *he) { int i; int j; printf("h_name: %s\n", he->h_name); for (i = 0; he->h_aliases[i]; i++) { printf("h_aliases[%d]: %s\n", i, he->h_aliases[i]); } printf("h_addrtype: %d\n", he->h_addrtype); printf("h_length: %d\n", he->h_length); for (i = 0; he->h_addr_list[i]; i++) { printf("h_addr_list[%d]: ", i); for (j = 0; j < he->h_length; j++) { if (j != 0) printf("."); printf("%u", (unsigned char)he->h_addr_list[i][j]); } printf("\n"); } } int main(int argc, char **argv) { const char *hostName = DEFAULT_HOST_NAME; PRHostEnt he, reversehe; char buf[PR_NETDB_BUF_SIZE]; char reversebuf[PR_NETDB_BUF_SIZE]; PRIntn idx; PRNetAddr addr; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "h"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* naked */ hostName = opt->value; break; case 'h': /* Help message */ default: Help(); return 2; } } PL_DestroyOptState(opt); if (PR_GetHostByName(hostName, buf, sizeof(buf), &he) == PR_FAILURE) { fprintf(stderr, "PR_GetHostByName failed\n"); exit(1); } PrintHostent(&he); idx = 0; while (1) { idx = PR_EnumerateHostEnt(idx, &he, 0, &addr); if (idx == -1) { fprintf(stderr, "PR_EnumerateHostEnt failed\n"); exit(1); } if (idx == 0) break; /* normal loop termination */ printf("reverse lookup\n"); if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf), &reversehe) == PR_FAILURE) { fprintf(stderr, "PR_GetHostByAddr failed\n"); exit(1); } PrintHostent(&reversehe); } printf("PR_GetIPNodeByName with PR_AF_INET\n"); if (PR_GetIPNodeByName(hostName, PR_AF_INET, PR_AI_DEFAULT, buf, sizeof(buf), &he) == PR_FAILURE) { fprintf(stderr, "PR_GetIPNodeByName failed\n"); exit(1); } PrintHostent(&he); printf("PR_GetIPNodeByName with PR_AF_INET6\n"); if (PR_GetIPNodeByName(hostName, PR_AF_INET6, PR_AI_DEFAULT, buf, sizeof(buf), &he) == PR_FAILURE) { fprintf(stderr, "PR_GetIPNodeByName failed\n"); exit(1); } PrintHostent(&he); idx = 0; printf("PR_GetHostByAddr with PR_AF_INET6\n"); while (1) { idx = PR_EnumerateHostEnt(idx, &he, 0, &addr); if (idx == -1) { fprintf(stderr, "PR_EnumerateHostEnt failed\n"); exit(1); } if (idx == 0) break; /* normal loop termination */ printf("reverse lookup\n"); if (PR_GetHostByAddr(&addr, reversebuf, sizeof(reversebuf), &reversehe) == PR_FAILURE) { fprintf(stderr, "PR_GetHostByAddr failed\n"); exit(1); } PrintHostent(&reversehe); } printf("PR_GetHostByAddr with PR_AF_INET6 done\n"); PR_StringToNetAddr("::1", &addr); if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_TRUE) { fprintf(stderr, "addr should not be ipv4 mapped address\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } PR_StringToNetAddr("127.0.0.1", &addr); if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } PR_StringToNetAddr("::FFFF:127.0.0.1", &addr); if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_FALSE) { fprintf(stderr, "addr should be ipv4 mapped address\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) { fprintf(stderr, "addr should be unspecified address\n"); exit(1); } if (PR_InitializeNetAddr(PR_IpAddrLoopback, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) { fprintf(stderr, "addr should be unspecified address\n"); exit(1); } if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_ANY); if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) { fprintf(stderr, "addr should be unspecified address\n"); exit(1); } { char buf[256]; PR_NetAddrToString(&addr, buf, 256); printf("IPv4 INADDRANY: %s\n", buf); } addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } { char buf[256]; PR_NetAddrToString(&addr, buf, 256); printf("IPv4 LOOPBACK: %s\n", buf); } if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) { fprintf(stderr, "addr should be unspecified address\n"); exit(1); } { char buf[256]; PR_NetAddrToString(&addr, buf, 256); printf("IPv6 INADDRANY: %s\n", buf); } if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) { fprintf(stderr, "addr should be loopback address\n"); exit(1); } { char buf[256]; PR_NetAddrToString(&addr, buf, 256); printf("IPv6 LOOPBACK: %s\n", buf); } { PRIPv6Addr v6addr; char tmp_buf[256]; PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET, 0, &addr); PR_ConvertIPv4AddrToIPv6(addr.inet.ip, &v6addr); PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr); addr.ipv6.ip = v6addr; PR_NetAddrToString(&addr, tmp_buf, 256); printf("IPv4-mapped IPv6 LOOPBACK: %s\n", tmp_buf); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/getproto.c0000644000000000000000000000520312623070344015324 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ************************************************************************* * * File: getproto.c * * A test program for PR_GetProtoByName and PR_GetProtoByNumber * ************************************************************************* */ #include "plstr.h" #include "plerror.h" #include "prinit.h" #include "prprf.h" #include "prnetdb.h" #include "prerror.h" int main(int argc, char **argv) { PRFileDesc *prstderr = PR_GetSpecialFD(PR_StandardError); PRBool failed = PR_FALSE; PRProtoEnt proto; char buf[2048]; PRStatus rv; PR_STDIO_INIT(); rv = PR_GetProtoByName("tcp", buf, sizeof(buf), &proto); if (PR_FAILURE == rv) { failed = PR_TRUE; PL_FPrintError(prstderr, "PR_GetProtoByName failed"); } else if (6 != proto.p_num) { PR_fprintf( prstderr,"tcp is usually 6, but is %d on this machine\n", proto.p_num); } else PR_fprintf(prstderr, "tcp is protocol number %d\n", proto.p_num); rv = PR_GetProtoByName("udp", buf, sizeof(buf), &proto); if (PR_FAILURE == rv) { failed = PR_TRUE; PL_FPrintError(prstderr, "PR_GetProtoByName failed"); } else if (17 != proto.p_num) { PR_fprintf( prstderr, "udp is usually 17, but is %d on this machine\n", proto.p_num); } else PR_fprintf(prstderr, "udp is protocol number %d\n", proto.p_num); rv = PR_GetProtoByNumber(6, buf, sizeof(buf), &proto); if (PR_FAILURE == rv) { failed = PR_TRUE; PL_FPrintError(prstderr, "PR_GetProtoByNumber failed"); } else if (PL_strcmp("tcp", proto.p_name)) { PR_fprintf( prstderr, "Protocol number 6 is usually tcp, but is %s" " on this platform\n", proto.p_name); } else PR_fprintf(prstderr, "Protocol number 6 is %s\n", proto.p_name); rv = PR_GetProtoByNumber(17, buf, sizeof(buf), &proto); if (PR_FAILURE == rv) { failed = PR_TRUE; PL_FPrintError(prstderr, "PR_GetProtoByNumber failed"); } else if (PL_strcmp("udp", proto.p_name)) { PR_fprintf( prstderr, "Protocol number 17 is usually udp, but is %s" " on this platform\n", proto.p_name); } else PR_fprintf(prstderr, "Protocol number 17 is %s\n", proto.p_name); PR_fprintf(prstderr, (failed) ? "FAILED\n" : "PASSED\n"); return (failed) ? 1 : 0; } nspr-4.11/nspr/pr/tests/i2l.c0000644000000000000000000000454712623070344014161 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "prio.h" #include "prinit.h" #include "prprf.h" #include "prlong.h" #include "plerror.h" #include "plgetopt.h" typedef union Overlay_i { PRInt32 i; PRInt64 l; } Overlay_i; typedef union Overlay_u { PRUint32 i; PRUint64 l; } Overlay_u; static PRFileDesc *err = NULL; static void Help(void) { PR_fprintf(err, "Usage: -i n | -u n | -h\n"); PR_fprintf(err, "\t-i n treat following number as signed integer\n"); PR_fprintf(err, "\t-u n treat following number as unsigned integer\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ static PRIntn PR_CALLBACK RealMain(PRIntn argc, char **argv) { Overlay_i si; Overlay_u ui; PLOptStatus os; PRBool bsi = PR_FALSE, bui = PR_FALSE; PLOptState *opt = PL_CreateOptState(argc, argv, "hi:u:"); err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'i': /* signed integer */ si.i = (PRInt32)atoi(opt->value); bsi = PR_TRUE; break; case 'u': /* unsigned */ ui.i = (PRUint32)atoi(opt->value); bui = PR_TRUE; break; case 'h': /* user wants some guidance */ default: Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); #if defined(HAVE_LONG_LONG) PR_fprintf(err, "We have long long\n"); #else PR_fprintf(err, "We don't have long long\n"); #endif if (bsi) { PR_fprintf(err, "Converting %ld: ", si.i); LL_I2L(si.l, si.i); PR_fprintf(err, "%lld\n", si.l); } if (bui) { PR_fprintf(err, "Converting %lu: ", ui.i); LL_I2L(ui.l, ui.i); PR_fprintf(err, "%llu\n", ui.l); } return 0; } /* main */ int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ /* i2l.c */ nspr-4.11/nspr/pr/tests/initclk.c0000644000000000000000000000435712623070344015127 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This is a regression test for the bug that the interval timer * is not initialized when _PR_CreateCPU calls PR_IntervalNow. * The bug would make this test program finish prematurely, * when the SHORT_TIMEOUT period expires. The correct behavior * is for the test to finish when the LONG_TIMEOUT period expires. */ #include "prlock.h" #include "prcvar.h" #include "prthread.h" #include "prinrval.h" #include "prlog.h" #include #include /* The timeouts, in milliseconds */ #define SHORT_TIMEOUT 1000 #define LONG_TIMEOUT 3000 PRLock *lock1, *lock2; PRCondVar *cv1, *cv2; void ThreadFunc(void *arg) { PR_Lock(lock1); PR_WaitCondVar(cv1, PR_MillisecondsToInterval(SHORT_TIMEOUT)); PR_Unlock(lock1); } int main(int argc, char **argv) { PRThread *thread; PRIntervalTime start, end; PRUint32 elapsed_ms; lock1 = PR_NewLock(); PR_ASSERT(NULL != lock1); cv1 = PR_NewCondVar(lock1); PR_ASSERT(NULL != cv1); lock2 = PR_NewLock(); PR_ASSERT(NULL != lock2); cv2 = PR_NewCondVar(lock2); PR_ASSERT(NULL != cv2); start = PR_IntervalNow(); thread = PR_CreateThread( PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(NULL != thread); PR_Lock(lock2); PR_WaitCondVar(cv2, PR_MillisecondsToInterval(LONG_TIMEOUT)); PR_Unlock(lock2); PR_JoinThread(thread); end = PR_IntervalNow(); elapsed_ms = PR_IntervalToMilliseconds((PRIntervalTime)(end - start)); /* Allow 100ms imprecision */ if (elapsed_ms < LONG_TIMEOUT - 100 || elapsed_ms > LONG_TIMEOUT + 100) { printf("Elapsed time should be %u ms but is %u ms\n", LONG_TIMEOUT, elapsed_ms); printf("FAIL\n"); exit(1); } printf("Elapsed time: %u ms, expected time: %u ms\n", LONG_TIMEOUT, elapsed_ms); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/inrval.c0000644000000000000000000001475512623070344014770 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** file: inrval.c ** description: Interval conversion test. ** Modification History: ** 15-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. **/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "obsolete/pralarm.h" #include "prio.h" #include "prprf.h" #include "prlock.h" #include "prlong.h" #include "prcvar.h" #include "prinrval.h" #include "prtime.h" #include "plgetopt.h" #include #include static PRIntn debug_mode; static PRFileDesc *output; static void TestConversions(void) { PRIntervalTime ticks = PR_TicksPerSecond(); if (debug_mode) { PR_fprintf(output, "PR_TicksPerSecond: %ld\n\n", ticks); PR_fprintf(output, "PR_SecondsToInterval(1): %ld\n", PR_SecondsToInterval(1)); PR_fprintf(output, "PR_MillisecondsToInterval(1000): %ld\n", PR_MillisecondsToInterval(1000)); PR_fprintf(output, "PR_MicrosecondsToInterval(1000000): %ld\n\n", PR_MicrosecondsToInterval(1000000)); PR_fprintf(output, "PR_SecondsToInterval(3): %ld\n", PR_SecondsToInterval(3)); PR_fprintf(output, "PR_MillisecondsToInterval(3000): %ld\n", PR_MillisecondsToInterval(3000)); PR_fprintf(output, "PR_MicrosecondsToInterval(3000000): %ld\n\n", PR_MicrosecondsToInterval(3000000)); PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks)); PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks)); PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks)); ticks *= 3; PR_fprintf(output, "PR_IntervalToSeconds(%ld): %ld\n", ticks, PR_IntervalToSeconds(ticks)); PR_fprintf(output, "PR_IntervalToMilliseconds(%ld): %ld\n", ticks, PR_IntervalToMilliseconds(ticks)); PR_fprintf(output, "PR_IntervalToMicroseconds(%ld): %ld\n\n", ticks, PR_IntervalToMicroseconds(ticks)); } /*end debug mode */ } /* TestConversions */ static void TestIntervalOverhead(void) { /* Hopefully the optimizer won't delete this function */ PRUint32 elapsed, per_call, loops = 1000000; PRIntervalTime timeout, timein = PR_IntervalNow(); while (--loops > 0) timeout = PR_IntervalNow(); elapsed = 1000U * PR_IntervalToMicroseconds(timeout - timein); per_call = elapsed / 1000000U; PR_fprintf( output, "Overhead of 'PR_IntervalNow()' is %u nsecs\n\n", per_call); } /* TestIntervalOverhead */ static void TestNowOverhead(void) { PRTime timeout, timein; PRInt32 overhead, loops = 1000000; PRInt64 elapsed, per_call, ten23rd, ten26th; LL_I2L(ten23rd, 1000); LL_I2L(ten26th, 1000000); timein = PR_Now(); while (--loops > 0) timeout = PR_Now(); LL_SUB(elapsed, timeout, timein); LL_MUL(elapsed, elapsed, ten23rd); LL_DIV(per_call, elapsed, ten26th); LL_L2I(overhead, per_call); PR_fprintf( output, "Overhead of 'PR_Now()' is %u nsecs\n\n", overhead); } /* TestNowOverhead */ static void TestIntervals(void) { PRStatus rv; PRUint32 delta; PRInt32 seconds; PRUint64 elapsed, thousand; PRTime timein, timeout; PRLock *ml = PR_NewLock(); PRCondVar *cv = PR_NewCondVar(ml); for (seconds = 0; seconds < 10; ++seconds) { PRIntervalTime ticks = PR_SecondsToInterval(seconds); PR_Lock(ml); timein = PR_Now(); rv = PR_WaitCondVar(cv, ticks); timeout = PR_Now(); PR_Unlock(ml); LL_SUB(elapsed, timeout, timein); LL_I2L(thousand, 1000); LL_DIV(elapsed, elapsed, thousand); LL_L2UI(delta, elapsed); if (debug_mode) PR_fprintf(output, "TestIntervals: %swaiting %ld seconds took %ld msecs\n", ((rv == PR_SUCCESS) ? "" : "FAILED "), seconds, delta); } PR_DestroyCondVar(cv); PR_DestroyLock(ml); if (debug_mode) PR_fprintf(output, "\n"); } /* TestIntervals */ static PRIntn PR_CALLBACK RealMain(int argc, char** argv) { PRUint32 vcpu, cpus = 0, loops = 1000; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ /* main test */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dl:c:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; case 'c': /* concurrency counter */ cpus = atoi(opt->value); break; case 'l': /* loop counter */ loops = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); output = PR_GetSpecialFD(PR_StandardOutput); PR_fprintf(output, "inrval: Examine stdout to determine results.\n"); if (cpus == 0) cpus = 8; if (loops == 0) loops = 1000; if (debug_mode > 0) { PR_fprintf(output, "Inrval: Using %d loops\n", loops); PR_fprintf(output, "Inrval: Using 1 and %d cpu(s)\n", cpus); } for (vcpu = 1; vcpu <= cpus; vcpu += cpus - 1) { if (debug_mode) PR_fprintf(output, "\nInrval: Using %d CPU(s)\n\n", vcpu); PR_SetConcurrency(vcpu); TestNowOverhead(); TestIntervalOverhead(); TestConversions(); TestIntervals(); } return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/instrumt.c0000644000000000000000000003017412623070344015353 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: instrumt.c ** Description: This test is for the NSPR debug aids defined in ** prcountr.h, prtrace.h, prolock.h ** ** The test case tests the three debug aids in NSPR: ** ** Diagnostic messages can be enabled using "instrumt -v 6" ** This sets the msgLevel to something that PR_LOG() likes. ** Also define in the environment "NSPR_LOG_MODULES=Test:6" ** ** CounterTest() tests the counter facility. This test ** creates 4 threads. Each thread either increments, decrements, ** adds to or subtracts from a counter, depending on an argument ** passed to the thread at thread-create time. Each of these threads ** does COUNT_LIMIT iterations doing its thing. When all 4 threads ** are done, the result of the counter is evaluated. If all was atomic, ** the the value of the counter should be zero. ** ** TraceTest(): ** This test mingles with the counter test. Counters trace. ** A thread to extract trace entries on the fly is started. ** A thread to dump trace entries to a file is started. ** ** OrderedLockTest(): ** ** ** ** ** */ #include #include #include #include #include #include #include #include #include #include #include #define COUNT_LIMIT (10 * ( 1024)) #define SMALL_TRACE_BUFSIZE ( 60 * 1024 ) typedef enum { CountLoop = 1, TraceLoop = 2, TraceFlow = 3 } TraceTypes; PRLogModuleLevel msgLevel = PR_LOG_ALWAYS; PRBool help = PR_FALSE; PRBool failed = PR_FALSE; PRLogModuleInfo *lm; PRMonitor *mon; PRInt32 activeThreads = 0; PR_DEFINE_COUNTER( hCounter ); PR_DEFINE_TRACE( hTrace ); static void Help(void) { printf("Help? ... Ha!\n"); } static void ListCounters(void) { PR_DEFINE_COUNTER( qh ); PR_DEFINE_COUNTER( rh ); const char *qn, *rn, *dn; const char **qname = &qn, **rname = &rn, **desc = &dn; PRUint32 tCtr; PR_INIT_COUNTER_HANDLE( qh, NULL ); PR_FIND_NEXT_COUNTER_QNAME(qh, qh ); while ( qh != NULL ) { PR_INIT_COUNTER_HANDLE( rh, NULL ); PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh ); while ( rh != NULL ) { PR_GET_COUNTER_NAME_FROM_HANDLE( rh, qname, rname, desc ); PR_GET_COUNTER(tCtr, rh); PR_LOG( lm, msgLevel, ( "QName: %s RName: %s Desc: %s Value: %ld\n", qn, rn, dn, tCtr )); PR_FIND_NEXT_COUNTER_RNAME(rh, rh, qh ); } PR_FIND_NEXT_COUNTER_QNAME(qh, qh); } return; } /* end ListCounters() */ static void ListTraces(void) { PR_DEFINE_TRACE( qh ); PR_DEFINE_TRACE( rh ); const char *qn, *rn, *dn; const char **qname = &qn, **rname = &rn, **desc = &dn; PR_INIT_TRACE_HANDLE( qh, NULL ); PR_FIND_NEXT_TRACE_QNAME(qh, qh ); while ( qh != NULL ) { PR_INIT_TRACE_HANDLE( rh, NULL ); PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh ); while ( rh != NULL ) { PR_GET_TRACE_NAME_FROM_HANDLE( rh, qname, rname, desc ); PR_LOG( lm, msgLevel, ( "QName: %s RName: %s Desc: %s", qn, rn, dn )); PR_FIND_NEXT_TRACE_RNAME(rh, rh, qh ); } PR_FIND_NEXT_TRACE_QNAME(qh, qh); } return; } /* end ListCounters() */ static PRInt32 one = 1; static PRInt32 two = 2; static PRInt32 three = 3; static PRInt32 four = 4; /* ** Thread to iteratively count something. */ static void PR_CALLBACK CountSomething( void *arg ) { PRInt32 switchVar = *((PRInt32 *)arg); PRInt32 i; PR_LOG( lm, msgLevel, ("CountSomething: begin thread %ld", switchVar )); for ( i = 0; i < COUNT_LIMIT ; i++) { switch ( switchVar ) { case 1 : PR_INCREMENT_COUNTER( hCounter ); break; case 2 : PR_DECREMENT_COUNTER( hCounter ); break; case 3 : PR_ADD_TO_COUNTER( hCounter, 1 ); break; case 4 : PR_SUBTRACT_FROM_COUNTER( hCounter, 1 ); break; default : PR_ASSERT( 0 ); break; } PR_TRACE( hTrace, CountLoop, switchVar, i, 0, 0, 0, 0, 0 ); } /* end for() */ PR_LOG( lm, msgLevel, ("CounterSomething: end thread %ld", switchVar )); PR_EnterMonitor(mon); --activeThreads; PR_Notify( mon ); PR_ExitMonitor(mon); return; } /* end CountSomething() */ /* ** Create the counter threads. */ static void CounterTest( void ) { PRThread *t1, *t2, *t3, *t4; PRIntn i = 0; PR_DEFINE_COUNTER( tc ); PR_DEFINE_COUNTER( zCounter ); PR_LOG( lm, msgLevel, ("Begin CounterTest")); /* ** Test Get and Set of a counter. ** */ PR_CREATE_COUNTER( zCounter, "Atomic", "get/set test", "test get and set of counter" ); PR_SET_COUNTER( zCounter, 9 ); PR_GET_COUNTER( i, zCounter ); if ( i != 9 ) { failed = PR_TRUE; PR_LOG( lm, msgLevel, ("Counter set/get failed")); } activeThreads += 4; PR_CREATE_COUNTER( hCounter, "Atomic", "SMP Tests", "test atomic nature of counter" ); PR_GET_COUNTER_HANDLE_FROM_NAME( tc, "Atomic", "SMP Tests" ); PR_ASSERT( tc == hCounter ); t1 = PR_CreateThread(PR_USER_THREAD, CountSomething, &one, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t1); t2 = PR_CreateThread(PR_USER_THREAD, CountSomething, &two, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t2); t3 = PR_CreateThread(PR_USER_THREAD, CountSomething, &three, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t3); t4 = PR_CreateThread(PR_USER_THREAD, CountSomething, &four, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t4); PR_LOG( lm, msgLevel, ("Counter Threads started")); ListCounters(); return; } /* end CounterTest() */ /* ** Thread to dump trace buffer to a file. */ static void PR_CALLBACK RecordTrace(void *arg ) { PR_RECORD_TRACE_ENTRIES(); PR_EnterMonitor(mon); --activeThreads; PR_Notify( mon ); PR_ExitMonitor(mon); return; } /* end RecordTrace() */ #define NUM_TRACE_RECORDS ( 10000 ) /* ** Thread to extract and print trace entries from the buffer. */ static void PR_CALLBACK SampleTrace( void *arg ) { #if defined(DEBUG) || defined(FORCE_NSPR_TRACE) PRInt32 found, rc; PRTraceEntry *foundEntries; PRInt32 i; foundEntries = (PRTraceEntry *)PR_Malloc( NUM_TRACE_RECORDS * sizeof(PRTraceEntry)); PR_ASSERT(foundEntries != NULL ); do { rc = PR_GetTraceEntries( foundEntries, NUM_TRACE_RECORDS, &found); PR_LOG( lm, msgLevel, ("SampleTrace: Lost Data: %ld found: %ld", rc, found )); if ( found != 0) { for ( i = 0 ; i < found; i++ ) { PR_LOG( lm, msgLevel, ("SampleTrace, detail: Thread: %p, Time: %llX, UD0: %ld, UD1: %ld, UD2: %8.8ld", (foundEntries +i)->thread, (foundEntries +i)->time, (foundEntries +i)->userData[0], (foundEntries +i)->userData[1], (foundEntries +i)->userData[2] )); } } PR_Sleep(PR_MillisecondsToInterval(50)); } while( found != 0 && activeThreads >= 1 ); PR_Free( foundEntries ); PR_EnterMonitor(mon); --activeThreads; PR_Notify( mon ); PR_ExitMonitor(mon); PR_LOG( lm, msgLevel, ("SampleTrace(): exiting")); #endif return; } /* end RecordTrace() */ /* ** Basic trace test. */ static void TraceTest( void ) { PRInt32 i; PRInt32 size; PR_DEFINE_TRACE( th ); PRThread *t1, *t2; PR_LOG( lm, msgLevel, ("Begin TraceTest")); size = SMALL_TRACE_BUFSIZE; PR_SET_TRACE_OPTION( PRTraceBufSize, &size ); PR_GET_TRACE_OPTION( PRTraceBufSize, &i ); PR_CREATE_TRACE( th, "TraceTest", "tt2", "A description for the trace test" ); PR_CREATE_TRACE( th, "TraceTest", "tt3", "A description for the trace test" ); PR_CREATE_TRACE( th, "TraceTest", "tt4", "A description for the trace test" ); PR_CREATE_TRACE( th, "TraceTest", "tt5", "A description for the trace test" ); PR_CREATE_TRACE( th, "TraceTest", "tt6", "A description for the trace test" ); PR_CREATE_TRACE( th, "TraceTest", "tt7", "A description for the trace test" ); PR_CREATE_TRACE( th, "TraceTest", "tt8", "A description for the trace test" ); PR_CREATE_TRACE( th, "Trace Test", "tt0", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt1", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt2", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt3", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt4", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt5", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt6", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt7", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt8", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt9", "QName is Trace Test, not TraceTest" ); PR_CREATE_TRACE( th, "Trace Test", "tt10", "QName is Trace Test, not TraceTest" ); activeThreads += 2; t1 = PR_CreateThread(PR_USER_THREAD, RecordTrace, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t1); t2 = PR_CreateThread(PR_USER_THREAD, SampleTrace, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); PR_ASSERT(t2); ListTraces(); PR_GET_TRACE_HANDLE_FROM_NAME( th, "TraceTest","tt1" ); PR_ASSERT( th == hTrace ); PR_LOG( lm, msgLevel, ("End TraceTest")); return; } /* end TraceTest() */ /* ** Ordered lock test. */ static void OrderedLockTest( void ) { PR_LOG( lm, msgLevel, ("Begin OrderedLockTest")); } /* end OrderedLockTest() */ int main(int argc, char **argv) { #if defined(DEBUG) || defined(FORCE_NSPR_TRACE) PRUint32 counter; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hdv:"); lm = PR_NewLogModule("Test"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'v': /* verbose mode */ msgLevel = (PRLogModuleLevel)atol( opt->value); break; case 'h': /* help message */ Help(); help = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); PR_CREATE_TRACE( hTrace, "TraceTest", "tt1", "A description for the trace test" ); mon = PR_NewMonitor(); PR_EnterMonitor( mon ); TraceTest(); CounterTest(); OrderedLockTest(); /* Wait for all threads to exit */ while ( activeThreads > 0 ) { if ( activeThreads == 1 ) PR_SET_TRACE_OPTION( PRTraceStopRecording, NULL ); PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); PR_GET_COUNTER( counter, hCounter ); } PR_ExitMonitor( mon ); /* ** Evaluate results */ PR_GET_COUNTER( counter, hCounter ); if ( counter != 0 ) { failed = PR_TRUE; PR_LOG( lm, msgLevel, ("Expected counter == 0, found: %ld", counter)); printf("FAIL\n"); } else { printf("PASS\n"); } PR_DESTROY_COUNTER( hCounter ); PR_DestroyMonitor( mon ); PR_TRACE( hTrace, TraceFlow, 0xfff,0,0,0,0,0,0); PR_DESTROY_TRACE( hTrace ); #else printf("Test not defined\n"); #endif return 0; } /* main() */ /* end instrumt.c */ nspr-4.11/nspr/pr/tests/intrio.c0000644000000000000000000000740012623070344014766 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: intrio.c * Purpose: testing i/o interrupts (see Bugzilla bug #31120) */ #include "nspr.h" #include #include #include /* for synchronization between the main thread and iothread */ static PRLock *lock; static PRCondVar *cvar; static PRBool iothread_ready; static void PR_CALLBACK AbortIO(void *arg) { PRStatus rv; PR_Sleep(PR_SecondsToInterval(2)); rv = PR_Interrupt((PRThread*)arg); PR_ASSERT(PR_SUCCESS == rv); } /* AbortIO */ static void PR_CALLBACK IOThread(void *arg) { PRFileDesc *sock, *newsock; PRNetAddr addr; sock = PR_OpenTCPSocket(PR_AF_INET6); if (sock == NULL) { fprintf(stderr, "PR_OpenTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } /* tell the main thread that we are ready */ PR_Lock(lock); iothread_ready = PR_TRUE; PR_NotifyCondVar(cvar); PR_Unlock(lock); newsock = PR_Accept(sock, NULL, PR_INTERVAL_NO_TIMEOUT); if (newsock != NULL) { fprintf(stderr, "PR_Accept shouldn't have succeeded\n"); exit(1); } if (PR_GetError() != PR_PENDING_INTERRUPT_ERROR) { fprintf(stderr, "PR_Accept failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("PR_Accept() is interrupted as expected\n"); if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } static void Test(PRThreadScope scope1, PRThreadScope scope2) { PRThread *iothread, *abortio; printf("A %s thread will be interrupted by a %s thread\n", (scope1 == PR_LOCAL_THREAD ? "local" : "global"), (scope2 == PR_LOCAL_THREAD ? "local" : "global")); iothread_ready = PR_FALSE; iothread = PR_CreateThread( PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL, scope1, PR_JOINABLE_THREAD, 0); if (iothread == NULL) { fprintf(stderr, "cannot create thread\n"); exit(1); } PR_Lock(lock); while (!iothread_ready) PR_WaitCondVar(cvar, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(lock); abortio = PR_CreateThread( PR_USER_THREAD, AbortIO, iothread, PR_PRIORITY_NORMAL, scope2, PR_JOINABLE_THREAD, 0); if (abortio == NULL) { fprintf(stderr, "cannot create thread\n"); exit(1); } if (PR_JoinThread(iothread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } if (PR_JoinThread(abortio) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } } int main(int argc, char **argv) { PR_STDIO_INIT(); lock = PR_NewLock(); if (lock == NULL) { fprintf(stderr, "PR_NewLock failed\n"); exit(1); } cvar = PR_NewCondVar(lock); if (cvar == NULL) { fprintf(stderr, "PR_NewCondVar failed\n"); exit(1); } /* test all four combinations */ Test(PR_LOCAL_THREAD, PR_LOCAL_THREAD); Test(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); Test(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); Test(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); printf("PASSED\n"); return 0; } /* main */ nspr-4.11/nspr/pr/tests/intrupt.c0000644000000000000000000002137312623070344015174 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: intrupt.c * Purpose: testing thread interrupts */ #include "plgetopt.h" #include "prcvar.h" #include "prerror.h" #include "prinit.h" #include "prinrval.h" #include "prio.h" #include "prlock.h" #include "prlog.h" #include "prthread.h" #include "prtypes.h" #include "prnetdb.h" #include #include #define DEFAULT_TCP_PORT 12500 static PRLock *ml = NULL; static PRCondVar *cv = NULL; static PRBool passed = PR_TRUE; static PRBool debug_mode = PR_FALSE; static PRThreadScope thread_scope = PR_LOCAL_THREAD; static void PR_CALLBACK AbortCV(void *arg) { PRStatus rv; PRThread *me = PR_GetCurrentThread(); /* some other thread (main) is doing the interrupt */ PR_Lock(ml); rv = PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); if (debug_mode) printf( "Expected interrupt on wait CV and "); if (PR_FAILURE == rv) { if (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) { if (debug_mode) printf("got it\n"); } else { if (debug_mode) printf("got random error\n"); passed = PR_FALSE; } } else { if (debug_mode) printf("got a successful completion\n"); passed = PR_FALSE; } rv = PR_WaitCondVar(cv, 10); if (debug_mode) { printf( "Expected success on wait CV and %s\n", (PR_SUCCESS == rv) ? "got it" : "failed"); } passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; /* interrupt myself, then clear */ PR_Interrupt(me); PR_ClearInterrupt(); rv = PR_WaitCondVar(cv, 10); if (debug_mode) { printf("Expected success on wait CV and "); if (PR_FAILURE == rv) { printf( "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ? "got interrupted" : "a random failure"); } printf("got it\n"); } passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; /* set, then wait - interrupt - then wait again */ PR_Interrupt(me); rv = PR_WaitCondVar(cv, 10); if (debug_mode) printf( "Expected interrupt on wait CV and "); if (PR_FAILURE == rv) { if (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) { if (debug_mode) printf("got it\n"); } else { if (debug_mode) printf("failed\n"); passed = PR_FALSE; } } else { if (debug_mode) printf("got a successful completion\n"); passed = PR_FALSE; } rv = PR_WaitCondVar(cv, 10); if (debug_mode) { printf( "Expected success on wait CV and %s\n", (PR_SUCCESS == rv) ? "got it" : "failed"); } passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; PR_Unlock(ml); } /* AbortCV */ static void PR_CALLBACK AbortIO(void *arg) { PRStatus rv; PR_Sleep(PR_SecondsToInterval(2)); rv = PR_Interrupt((PRThread*)arg); PR_ASSERT(PR_SUCCESS == rv); } /* AbortIO */ static void PR_CALLBACK AbortJoin(void *arg) { } /* AbortJoin */ static void setup_listen_socket(PRFileDesc **listner, PRNetAddr *netaddr) { PRStatus rv; PRInt16 port = DEFAULT_TCP_PORT; *listner = PR_NewTCPSocket(); PR_ASSERT(*listner != NULL); memset(netaddr, 0, sizeof(*netaddr)); (*netaddr).inet.ip = PR_htonl(PR_INADDR_ANY); (*netaddr).inet.family = PR_AF_INET; do { (*netaddr).inet.port = PR_htons(port); rv = PR_Bind(*listner, netaddr); port += 1; PR_ASSERT(port < (DEFAULT_TCP_PORT + 10)); } while (PR_FAILURE == rv); rv = PR_Listen(*listner, 5); if (PR_GetSockName(*listner, netaddr) < 0) { if (debug_mode) printf("intrupt: ERROR - PR_GetSockName failed\n"); passed = PR_FALSE; return; } } static void PR_CALLBACK IntrBlock(void *arg) { PRStatus rv; PRNetAddr netaddr; PRFileDesc *listner; /* some other thread (main) is doing the interrupt */ /* block the interrupt */ PR_BlockInterrupt(); PR_Lock(ml); rv = PR_WaitCondVar(cv, PR_SecondsToInterval(4)); PR_Unlock(ml); if (debug_mode) { printf("Expected success on wait CV and "); if (PR_FAILURE == rv) { printf( "%s\n", (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) ? "got interrupted" : "got a random failure"); } else printf("got it\n"); } passed = ((PR_TRUE == passed) && (PR_SUCCESS == rv)) ? PR_TRUE : PR_FALSE; setup_listen_socket(&listner, &netaddr); PR_UnblockInterrupt(); if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL) { PRInt32 error = PR_GetError(); if (debug_mode) printf("Expected interrupt on PR_Accept() and "); if (PR_PENDING_INTERRUPT_ERROR == error) { if (debug_mode) printf("got it\n"); } else { if (debug_mode) printf("failed\n"); passed = PR_FALSE; } } else { if (debug_mode) printf("Failed to interrupt PR_Accept()\n"); passed = PR_FALSE; } (void)PR_Close(listner); listner = NULL; } /* TestIntrBlock */ void PR_CALLBACK Intrupt(void *arg) { PRStatus rv; PRNetAddr netaddr; PRFileDesc *listner; PRThread *abortCV, *abortIO, *abortJoin, *intrBlock; ml = PR_NewLock(); cv = PR_NewCondVar(ml); /* Part I */ if (debug_mode) printf("Part I\n"); abortCV = PR_CreateThread( PR_USER_THREAD, AbortCV, 0, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); PR_Sleep(PR_SecondsToInterval(2)); rv = PR_Interrupt(abortCV); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(abortCV); PR_ASSERT(PR_SUCCESS == rv); /* Part II */ if (debug_mode) printf("Part II\n"); abortJoin = PR_CreateThread( PR_USER_THREAD, AbortJoin, 0, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); PR_Sleep(PR_SecondsToInterval(2)); if (debug_mode) printf("Expecting to interrupt an exited thread "); rv = PR_Interrupt(abortJoin); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(abortJoin); PR_ASSERT(PR_SUCCESS == rv); if (debug_mode) printf("and succeeded\n"); /* Part III */ if (debug_mode) printf("Part III\n"); setup_listen_socket(&listner, &netaddr); abortIO = PR_CreateThread( PR_USER_THREAD, AbortIO, PR_GetCurrentThread(), PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (PR_Accept(listner, &netaddr, PR_INTERVAL_NO_TIMEOUT) == NULL) { PRInt32 error = PR_GetError(); if (debug_mode) printf("Expected interrupt on PR_Accept() and "); if (PR_PENDING_INTERRUPT_ERROR == error) { if (debug_mode) printf("got it\n"); } else { if (debug_mode) printf("failed\n"); passed = PR_FALSE; } } else { if (debug_mode) printf("Failed to interrupt PR_Accept()\n"); passed = PR_FALSE; } (void)PR_Close(listner); listner = NULL; rv = PR_JoinThread(abortIO); PR_ASSERT(PR_SUCCESS == rv); /* Part VI */ if (debug_mode) printf("Part VI\n"); intrBlock = PR_CreateThread( PR_USER_THREAD, IntrBlock, 0, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); PR_Sleep(PR_SecondsToInterval(2)); rv = PR_Interrupt(intrBlock); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(intrBlock); PR_ASSERT(PR_SUCCESS == rv); PR_DestroyCondVar(cv); PR_DestroyLock(ml); } /* Intrupt */ int main(int argc, char **argv) { PRThread *intrupt; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dG"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); intrupt = PR_CreateThread( PR_USER_THREAD, Intrupt, NULL, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (intrupt == NULL) { fprintf(stderr, "cannot create thread\n"); passed = PR_FALSE; } else { PRStatus rv; rv = PR_JoinThread(intrupt); PR_ASSERT(rv == PR_SUCCESS); } printf("%s\n", ((passed) ? "PASSED" : "FAILED")); return ((passed) ? 0 : 1); } /* main */ /* intrupt.c */ nspr-4.11/nspr/pr/tests/io_timeout.c0000644000000000000000000001520512623070344015641 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** Test socket IO timeouts ** ** ** ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include #include "nspr.h" #define NUM_THREADS 1 #define BASE_PORT 8000 #define DEFAULT_ACCEPT_TIMEOUT 2 typedef struct threadInfo { PRInt16 id; PRInt16 accept_timeout; PRLock *dead_lock; PRCondVar *dead_cv; PRInt32 *alive; } threadInfo; PRIntn failed_already = 0; PRIntn debug_mode = 0; #define LOCAL_SCOPE_STRING "LOCAL scope" #define GLOBAL_SCOPE_STRING "GLOBAL scope" #define GLOBAL_BOUND_SCOPE_STRING "GLOBAL_BOUND scope" void thread_main(void *_info) { threadInfo *info = (threadInfo *)_info; PRNetAddr listenAddr; PRNetAddr clientAddr; PRFileDesc *listenSock = NULL; PRFileDesc *clientSock; PRStatus rv; PRThreadScope tscope; char *scope_str; if (debug_mode) printf("thread %d is alive\n", info->id); tscope = PR_GetThreadScope(PR_GetCurrentThread()); switch(tscope) { case PR_LOCAL_THREAD: scope_str = LOCAL_SCOPE_STRING; break; case PR_GLOBAL_THREAD: scope_str = GLOBAL_SCOPE_STRING; break; case PR_GLOBAL_BOUND_THREAD: scope_str = GLOBAL_BOUND_SCOPE_STRING; break; default: PR_NOT_REACHED("Invalid thread scope"); break; } printf("thread id %d, scope %s\n", info->id, scope_str); listenSock = PR_NewTCPSocket(); if (!listenSock) { if (debug_mode) printf("unable to create listen socket\n"); failed_already=1; goto dead; } listenAddr.inet.family = PR_AF_INET; listenAddr.inet.port = PR_htons(BASE_PORT + info->id); listenAddr.inet.ip = PR_htonl(PR_INADDR_ANY); rv = PR_Bind(listenSock, &listenAddr); if (rv == PR_FAILURE) { if (debug_mode) printf("unable to bind\n"); failed_already=1; goto dead; } rv = PR_Listen(listenSock, 4); if (rv == PR_FAILURE) { if (debug_mode) printf("unable to listen\n"); failed_already=1; goto dead; } if (debug_mode) printf("thread %d going into accept for %d seconds\n", info->id, info->accept_timeout + info->id); clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id)); if (clientSock == NULL) { if (PR_GetError() == PR_IO_TIMEOUT_ERROR) { if (debug_mode) { printf("PR_Accept() timeout worked!\n"); printf("TEST PASSED! PR_Accept() returned error %d\n", PR_IO_TIMEOUT_ERROR); } } else { if (debug_mode) printf("TEST FAILED! PR_Accept() returned error %d\n", PR_GetError()); failed_already=1; } } else { if (debug_mode) printf ("TEST FAILED! PR_Accept() succeeded?\n"); failed_already=1; PR_Close(clientSock); } dead: if (listenSock) { PR_Close(listenSock); } PR_Lock(info->dead_lock); (*info->alive)--; PR_NotifyCondVar(info->dead_cv); PR_Unlock(info->dead_lock); if (debug_mode) printf("thread %d is dead\n", info->id); PR_Free(info); } void thread_test(PRThreadScope scope, PRInt32 num_threads) { PRInt32 index; PRThread *thr; PRLock *dead_lock; PRCondVar *dead_cv; PRInt32 alive; if (debug_mode) printf("IO Timeout test started with %d threads\n", num_threads); dead_lock = PR_NewLock(); dead_cv = PR_NewCondVar(dead_lock); alive = num_threads; for (index = 0; index < num_threads; index++) { threadInfo *info = (threadInfo *)PR_Malloc(sizeof(threadInfo)); info->id = index; info->dead_lock = dead_lock; info->dead_cv = dead_cv; info->alive = &alive; info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT; thr = PR_CreateThread( PR_USER_THREAD, thread_main, (void *)info, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0); if (!thr) { printf("Failed to create thread, error = %d(%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; PR_Lock(dead_lock); alive--; PR_Unlock(dead_lock); } } PR_Lock(dead_lock); while(alive) { if (debug_mode) printf("main loop awake; alive = %d\n", alive); PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(dead_lock); PR_DestroyCondVar(dead_cv); PR_DestroyLock(dead_lock); } int main(int argc, char **argv) { PRInt32 num_threads = 0; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name [-d] [-t ] */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dt:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; case 't': /* threads to involve */ num_threads = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); /* main test */ if (0 == num_threads) num_threads = NUM_THREADS; PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0); PR_STDIO_INIT(); printf("test with global bound thread\n"); thread_test(PR_GLOBAL_BOUND_THREAD, num_threads); printf("test with local thread\n"); thread_test(PR_LOCAL_THREAD, num_threads); printf("test with global thread\n"); thread_test(PR_GLOBAL_THREAD, num_threads); PR_Cleanup(); if (failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/io_timeoutk.c0000644000000000000000000001310312623070344016007 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** name io_timeoutk.c ** Description:Test socket IO timeouts (kernel level) ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include #include "nspr.h" #define NUM_THREADS 1 #define BASE_PORT 8000 #define DEFAULT_ACCEPT_TIMEOUT 2 typedef struct threadInfo { PRInt16 id; PRInt16 accept_timeout; PRLock *dead_lock; PRCondVar *dead_cv; PRInt32 *alive; } threadInfo; PRIntn failed_already=0; PRIntn debug_mode; void thread_main(void *_info) { threadInfo *info = (threadInfo *)_info; PRNetAddr listenAddr; PRNetAddr clientAddr; PRFileDesc *listenSock = NULL; PRFileDesc *clientSock; PRStatus rv; if (debug_mode) printf("thread %d is alive\n", info->id); listenSock = PR_NewTCPSocket(); if (!listenSock) { if (debug_mode) printf("unable to create listen socket\n"); goto dead; } listenAddr.inet.family = AF_INET; listenAddr.inet.port = PR_htons(BASE_PORT + info->id); listenAddr.inet.ip = PR_htonl(INADDR_ANY); rv = PR_Bind(listenSock, &listenAddr); if (rv == PR_FAILURE) { if (debug_mode) printf("unable to bind\n"); goto dead; } rv = PR_Listen(listenSock, 4); if (rv == PR_FAILURE) { if (debug_mode) printf("unable to listen\n"); goto dead; } if (debug_mode) printf("thread %d going into accept for %d seconds\n", info->id, info->accept_timeout + info->id); clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id)); if (clientSock == NULL) { if (PR_GetError() == PR_IO_TIMEOUT_ERROR) if (debug_mode) { printf("PR_Accept() timeout worked!\n"); printf("TEST FAILED! PR_Accept() returned error %d\n", PR_GetError()); } else failed_already=1; } else { if (debug_mode) printf ("TEST FAILED! PR_Accept() succeeded?\n"); else failed_already=1; PR_Close(clientSock); } dead: if (listenSock) { PR_Close(listenSock); } PR_Lock(info->dead_lock); (*info->alive)--; PR_NotifyCondVar(info->dead_cv); PR_Unlock(info->dead_lock); if (debug_mode) printf("thread %d is dead\n", info->id); } void thread_test(PRInt32 scope, PRInt32 num_threads) { PRInt32 index; PRThread *thr; PRLock *dead_lock; PRCondVar *dead_cv; PRInt32 alive; if (debug_mode) printf("IO Timeout test started with %d threads\n", num_threads); dead_lock = PR_NewLock(); dead_cv = PR_NewCondVar(dead_lock); alive = num_threads; for (index = 0; index < num_threads; index++) { threadInfo *info = (threadInfo *)malloc(sizeof(threadInfo)); info->id = index; info->dead_lock = dead_lock; info->dead_cv = dead_cv; info->alive = &alive; info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT; thr = PR_CreateThread( PR_USER_THREAD, thread_main, (void *)info, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0); if (!thr) { PR_Lock(dead_lock); alive--; PR_Unlock(dead_lock); } } PR_Lock(dead_lock); while(alive) { if (debug_mode) printf("main loop awake; alive = %d\n", alive); PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(dead_lock); } int main(int argc, char **argv) { PRInt32 num_threads; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ if (argc > 2) num_threads = atoi(argv[2]); else num_threads = NUM_THREADS; PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0); PR_STDIO_INIT(); if (debug_mode) printf("kernel level test\n"); thread_test(PR_GLOBAL_THREAD, num_threads); PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/io_timeoutu.c0000644000000000000000000001310312623070344016021 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** name io_timeoutu.c ** Description: Test socket IO timeouts (user level) ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include #include "nspr.h" #define NUM_THREADS 1 #define BASE_PORT 8000 #define DEFAULT_ACCEPT_TIMEOUT 2 typedef struct threadInfo { PRInt16 id; PRInt16 accept_timeout; PRLock *dead_lock; PRCondVar *dead_cv; PRInt32 *alive; } threadInfo; PRIntn failed_already=0; PRIntn debug_mode; void thread_main(void *_info) { threadInfo *info = (threadInfo *)_info; PRNetAddr listenAddr; PRNetAddr clientAddr; PRFileDesc *listenSock = NULL; PRFileDesc *clientSock; PRStatus rv; if (debug_mode) printf("thread %d is alive\n", info->id); listenSock = PR_NewTCPSocket(); if (!listenSock) { if (debug_mode) printf("unable to create listen socket\n"); goto dead; } listenAddr.inet.family = AF_INET; listenAddr.inet.port = PR_htons(BASE_PORT + info->id); listenAddr.inet.ip = PR_htonl(INADDR_ANY); rv = PR_Bind(listenSock, &listenAddr); if (rv == PR_FAILURE) { if (debug_mode) printf("unable to bind\n"); goto dead; } rv = PR_Listen(listenSock, 4); if (rv == PR_FAILURE) { if (debug_mode) printf("unable to listen\n"); goto dead; } if (debug_mode) printf("thread %d going into accept for %d seconds\n", info->id, info->accept_timeout + info->id); clientSock = PR_Accept( listenSock, &clientAddr, PR_SecondsToInterval( info->accept_timeout + info->id)); if (clientSock == NULL) { if (PR_GetError() == PR_IO_TIMEOUT_ERROR) if (debug_mode) { printf("PR_Accept() timeout worked!\n"); printf("TEST FAILED! PR_Accept() returned error %d\n", } PR_GetError()); else failed_already=1; } else { if (debug_mode) printf ("TEST FAILED! PR_Accept() succeeded?\n"); else failed_already=1; PR_Close(clientSock); } dead: if (listenSock) { PR_Close(listenSock); } PR_Lock(info->dead_lock); (*info->alive)--; PR_NotifyCondVar(info->dead_cv); PR_Unlock(info->dead_lock); if (debug_mode) printf("thread %d is dead\n", info->id); } void thread_test(PRInt32 scope, PRInt32 num_threads) { PRInt32 index; PRThread *thr; PRLock *dead_lock; PRCondVar *dead_cv; PRInt32 alive; if (debug_mode) printf("IO Timeout test started with %d threads\n", num_threads); dead_lock = PR_NewLock(); dead_cv = PR_NewCondVar(dead_lock); alive = num_threads; for (index = 0; index < num_threads; index++) { threadInfo *info = (threadInfo *)malloc(sizeof(threadInfo)); info->id = index; info->dead_lock = dead_lock; info->dead_cv = dead_cv; info->alive = &alive; info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT; thr = PR_CreateThread( PR_USER_THREAD, thread_main, (void *)info, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0); if (!thr) { PR_Lock(dead_lock); alive--; PR_Unlock(dead_lock); } } PR_Lock(dead_lock); while(alive) { if (debug_mode) printf("main loop awake; alive = %d\n", alive); PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(dead_lock); } int main(int argc, char **argv) { PRInt32 num_threads; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ if (argc > 2) num_threads = atoi(argv[2]); else num_threads = NUM_THREADS; PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0); PR_STDIO_INIT(); if (debug_mode) printf("user level test\n"); thread_test(PR_LOCAL_THREAD, num_threads); PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/ioconthr.c0000644000000000000000000000707712623070344015321 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This is a test for the io continuation thread machinery * in pthreads. */ #include "nspr.h" #include int num_threads = 10; /* must be an even number */ PRThreadScope thread_scope = PR_GLOBAL_THREAD; void ThreadFunc(void *arg) { PRFileDesc *fd = (PRFileDesc *) arg; char buf[1024]; PRInt32 nbytes; PRErrorCode err; nbytes = PR_Recv(fd, buf, sizeof(buf), 0, PR_SecondsToInterval(20)); if (nbytes == -1) { err = PR_GetError(); if (err != PR_PENDING_INTERRUPT_ERROR) { fprintf(stderr, "PR_Recv failed: (%d, %d)\n", err, PR_GetOSError()); PR_ProcessExit(1); } /* * After getting an I/O interrupt, this thread must * close the fd before it exits due to a limitation * of our NT implementation. */ if (PR_Close(fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); PR_ProcessExit(1); } } else { fprintf(stderr, "PR_Recv received %d bytes!?\n", nbytes); PR_ProcessExit(1); } } int main(int argc, char **argv) { PRFileDesc **fds; PRThread **threads; PRIntervalTime start, elapsed; int index; fds = (PRFileDesc **) PR_MALLOC(2 * num_threads * sizeof(PRFileDesc *)); PR_ASSERT(fds != NULL); threads = (PRThread **) PR_MALLOC(num_threads * sizeof(PRThread *)); PR_ASSERT(threads != NULL); for (index = 0; index < num_threads; index++) { if (PR_NewTCPSocketPair(&fds[2 * index]) == PR_FAILURE) { fprintf(stderr, "PR_NewTCPSocket failed\n"); PR_ProcessExit(1); } threads[index] = PR_CreateThread( PR_USER_THREAD, ThreadFunc, fds[2 * index], PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (NULL == threads[index]) { fprintf(stderr, "PR_CreateThread failed\n"); PR_ProcessExit(1); } } /* Let the threads block in PR_Recv */ PR_Sleep(PR_SecondsToInterval(2)); printf("Interrupting the threads\n"); fflush(stdout); start = PR_IntervalNow(); for (index = 0; index < num_threads; index++) { if (PR_Interrupt(threads[index]) == PR_FAILURE) { fprintf(stderr, "PR_Interrupt failed\n"); PR_ProcessExit(1); } } for (index = 0; index < num_threads; index++) { if (PR_JoinThread(threads[index]) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); PR_ProcessExit(1); } } elapsed = (PRIntervalTime)(PR_IntervalNow() - start); printf("Threads terminated in %d milliseconds\n", PR_IntervalToMilliseconds(elapsed)); fflush(stdout); /* We are being very generous and allow 10 seconds. */ if (elapsed >= PR_SecondsToInterval(10)) { fprintf(stderr, "Interrupting threads took longer than 10 seconds!!\n"); PR_ProcessExit(1); } for (index = 0; index < num_threads; index++) { /* fds[2 * index] was passed to and closed by threads[index]. */ if (PR_Close(fds[2 * index + 1]) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); PR_ProcessExit(1); } } PR_DELETE(threads); PR_DELETE(fds); printf("PASS\n"); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/ipv6.c0000644000000000000000000001554312623070344014355 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prenv.h" #include "prmem.h" #include "prlink.h" #include "prsystem.h" #include "prnetdb.h" #include "prprf.h" #include "prvrsion.h" #include "plerror.h" #include "plgetopt.h" #include "obsolete/probslet.h" #include #define DNS_BUFFER 100 #define ADDR_BUFFER 100 #define HOST_BUFFER 1024 #define PROTO_BUFFER 1500 #define NETADDR_SIZE(addr) \ (PR_AF_INET == (addr)->raw.family ? \ sizeof((addr)->inet) : sizeof((addr)->ipv6)) static PRFileDesc *err = NULL; static void Help(void) { PR_fprintf(err, "Usage: [-V] [-h]\n"); PR_fprintf(err, "\t Name of host to lookup (default: self)\n"); PR_fprintf(err, "\t-V Display runtime version info (default: FALSE)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ static void DumpAddr(const PRNetAddr* address, const char *msg) { PRUint32 *word = (PRUint32*)address; PRUint32 addr_len = sizeof(PRNetAddr); PR_fprintf(err, "%s[%d]\t", msg, NETADDR_SIZE(address)); while (addr_len > 0) { PR_fprintf(err, " %08x", *word++); addr_len -= sizeof(PRUint32); } PR_fprintf(err, "\n"); } /* DumpAddr */ static PRStatus PrintAddress(const PRNetAddr* address) { PRNetAddr translation; char buffer[ADDR_BUFFER]; PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer)); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_NetAddrToString"); else { PR_fprintf(err, "\t%s\n", buffer); memset(&translation, 0, sizeof(translation)); rv = PR_StringToNetAddr(buffer, &translation); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_StringToNetAddr"); else { PRSize addr_len = NETADDR_SIZE(address); if (0 != memcmp(address, &translation, addr_len)) { PR_fprintf(err, "Address translations do not match\n"); DumpAddr(address, "original"); DumpAddr(&translation, "translate"); rv = PR_FAILURE; } } } return rv; } /* PrintAddress */ int main(int argc, char **argv) { PRStatus rv; PLOptStatus os; PRHostEnt host; PRProtoEnt proto; const char *name = NULL; PRBool failed = PR_FALSE, version = PR_FALSE; PLOptState *opt = PL_CreateOptState(argc, argv, "Vh"); err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* Name of host to lookup */ name = opt->value; break; case 'V': /* Do version discovery */ version = PR_TRUE; break; case 'h': /* user wants some guidance */ default: Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); if (version) { #if defined(WINNT) #define NSPR_LIB "libnspr4" #else #define NSPR_LIB "nspr4" #endif const PRVersionDescription *version_info; char *nspr_path = PR_GetEnv("LD_LIBRARY_PATH"); char *nspr_name = PR_GetLibraryName(nspr_path, NSPR_LIB); PRLibrary *runtime = PR_LoadLibrary(nspr_name); if (NULL == runtime) PL_FPrintError(err, "PR_LoadLibrary"); else { versionEntryPointType versionPoint = (versionEntryPointType) PR_FindSymbol(runtime, "libVersionPoint"); if (NULL == versionPoint) PL_FPrintError(err, "PR_FindSymbol"); else { char buffer[100]; PRExplodedTime exploded; version_info = versionPoint(); (void)PR_fprintf(err, "Runtime library version information\n"); PR_ExplodeTime( version_info->buildTime, PR_GMTParameters, &exploded); (void)PR_FormatTime( buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded); (void)PR_fprintf(err, " Build time: %s GMT\n", buffer); (void)PR_fprintf( err, " Build time: %s\n", version_info->buildTimeString); (void)PR_fprintf( err, " %s V%u.%u.%u (%s%s%s)\n", version_info->description, version_info->vMajor, version_info->vMinor, version_info->vPatch, (version_info->beta ? " beta " : ""), (version_info->debug ? " debug " : ""), (version_info->special ? " special" : "")); (void)PR_fprintf(err, " filename: %s\n", version_info->filename); (void)PR_fprintf(err, " security: %s\n", version_info->security); (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright); (void)PR_fprintf(err, " comment: %s\n", version_info->comment); } } if (NULL != nspr_name) PR_FreeLibraryName(nspr_name); } { if (NULL == name) { char *me = (char*)PR_MALLOC(DNS_BUFFER); rv = PR_GetSystemInfo(PR_SI_HOSTNAME, me, DNS_BUFFER); if (PR_FAILURE == rv) { failed = PR_TRUE; PL_FPrintError(err, "PR_GetSystemInfo"); return 2; } name = me; /* just leak the storage */ } } { char buffer[HOST_BUFFER]; PR_fprintf(err, "Translating the name %s ...", name); rv = PR_GetHostByName(name, buffer, sizeof(buffer), &host); if (PR_FAILURE == rv) { failed = PR_TRUE; PL_FPrintError(err, "PR_GetHostByName"); } else { PRIntn index = 0; PRNetAddr address; memset(&address, 0, sizeof(PRNetAddr)); PR_fprintf(err, "success .. enumerating results\n"); do { index = PR_EnumerateHostEnt(index, &host, 0, &address); if (index > 0) PrintAddress(&address); else if (-1 == index) { failed = PR_TRUE; PL_FPrintError(err, "PR_EnumerateHostEnt"); } } while (index > 0); } } { char buffer[PROTO_BUFFER]; /* ** Get Proto by name/number */ rv = PR_GetProtoByName("tcp", &buffer[1], sizeof(buffer) - 1, &proto); rv = PR_GetProtoByNumber(6, &buffer[3], sizeof(buffer) - 3, &proto); } return (failed) ? 1 : 0; } nspr-4.11/nspr/pr/tests/join.c0000644000000000000000000001431612623070344014425 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dbmalloc1.c ** ** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions. ** ** Modification History: ** ** 19-May-97 AGarcia - separate the four join tests into different unit test modules. ** AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prttools.h" #include "nspr.h" #include #include #include /*********************************************************************** ** PRIVATE FUNCTION: Test_Result ** DESCRIPTION: Used in conjunction with the regress tool, prints out the ** status of the test case. ** INPUTS: PASS/FAIL ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: Determine what the status is and print accordingly. ** ***********************************************************************/ static void Test_Result (int result) { if (result == PASS) printf ("PASS\n"); else printf ("FAIL\n"); exit (1); } /* Program to test joining of threads. Two threads are created. One to be waited upon until it has started. The other to join after it has completed. */ static void PR_CALLBACK lowPriority(void *arg) { } static void PR_CALLBACK highPriority(void *arg) { } static void PR_CALLBACK unjoinable(void *arg) { PR_Sleep(PR_INTERVAL_NO_TIMEOUT); } void runTest(PRThreadScope scope1, PRThreadScope scope2) { PRThread *low,*high; /* create the low and high priority threads */ low = PR_CreateThread(PR_USER_THREAD, lowPriority, 0, PR_PRIORITY_LOW, scope1, PR_JOINABLE_THREAD, 0); if (!low) { if (debug_mode) printf("\tcannot create low priority thread\n"); else Test_Result(FAIL); return; } high = PR_CreateThread(PR_USER_THREAD, highPriority, 0, PR_PRIORITY_HIGH, scope2, PR_JOINABLE_THREAD, 0); if (!high) { if (debug_mode) printf("\tcannot create high priority thread\n"); else Test_Result(FAIL); return; } /* Do the joining for both threads */ if (PR_JoinThread(low) == PR_FAILURE) { if (debug_mode) printf("\tcannot join low priority thread\n"); else Test_Result (FAIL); return; } else { if (debug_mode) printf("\tjoined low priority thread\n"); } if (PR_JoinThread(high) == PR_FAILURE) { if (debug_mode) printf("\tcannot join high priority thread\n"); else Test_Result(FAIL); return; } else { if (debug_mode) printf("\tjoined high priority thread\n"); } } void joinWithUnjoinable(void) { PRThread *thread; /* create the unjoinable thread */ thread = PR_CreateThread(PR_USER_THREAD, unjoinable, 0, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (!thread) { if (debug_mode) printf("\tcannot create unjoinable thread\n"); else Test_Result(FAIL); return; } if (PR_JoinThread(thread) == PR_SUCCESS) { if (debug_mode) printf("\tsuccessfully joined with unjoinable thread?!\n"); else Test_Result(FAIL); return; } else { if (debug_mode) printf("\tcannot join with unjoinable thread, as expected\n"); if (PR_GetError() != PR_INVALID_ARGUMENT_ERROR) { if (debug_mode) printf("\tWrong error code\n"); else Test_Result(FAIL); return; } } if (PR_Interrupt(thread) == PR_FAILURE) { if (debug_mode) printf("\tcannot interrupt unjoinable thread\n"); else Test_Result(FAIL); return; } else { if (debug_mode) printf("\tinterrupted unjoinable thread\n"); } } static PRIntn PR_CALLBACK RealMain(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ printf("User-User test\n"); runTest(PR_LOCAL_THREAD, PR_LOCAL_THREAD); printf("User-Kernel test\n"); runTest(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); printf("Kernel-User test\n"); runTest(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); printf("Kernel-Kernel test\n"); runTest(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); printf("Join with unjoinable thread\n"); joinWithUnjoinable(); printf("PASSED\n"); return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/joinkk.c0000644000000000000000000000767212623070344014762 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dbmalloc1.c ** ** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions. ** ** Modification History: ** ** 19-May-97 AGarcia - separate the four join tests into different unit test modules. ** AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; /* Program to test joining of threads. Two threads are created. One to be waited upon until it has started. The other to join after it has completed. */ static void lowPriority(void *arg) { } static void highPriority(void *arg) { } void runTest(PRThreadScope scope1, PRThreadScope scope2) { PRThread *low,*high; /* create the low and high priority threads */ low = PR_CreateThread(PR_USER_THREAD, lowPriority, 0, PR_PRIORITY_LOW, scope1, PR_JOINABLE_THREAD, 0); if (!low) { if (debug_mode) printf("\tcannot create low priority thread\n"); else failed_already=1; return; } high = PR_CreateThread(PR_USER_THREAD, highPriority, 0, PR_PRIORITY_HIGH, scope2, PR_JOINABLE_THREAD, 0); if (!high) { if (debug_mode) printf("\tcannot create high priority thread\n"); else failed_already=1; return; } /* Do the joining for both threads */ if (PR_JoinThread(low) == PR_FAILURE) { if (debug_mode) printf("\tcannot join low priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined low priority thread\n"); } if (PR_JoinThread(high) == PR_FAILURE) { if (debug_mode) printf("\tcannot join high priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined high priority thread\n"); } } static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ if (debug_mode) printf("Kernel-Kernel test\n"); runTest(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); if(failed_already) { printf("FAIL\n"); return 1; } else { printf("PASS\n"); return 0; } } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/joinku.c0000644000000000000000000001000312623070344014752 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dbmalloc1.c ** ** Description: Tests PR_SetMallocCountdown PR_ClearMallocCountdown functions. ** ** Modification History: ** ** 19-May-97 AGarcia - separate the four join tests into different unit test modules. ** AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; /* Program to test joining of threads. Two threads are created. One to be waited upon until it has started. The other to join after it has completed. */ static void lowPriority(void *arg) { } static void highPriority(void *arg) { } void runTest(PRThreadScope scope1, PRThreadScope scope2) { PRThread *low,*high; /* create the low and high priority threads */ low = PR_CreateThread(PR_USER_THREAD, lowPriority, 0, PR_PRIORITY_LOW, scope1, PR_JOINABLE_THREAD, 0); if (!low) { if (debug_mode) printf("\tcannot create low priority thread\n"); else failed_already=1; return; } high = PR_CreateThread(PR_USER_THREAD, highPriority, 0, PR_PRIORITY_HIGH, scope2, PR_JOINABLE_THREAD, 0); if (!high) { if (debug_mode) printf("\tcannot create high priority thread\n"); else failed_already=1; return; } /* Do the joining for both threads */ if (PR_JoinThread(low) == PR_FAILURE) { if (debug_mode) printf("\tcannot join low priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined low priority thread\n"); } if (PR_JoinThread(high) == PR_FAILURE) { if (debug_mode) printf("\tcannot join high priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined high priority thread\n"); } } static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); /* main test */ if (debug_mode) printf("Kernel-User test\n"); runTest(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); if(failed_already) { printf("FAIL\n"); return 1; } else { printf("PASS\n"); return 0; } } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/joinuk.c0000644000000000000000000000773312623070344014772 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: joinuk.c ** ** Description: Join kernel - user ** ** Modification History: ** ** 19-May-97 AGarcia - separate the four join tests into different unit test modules. ** AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; /* Program to test joining of threads. Two threads are created. One to be waited upon until it has started. The other to join after it has completed. */ static void lowPriority(void *arg) { } static void highPriority(void *arg) { } void runTest(PRThreadScope scope1, PRThreadScope scope2) { PRThread *low,*high; /* create the low and high priority threads */ low = PR_CreateThread(PR_USER_THREAD, lowPriority, 0, PR_PRIORITY_LOW, scope1, PR_JOINABLE_THREAD, 0); if (!low) { if (debug_mode) printf("\tcannot create low priority thread\n"); else failed_already=1; return; } high = PR_CreateThread(PR_USER_THREAD, highPriority, 0, PR_PRIORITY_HIGH, scope2, PR_JOINABLE_THREAD, 0); if (!high) { if (debug_mode) printf("\tcannot create high priority thread\n"); else failed_already=1; return; } /* Do the joining for both threads */ if (PR_JoinThread(low) == PR_FAILURE) { if (debug_mode) printf("\tcannot join low priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined low priority thread\n"); } if (PR_JoinThread(high) == PR_FAILURE) { if (debug_mode) printf("\tcannot join high priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined high priority thread\n"); } } static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); /* main test */ if (debug_mode) printf("User-Kernel test\n"); runTest(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); if(failed_already) { printf("FAIL\n"); return 1; } else { printf("PASS\n"); return 0; } } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/joinuu.c0000644000000000000000000000774112623070344015003 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: dbmalloc1.c ** ** Description: Join tests user - user ** ** Modification History: ** ** 19-May-97 AGarcia - separate the four join tests into different unit test modules. ** AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; /* Program to test joining of threads. Two threads are created. One to be waited upon until it has started. The other to join after it has completed. */ static void lowPriority(void *arg) { } static void highPriority(void *arg) { } void runTest(PRThreadScope scope1, PRThreadScope scope2) { PRThread *low,*high; /* create the low and high priority threads */ low = PR_CreateThread(PR_USER_THREAD, lowPriority, 0, PR_PRIORITY_LOW, scope1, PR_JOINABLE_THREAD, 0); if (!low) { if (debug_mode) printf("\tcannot create low priority thread\n"); else failed_already=1; return; } high = PR_CreateThread(PR_USER_THREAD, highPriority, 0, PR_PRIORITY_HIGH, scope2, PR_JOINABLE_THREAD, 0); if (!high) { if (debug_mode) printf("\tcannot create high priority thread\n"); else failed_already=1; return; } /* Do the joining for both threads */ if (PR_JoinThread(low) == PR_FAILURE) { if (debug_mode) printf("\tcannot join low priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined low priority thread\n"); } if (PR_JoinThread(high) == PR_FAILURE) { if (debug_mode) printf("\tcannot join high priority thread\n"); else failed_already=1; return; } else { if (debug_mode) printf("\tjoined high priority thread\n"); } } static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); /* main test */ if (debug_mode) printf("User-User test\n"); runTest(PR_LOCAL_THREAD, PR_LOCAL_THREAD); if(failed_already) { printf("FAIL\n"); return 1; } else { printf("PASS\n"); return 0; } } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/layer.c0000644000000000000000000003542012623070344014601 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prprf.h" #include "prlog.h" #include "prnetdb.h" #include "prthread.h" #include "plerror.h" #include "plgetopt.h" #include "prwin16.h" #include #include /* ** Testing layering of I/O ** ** The layered server ** A thread that acts as a server. It creates a TCP listener with a dummy ** layer pushed on top. Then listens for incoming connections. Each connection ** request for connection will be layered as well, accept one request, echo ** it back and close. ** ** The layered client ** Pretty much what you'd expect. */ static PRFileDesc *logFile; static PRDescIdentity identity; static PRNetAddr server_address; static PRIOMethods myMethods; typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity; static PRIntn minor_iterations = 5; static PRIntn major_iterations = 1; static Verbosity verbosity = quiet; static PRUint16 default_port = 12273; static PRFileDesc *PushLayer(PRFileDesc *stack) { PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods); PRStatus rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); return stack; } /* PushLayer */ static PRFileDesc *PushNewLayers(PRFileDesc *stack) { PRDescIdentity tmp_identity; PRFileDesc *layer; PRStatus rv; /* push a dummy layer */ tmp_identity = PR_GetUniqueIdentity("Dummy 1"); layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods()); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); /* push a data procesing layer */ layer = PR_CreateIOLayerStub(identity, &myMethods); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); /* push another dummy layer */ tmp_identity = PR_GetUniqueIdentity("Dummy 2"); layer = PR_CreateIOLayerStub(tmp_identity, PR_GetDefaultIOMethods()); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); PR_ASSERT(PR_SUCCESS == rv); return stack; } /* PushLayer */ #if 0 static PRFileDesc *PopLayer(PRFileDesc *stack) { PRFileDesc *popped = PR_PopIOLayer(stack, identity); if (verbosity > quiet) PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack); popped->dtor(popped); return stack; } /* PopLayer */ #endif static void PR_CALLBACK Client(void *arg) { PRStatus rv; PRUint8 buffer[100]; PRIntn empty_flags = 0; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; /* Initialize the buffer so that Purify won't complain */ memset(buffer, 0, sizeof(buffer)); rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(PR_SUCCESS == rv); while (minor_iterations-- > 0) { bytes_sent = PR_Send( stack, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(sizeof(buffer) == bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Client sending %d bytes\n", bytes_sent); bytes_read = PR_Recv( stack, buffer, bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Client receiving %d bytes\n", bytes_read); PR_ASSERT(bytes_read == bytes_sent); } if (verbosity > quiet) PR_fprintf(logFile, "Client shutting down stack\n"); rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); } /* Client */ static void PR_CALLBACK Server(void *arg) { PRStatus rv; PRUint8 buffer[100]; PRFileDesc *service; PRUintn empty_flags = 0; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; PRNetAddr client_address; service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT); if (verbosity > quiet) PR_fprintf(logFile, "Server accepting connection\n"); do { bytes_read = PR_Recv( service, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT); if (0 != bytes_read) { if (verbosity > chatty) PR_fprintf(logFile, "Server receiving %d bytes\n", bytes_read); PR_ASSERT(bytes_read > 0); bytes_sent = PR_Send( service, buffer, bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server sending %d bytes\n", bytes_sent); PR_ASSERT(bytes_read == bytes_sent); } } while (0 != bytes_read); if (verbosity > quiet) PR_fprintf(logFile, "Server shutting down and closing stack\n"); rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); } /* Server */ static PRInt32 PR_CALLBACK MyRecv( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { char *b = (char*)buf; PRFileDesc *lo = fd->lower; PRInt32 rv, readin = 0, request = 0; rv = lo->methods->recv(lo, &request, sizeof(request), flags, timeout); if (verbosity > chatty) PR_fprintf( logFile, "MyRecv sending permission for %d bytes\n", request); if (0 < rv) { if (verbosity > chatty) PR_fprintf( logFile, "MyRecv received permission request for %d bytes\n", request); rv = lo->methods->send( lo, &request, sizeof(request), flags, timeout); if (0 < rv) { if (verbosity > chatty) PR_fprintf( logFile, "MyRecv sending permission for %d bytes\n", request); while (readin < request) { rv = lo->methods->recv( lo, b + readin, amount - readin, flags, timeout); if (rv <= 0) break; if (verbosity > chatty) PR_fprintf( logFile, "MyRecv received %d bytes\n", rv); readin += rv; } rv = readin; } } return rv; } /* MyRecv */ static PRInt32 PR_CALLBACK MySend( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRFileDesc *lo = fd->lower; const char *b = (const char*)buf; PRInt32 rv, wroteout = 0, request; if (verbosity > chatty) PR_fprintf( logFile, "MySend asking permission to send %d bytes\n", amount); rv = lo->methods->send(lo, &amount, sizeof(amount), flags, timeout); if (0 < rv) { rv = lo->methods->recv( lo, &request, sizeof(request), flags, timeout); if (0 < rv) { PR_ASSERT(request == amount); if (verbosity > chatty) PR_fprintf( logFile, "MySend got permission to send %d bytes\n", request); while (wroteout < request) { rv = lo->methods->send( lo, b + wroteout, request - wroteout, flags, timeout); if (rv <= 0) break; if (verbosity > chatty) PR_fprintf( logFile, "MySend wrote %d bytes\n", rv); wroteout += rv; } rv = amount; } } return rv; } /* MySend */ static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta) { PRIntn verbage = (PRIntn)verbosity + delta; if (verbage < (PRIntn)silent) verbage = (PRIntn)silent; else if (verbage > (PRIntn)noisy) verbage = (PRIntn)noisy; return (Verbosity)verbage; } /* ChangeVerbosity */ int main(int argc, char **argv) { PRStatus rv; PRIntn mits; PLOptStatus os; PRFileDesc *client, *service; PRFileDesc *client_stack, *service_stack; PRNetAddr any_address; const char *server_name = NULL; const PRIOMethods *stubMethods; PRThread *client_thread, *server_thread; PRThreadScope thread_scope = PR_LOCAL_THREAD; PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: server_name = opt->value; break; case 'd': /* debug mode */ if (verbosity < noisy) verbosity = ChangeVerbosity(verbosity, 1); break; case 'q': /* debug mode */ if (verbosity > silent) verbosity = ChangeVerbosity(verbosity, -1); break; case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'C': /* number of threads waiting */ major_iterations = atoi(opt->value); break; case 'c': /* number of client threads */ minor_iterations = atoi(opt->value); break; case 'p': /* default port */ default_port = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); logFile = PR_GetSpecialFD(PR_StandardError); identity = PR_GetUniqueIdentity("Dummy"); stubMethods = PR_GetDefaultIOMethods(); /* ** The protocol we're going to implement is one where in order to initiate ** a send, the sender must first solicit permission. Therefore, every ** send is really a send - receive - send sequence. */ myMethods = *stubMethods; /* first get the entire batch */ myMethods.recv = MyRecv; /* then override the ones we care about */ myMethods.send = MySend; /* then override the ones we care about */ if (NULL == server_name) rv = PR_InitializeNetAddr( PR_IpAddrLoopback, default_port, &server_address); else { rv = PR_StringToNetAddr(server_name, &server_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_InitializeNetAddr( PR_IpAddrNull, default_port, &server_address); } PR_ASSERT(PR_SUCCESS == rv); /* one type w/o layering */ mits = minor_iterations; while (major_iterations-- > 0) { if (verbosity > silent) PR_fprintf(logFile, "Beginning non-layered test\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); minor_iterations = mits; server_thread = PR_CreateThread( PR_USER_THREAD, Server, service, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > silent) PR_fprintf(logFile, "Ending non-layered test\n"); /* with layering */ if (verbosity > silent) PR_fprintf(logFile, "Beginning layered test\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); PushLayer(client); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); PushLayer(service); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); minor_iterations = mits; server_thread = PR_CreateThread( PR_USER_THREAD, Server, service, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); /* with layering, using new style stack */ if (verbosity > silent) PR_fprintf(logFile, "Beginning layered test with new style stack\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); client_stack = PR_CreateIOLayer(client); PushNewLayers(client_stack); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); service_stack = PR_CreateIOLayer(service); PushNewLayers(service_stack); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); minor_iterations = mits; server_thread = PR_CreateThread( PR_USER_THREAD, Server, service_stack, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client_stack, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client_stack); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service_stack); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > silent) PR_fprintf(logFile, "Ending layered test\n"); } return 0; } /* main */ /* layer.c */ nspr-4.11/nspr/pr/tests/lazyinit.c0000644000000000000000000000537712623070344015340 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: lazyinit.c ** Description: Testing lazy initialization ** ** Since you only get to initialize once, you have to rerun the test ** for each test case. The test cases are numbered. If you want to ** add more tests, take the next number and add it to the switch ** statement. ** ** This test is problematic on systems that don't support the notion ** of console output. The workarounds to emulate that feature include ** initializations themselves, which defeats the purpose here. */ #include "prcvar.h" #include "prenv.h" #include "prinit.h" #include "prinrval.h" #include "prio.h" #include "prlock.h" #include "prlog.h" #include "prthread.h" #include "prtypes.h" #include #include static void PR_CALLBACK lazyEntry(void *arg) { PR_ASSERT(NULL == arg); } /* lazyEntry */ int main(int argc, char **argv) { PRUintn pdkey; PRStatus status; char *path = NULL; PRDir *dir = NULL; PRLock *ml = NULL; PRCondVar *cv = NULL; PRThread *thread = NULL; PRIntervalTime interval = 0; PRFileDesc *file, *udp, *tcp, *pair[2]; PRIntn test; if ( argc < 2) { test = 0; } else test = atoi(argv[1]); switch (test) { case 0: ml = PR_NewLock(); break; case 1: interval = PR_SecondsToInterval(1); break; case 2: thread = PR_CreateThread( PR_USER_THREAD, lazyEntry, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); break; case 3: file = PR_Open("/usr/tmp/", PR_RDONLY, 0); break; case 4: udp = PR_NewUDPSocket(); break; case 5: tcp = PR_NewTCPSocket(); break; case 6: dir = PR_OpenDir("/usr/tmp/"); break; case 7: (void)PR_NewThreadPrivateIndex(&pdkey, NULL); break; case 8: path = PR_GetEnv("PATH"); break; case 9: status = PR_NewTCPSocketPair(pair); break; case 10: PR_SetConcurrency(2); break; default: printf( "lazyinit: unrecognized command line argument: %s\n", argv[1] ); printf( "FAIL\n" ); exit( 1 ); break; } /* switch() */ return 0; } /* Lazy */ /* lazyinit.c */ nspr-4.11/nspr/pr/tests/libfilename.c0000644000000000000000000000525612623070344015740 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: libfilename.c ** ** Description: test PR_GetLibraryFilePathname. ** ***********************************************************************/ #include "nspr.h" #include "pprio.h" #include #include #include PRBool debug_mode = PR_FALSE; static PRStatus RunTest(const char *name, PRFuncPtr addr) { char *pathname; PRFileDesc *fd; pathname = PR_GetLibraryFilePathname(name, addr); if (pathname == NULL) { fprintf(stderr, "PR_GetLibraryFilePathname failed\n"); /* we let this test pass if this function is not implemented */ if (PR_GetError() == PR_NOT_IMPLEMENTED_ERROR) { return PR_SUCCESS; } return PR_FAILURE; } if (debug_mode) printf("Pathname is %s\n", pathname); fd = PR_OpenFile(pathname, PR_RDONLY, 0); if (fd == NULL) { fprintf(stderr, "PR_Open failed: %d\n", (int)PR_GetError()); return PR_FAILURE; } if (PR_Close(fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed: %d\n", (int)PR_GetError()); return PR_FAILURE; } PR_Free(pathname); return PR_SUCCESS; } int main(int argc, char **argv) { char *name; PRFuncPtr addr; PRLibrary *lib; PRBool failed = PR_FALSE; if (argc >= 2 && strcmp(argv[1], "-d") == 0) { debug_mode = PR_TRUE; } /* First test a library that is implicitly linked. */ #ifdef WINNT name = PR_Malloc(strlen("libnspr4.dll")+1); strcpy(name, "libnspr4.dll"); #else name = PR_GetLibraryName(NULL, "nspr4"); #endif addr = (PRFuncPtr)PR_GetTCPMethods()->close; if (RunTest(name, addr) == PR_FAILURE) { failed = PR_TRUE; } PR_FreeLibraryName(name); /* Next test a library that is dynamically loaded. */ name = PR_GetLibraryName("dll", "my"); if (debug_mode) printf("Loading library %s\n", name); lib = PR_LoadLibrary(name); if (!lib) { fprintf(stderr, "PR_LoadLibrary failed\n"); exit(1); } PR_FreeLibraryName(name); name = PR_GetLibraryName(NULL, "my"); addr = PR_FindFunctionSymbol(lib, "My_GetValue"); if (RunTest(name, addr) == PR_FAILURE) { failed = PR_TRUE; } PR_FreeLibraryName(name); PR_UnloadLibrary(lib); if (failed) { printf("FAIL\n"); return 1; } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/lltest.c0000644000000000000000000006216612623070344015003 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** testll.c -- test suite for 64bit integer (longlong) operations ** ** Summary: testll [-d] | [-h] ** ** Where: ** -d set debug mode on; displays individual test failures ** -v verbose mode; displays progress in test, plus -d ** -h gives usage message. ** ** Description: ** lltest.c tests the functions defined in NSPR 2.0's prlong.h. ** ** Successive tests begin to depend on other LL functions working ** correctly. So, ... Do not change the order of the tests as run ** from main(). ** ** Caveats: ** Do not even begin to think that this is an exhaustive test! ** ** These tests try a little of everything, but not all boundary ** conditions and limits are tested. ** You want better coverage? ... Add it. ** ** --- ** Author: Lawrence Hardiman . ** --- ** Revision History: ** 01-Oct-1997. Original implementation. ** */ #include "nspr.h" #include "plgetopt.h" /* --- Local Definitions --- */ #define ReportProgress(m) if (verboseMode) PR_fprintf(output, (m)); /* --- Global variables --- */ static PRIntn failedAlready = 0; static PRFileDesc* output = NULL; static PRBool debugMode = PR_FALSE; static PRBool verboseMode = PR_FALSE; /* ** Constants used in tests. */ const PRInt64 bigZero = LL_INIT( 0, 0 ); const PRInt64 bigOne = LL_INIT( 0, 1 ); const PRInt64 bigTwo = LL_INIT( 0, 2 ); const PRInt64 bigSixTeen = LL_INIT( 0, 16 ); const PRInt64 bigThirtyTwo = LL_INIT( 0, 32 ); const PRInt64 bigMinusOne = LL_INIT( 0xffffffff, 0xffffffff ); const PRInt64 bigMinusTwo = LL_INIT( 0xffffffff, 0xfffffffe ); const PRInt64 bigNumber = LL_INIT( 0x7fffffff, 0xffffffff ); const PRInt64 bigMinusNumber = LL_INIT( 0x80000000, 0x00000001 ); const PRInt64 bigMaxInt32 = LL_INIT( 0x00000000, 0x7fffffff ); const PRInt64 big2To31 = LL_INIT( 0x00000000, 0x80000000 ); const PRUint64 bigZeroFox = LL_INIT( 0x00000000, 0xffffffff ); const PRUint64 bigFoxFox = LL_INIT( 0xffffffff, 0xffffffff ); const PRUint64 bigFoxZero = LL_INIT( 0xffffffff, 0x00000000 ); const PRUint64 bigEightZero = LL_INIT( 0x80000000, 0x00000000 ); const PRUint64 big64K = LL_INIT( 0x00000000, 0x00010000 ); const PRInt64 bigInt0 = LL_INIT( 0x01a00000, 0x00001000 ); const PRInt64 bigInt1 = LL_INIT( 0x01a00000, 0x00001100 ); const PRInt64 bigInt2 = LL_INIT( 0x01a00000, 0x00000100 ); const PRInt64 bigInt3 = LL_INIT( 0x01a00001, 0x00001000 ); const PRInt64 bigInt4 = LL_INIT( 0x01a00001, 0x00001100 ); const PRInt64 bigInt5 = LL_INIT( 0x01a00001, 0x00000100 ); const PRInt64 bigInt6 = LL_INIT( 0xb1a00000, 0x00001000 ); const PRInt64 bigInt7 = LL_INIT( 0xb1a00000, 0x00001100 ); const PRInt64 bigInt8 = LL_INIT( 0xb1a00000, 0x00000100 ); const PRInt64 bigInt9 = LL_INIT( 0xb1a00001, 0x00001000 ); const PRInt64 bigInt10 = LL_INIT( 0xb1a00001, 0x00001100 ); const PRInt64 bigInt11 = LL_INIT( 0xb1a00001, 0x00000100 ); const PRInt32 one = 1l; const PRInt32 minusOne = -1l; const PRInt32 sixteen = 16l; const PRInt32 thirtyTwo = 32l; const PRInt32 sixtyThree = 63l; /* ** SetFailed() -- Report individual test failure ** */ static void SetFailed( char *what, char *how ) { failedAlready = 1; if ( debugMode ) PR_fprintf(output, "%s: failed: %s\n", what, how ); return; } static void ResultFailed( char *what, char *how, PRInt64 expected, PRInt64 got) { if ( debugMode) { SetFailed( what, how ); PR_fprintf(output, "Expected: 0x%llx Got: 0x%llx\n", expected, got ); } return; } /* ** TestAssignment() -- Test the assignment */ static void TestAssignment( void ) { PRInt64 zero = LL_Zero(); PRInt64 min = LL_MinInt(); PRInt64 max = LL_MaxInt(); if (!LL_EQ(zero, bigZero)) SetFailed("LL_EQ(zero, bigZero)", "!="); if (!LL_CMP(max, >, min)) SetFailed("LL_CMP(max, >, min)", "!>"); } /* ** TestComparisons() -- Test the longlong comparison operations */ static void TestComparisons( void ) { ReportProgress("Testing Comparisons Operations\n"); /* test for zero */ if ( !LL_IS_ZERO( bigZero )) SetFailed( "LL_IS_ZERO", "Zero is not zero" ); if ( LL_IS_ZERO( bigOne )) SetFailed( "LL_IS_ZERO", "One tests as zero" ); if ( LL_IS_ZERO( bigMinusOne )) SetFailed( "LL_IS_ZERO", "Minus One tests as zero" ); /* test equal */ if ( !LL_EQ( bigZero, bigZero )) SetFailed( "LL_EQ", "zero EQ zero"); if ( !LL_EQ( bigOne, bigOne )) SetFailed( "LL_EQ", "one EQ one" ); if ( !LL_EQ( bigNumber, bigNumber )) SetFailed( "LL_EQ", "bigNumber EQ bigNumber" ); if ( !LL_EQ( bigMinusOne, bigMinusOne )) SetFailed( "LL_EQ", "minus one EQ minus one"); if ( LL_EQ( bigZero, bigOne )) SetFailed( "LL_EQ", "zero EQ one"); if ( LL_EQ( bigOne, bigZero )) SetFailed( "LL_EQ", "one EQ zero" ); if ( LL_EQ( bigMinusOne, bigOne )) SetFailed( "LL_EQ", "minus one EQ one"); if ( LL_EQ( bigNumber, bigOne )) SetFailed( "LL_EQ", "bigNumber EQ one"); /* test not equal */ if ( LL_NE( bigZero, bigZero )) SetFailed( "LL_NE", "0 NE 0"); if ( LL_NE( bigOne, bigOne )) SetFailed( "LL_NE", "1 NE 1"); if ( LL_NE( bigMinusOne, bigMinusOne )) SetFailed( "LL_NE", "-1 NE -1"); if ( LL_NE( bigNumber, bigNumber )) SetFailed( "LL_NE", "n NE n"); if ( LL_NE( bigMinusNumber, bigMinusNumber )) SetFailed( "LL_NE", "-n NE -n"); if ( !LL_NE( bigZero, bigOne)) SetFailed( "LL_NE", "0 NE 1"); if ( !LL_NE( bigOne, bigMinusNumber)) SetFailed( "LL_NE", "1 NE -n"); /* Greater than or equal to zero */ if ( !LL_GE_ZERO( bigZero )) SetFailed( "LL_GE_ZERO", "0"); if ( !LL_GE_ZERO( bigOne )) SetFailed( "LL_GE_ZERO", "1"); if ( !LL_GE_ZERO( bigNumber )) SetFailed( "LL_GE_ZERO", "n"); if ( LL_GE_ZERO( bigMinusOne )) SetFailed( "LL_GE_ZERO", "-1"); if ( LL_GE_ZERO( bigMinusNumber )) SetFailed( "LL_GE_ZERO", "-n"); /* Algebraic Compare two values */ if ( !LL_CMP( bigZero, ==, bigZero )) SetFailed( "LL_CMP", "0 == 0"); if ( LL_CMP( bigZero, >, bigZero )) SetFailed( "LL_CMP", "0 > 0"); if ( LL_CMP( bigZero, <, bigZero )) SetFailed( "LL_CMP", "0 < 0"); if ( LL_CMP( bigNumber, <, bigOne )) SetFailed( "LL_CMP", "n < 1"); if ( !LL_CMP( bigNumber, >, bigOne )) SetFailed( "LL_CMP", "n <= 1"); if ( LL_CMP( bigOne, >, bigNumber )) SetFailed( "LL_CMP", "1 > n"); if ( LL_CMP( bigMinusNumber, >, bigNumber )) SetFailed( "LL_CMP", "-n > n"); if ( LL_CMP( bigNumber, !=, bigNumber)) SetFailed( "LL_CMP", "n != n"); if ( !LL_CMP( bigMinusOne, >, bigMinusTwo )) SetFailed( "LL_CMP", "-1 <= -2"); if ( !LL_CMP( bigMaxInt32, <, big2To31 )) SetFailed( "LL_CMP", "Max 32-bit signed int >= 2^31"); /* Two positive numbers */ if ( !LL_CMP( bigInt0, <=, bigInt0 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt0, <=, bigInt1 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( LL_CMP( bigInt0, <=, bigInt2 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt0, <=, bigInt3 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt0, <=, bigInt4 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt0, <=, bigInt5 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); /* Two negative numbers */ if ( !LL_CMP( bigInt6, <=, bigInt6 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt6, <=, bigInt7 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( LL_CMP( bigInt6, <=, bigInt8 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt6, <=, bigInt9 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt6, <=, bigInt10 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( !LL_CMP( bigInt6, <=, bigInt11 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); /* One positive, one negative */ if ( LL_CMP( bigInt0, <=, bigInt6 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( LL_CMP( bigInt0, <=, bigInt7 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); if ( LL_CMP( bigInt0, <=, bigInt8 )) SetFailed( "LL_CMP", "LL_CMP(<=) failed"); /* Bitwise Compare two numbers */ if ( !LL_UCMP( bigZero, ==, bigZero )) SetFailed( "LL_UCMP", "0 == 0"); if ( LL_UCMP( bigZero, >, bigZero )) SetFailed( "LL_UCMP", "0 > 0"); if ( LL_UCMP( bigZero, <, bigZero )) SetFailed( "LL_UCMP", "0 < 0"); if ( LL_UCMP( bigNumber, <, bigOne )) SetFailed( "LL_UCMP", "n < 1"); if ( !LL_UCMP( bigNumber, >, bigOne )) SetFailed( "LL_UCMP", "n < 1"); if ( LL_UCMP( bigOne, >, bigNumber )) SetFailed( "LL_UCMP", "1 > n"); if ( LL_UCMP( bigMinusNumber, <, bigNumber )) SetFailed( "LL_UCMP", "-n < n"); /* Two positive numbers */ if ( !LL_UCMP( bigInt0, <=, bigInt0 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt0, <=, bigInt1 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( LL_UCMP( bigInt0, <=, bigInt2 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt0, <=, bigInt3 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt0, <=, bigInt4 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt0, <=, bigInt5 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); /* Two negative numbers */ if ( !LL_UCMP( bigInt6, <=, bigInt6 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt6, <=, bigInt7 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( LL_UCMP( bigInt6, <=, bigInt8 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt6, <=, bigInt9 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt6, <=, bigInt10 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt6, <=, bigInt11 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); /* One positive, one negative */ if ( !LL_UCMP( bigInt0, <=, bigInt6 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt0, <=, bigInt7 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); if ( !LL_UCMP( bigInt0, <=, bigInt8 )) SetFailed( "LL_UCMP", "LL_UCMP(<=) failed"); return; } /* ** TestLogicalOperations() -- Tests for AND, OR, ... ** */ static void TestLogicalOperations( void ) { PRUint64 result, result2; ReportProgress("Testing Logical Operations\n"); /* Test AND */ LL_AND( result, bigZero, bigZero ); if ( !LL_IS_ZERO( result )) ResultFailed( "LL_AND", "0 & 0", bigZero, result ); LL_AND( result, bigOne, bigOne ); if ( LL_IS_ZERO( result )) ResultFailed( "LL_AND", "1 & 1", bigOne, result ); LL_AND( result, bigZero, bigOne ); if ( !LL_IS_ZERO( result )) ResultFailed( "LL_AND", "1 & 1", bigZero, result ); LL_AND( result, bigMinusOne, bigMinusOne ); if ( !LL_UCMP( result, ==, bigMinusOne )) ResultFailed( "LL_AND", "-1 & -1", bigMinusOne, result ); /* test OR */ LL_OR( result, bigZero, bigZero ); if ( !LL_IS_ZERO( result )) ResultFailed( "LL_OR", "0 | 1", bigZero, result); LL_OR( result, bigZero, bigOne ); if ( LL_IS_ZERO( result )) ResultFailed( "LL_OR", "0 | 1", bigOne, result ); LL_OR( result, bigZero, bigMinusNumber ); if ( !LL_UCMP( result, ==, bigMinusNumber )) ResultFailed( "LL_OR", "0 | -n", bigMinusNumber, result); LL_OR( result, bigMinusNumber, bigZero ); if ( !LL_UCMP( result, ==, bigMinusNumber )) ResultFailed( "LL_OR", "-n | 0", bigMinusNumber, result ); /* test XOR */ LL_XOR( result, bigZero, bigZero ); if ( LL_UCMP( result, !=, bigZero )) ResultFailed( "LL_XOR", "0 ^ 0", bigZero, result); LL_XOR( result, bigOne, bigZero ); if ( LL_UCMP( result, !=, bigOne )) ResultFailed( "LL_XOR", "1 ^ 0", bigZero, result ); LL_XOR( result, bigMinusNumber, bigZero ); if ( LL_UCMP( result, !=, bigMinusNumber )) ResultFailed( "LL_XOR", "-n ^ 0", bigMinusNumber, result ); LL_XOR( result, bigMinusNumber, bigMinusNumber ); if ( LL_UCMP( result, !=, bigZero )) ResultFailed( "LL_XOR", "-n ^ -n", bigMinusNumber, result); /* test OR2. */ result = bigZero; LL_OR2( result, bigOne ); if ( LL_UCMP( result, !=, bigOne )) ResultFailed( "LL_OR2", "(r=0) |= 1", bigOne, result); result = bigOne; LL_OR2( result, bigNumber ); if ( LL_UCMP( result, !=, bigNumber )) ResultFailed( "LL_OR2", "(r=1) |= n", bigNumber, result); result = bigMinusNumber; LL_OR2( result, bigMinusNumber ); if ( LL_UCMP( result, !=, bigMinusNumber )) ResultFailed( "LL_OR2", "(r=-n) |= -n", bigMinusNumber, result); /* test NOT */ LL_NOT( result, bigMinusNumber); LL_NOT( result2, result); if ( LL_UCMP( result2, !=, bigMinusNumber )) ResultFailed( "LL_NOT", "r != ~(~-n)", bigMinusNumber, result); /* test Negation */ LL_NEG( result, bigMinusNumber ); LL_NEG( result2, result ); if ( LL_CMP( result2, !=, bigMinusNumber )) ResultFailed( "LL_NEG", "r != -(-(-n))", bigMinusNumber, result); return; } /* ** TestConversion() -- Test Conversion Operations ** */ static void TestConversion( void ) { PRInt64 result; PRInt64 resultU; PRInt32 result32; PRUint32 resultU32; float resultF; PRFloat64 resultD; ReportProgress("Testing Conversion Operations\n"); /* LL_L2I -- Convert to signed 32bit */ LL_L2I(result32, bigOne ); if ( result32 != one ) SetFailed( "LL_L2I", "r != 1"); LL_L2I(result32, bigMinusOne ); if ( result32 != minusOne ) SetFailed( "LL_L2I", "r != -1"); /* LL_L2UI -- Convert 64bit to unsigned 32bit */ LL_L2UI( resultU32, bigMinusOne ); if ( resultU32 != (PRUint32) minusOne ) SetFailed( "LL_L2UI", "r != -1"); LL_L2UI( resultU32, bigOne ); if ( resultU32 != (PRUint32) one ) SetFailed( "LL_L2UI", "r != 1"); /* LL_L2F -- Convert to 32bit floating point */ LL_L2F( resultF, bigOne ); if ( resultF != 1.0 ) SetFailed( "LL_L2F", "r != 1.0"); LL_L2F( resultF, bigMinusOne ); if ( resultF != -1.0 ) SetFailed( "LL_L2F", "r != 1.0"); /* LL_L2D -- Convert to 64bit floating point */ LL_L2D( resultD, bigOne ); if ( resultD != 1.0L ) SetFailed( "LL_L2D", "r != 1.0"); LL_L2D( resultD, bigMinusOne ); if ( resultD != -1.0L ) SetFailed( "LL_L2D", "r != -1.0"); /* LL_I2L -- Convert 32bit signed to 64bit signed */ LL_I2L( result, one ); if ( LL_CMP(result, !=, bigOne )) SetFailed( "LL_I2L", "r != 1"); LL_I2L( result, minusOne ); if ( LL_CMP(result, !=, bigMinusOne )) SetFailed( "LL_I2L", "r != -1"); /* LL_UI2L -- Convert 32bit unsigned to 64bit unsigned */ LL_UI2L( resultU, (PRUint32) one ); if ( LL_CMP(resultU, !=, bigOne )) SetFailed( "LL_UI2L", "r != 1"); /* [lth.] This did not behave as expected, but it is correct */ LL_UI2L( resultU, (PRUint32) minusOne ); if ( LL_CMP(resultU, !=, bigZeroFox )) ResultFailed( "LL_UI2L", "r != -1", bigZeroFox, resultU); /* LL_F2L -- Convert 32bit float to 64bit signed */ LL_F2L( result, 1.0 ); if ( LL_CMP(result, !=, bigOne )) SetFailed( "LL_F2L", "r != 1"); LL_F2L( result, -1.0 ); if ( LL_CMP(result, !=, bigMinusOne )) SetFailed( "LL_F2L", "r != -1"); /* LL_D2L -- Convert 64bit Float to 64bit signed */ LL_D2L( result, 1.0L ); if ( LL_CMP(result, !=, bigOne )) SetFailed( "LL_D2L", "r != 1"); LL_D2L( result, -1.0L ); if ( LL_CMP(result, !=, bigMinusOne )) SetFailed( "LL_D2L", "r != -1"); return; } static void ShiftCompileOnly() { /* ** This function is only compiled, never called. ** The real test is to see if it compiles w/o ** warnings. This is no small feat, by the way. */ PRInt64 ia, ib; PRUint64 ua, ub; LL_SHR(ia, ib, 32); LL_SHL(ia, ib, 32); LL_USHR(ua, ub, 32); LL_ISHL(ia, 49, 32); } /* ShiftCompileOnly */ /* ** TestShift() -- Test Shifting Operations ** */ static void TestShift( void ) { static const PRInt64 largeTwoZero = LL_INIT( 0x00000002, 0x00000000 ); PRInt64 result; PRUint64 resultU; ReportProgress("Testing Shifting Operations\n"); /* LL_SHL -- Shift left algebraic */ LL_SHL( result, bigOne, one ); if ( LL_CMP( result, !=, bigTwo )) ResultFailed( "LL_SHL", "r != 2", bigOne, result ); LL_SHL( result, bigTwo, thirtyTwo ); if ( LL_CMP( result, !=, largeTwoZero )) ResultFailed( "LL_SHL", "r != twoZero", largeTwoZero, result); /* LL_SHR -- Shift right algebraic */ LL_SHR( result, bigFoxZero, thirtyTwo ); if ( LL_CMP( result, !=, bigMinusOne )) ResultFailed( "LL_SHR", "r != -1", bigMinusOne, result); LL_SHR( result, bigTwo, one ); if ( LL_CMP( result, !=, bigOne )) ResultFailed( "LL_SHR", "r != 1", bigOne, result); LL_SHR( result, bigFoxFox, thirtyTwo ); if ( LL_CMP( result, !=, bigMinusOne )) ResultFailed( "LL_SHR", "r != -1 (was ff,ff)", bigMinusOne, result); /* LL_USHR -- Logical shift right */ LL_USHR( resultU, bigZeroFox, thirtyTwo ); if ( LL_UCMP( resultU, !=, bigZero )) ResultFailed( "LL_USHR", "r != 0 ", bigZero, result); LL_USHR( resultU, bigFoxFox, thirtyTwo ); if ( LL_UCMP( resultU, !=, bigZeroFox )) ResultFailed( "LL_USHR", "r != 0 ", bigZeroFox, result); /* LL_ISHL -- Shift a 32bit integer into a 64bit result */ LL_ISHL( resultU, minusOne, thirtyTwo ); if ( LL_UCMP( resultU, !=, bigFoxZero )) ResultFailed( "LL_ISHL", "r != ff,00 ", bigFoxZero, result); LL_ISHL( resultU, one, sixtyThree ); if ( LL_UCMP( resultU, !=, bigEightZero )) ResultFailed( "LL_ISHL", "r != 80,00 ", bigEightZero, result); LL_ISHL( resultU, one, sixteen ); if ( LL_UCMP( resultU, !=, big64K )) ResultFailed( "LL_ISHL", "r != 64K ", big64K, resultU); return; } /* ** TestArithmetic() -- Test arithmetic operations. ** */ static void TestArithmetic( void ) { PRInt64 largeVal = LL_INIT( 0x00000001, 0xffffffff ); PRInt64 largeValPlusOne = LL_INIT( 0x00000002, 0x00000000 ); PRInt64 largeValTimesTwo = LL_INIT( 0x00000003, 0xfffffffe ); PRInt64 largeMultCand = LL_INIT( 0x00000000, 0x7fffffff ); PRInt64 largeMinusMultCand = LL_INIT( 0xffffffff, 0x10000001 ); PRInt64 largeMultCandx64K = LL_INIT( 0x00007fff, 0xffff0000 ); PRInt64 largeNumSHL5 = LL_INIT( 0x0000001f, 0xffffffe0 ); PRInt64 result, result2; /* Addition */ LL_ADD( result, bigOne, bigOne ); if ( LL_CMP( result, !=, bigTwo )) ResultFailed( "LL_ADD", "r != 1 + 1", bigTwo, result); LL_ADD( result, bigMinusOne, bigOne ); if ( LL_CMP( result, !=, bigZero )) ResultFailed( "LL_ADD", "r != -1 + 1", bigOne, result); LL_ADD( result, largeVal, bigOne ); if ( LL_CMP( result, !=, largeValPlusOne )) ResultFailed( "LL_ADD", "lVP1 != lV + 1", largeValPlusOne, result); /* Subtraction */ LL_SUB( result, bigOne, bigOne ); if ( LL_CMP( result, !=, bigZero )) ResultFailed( "LL_SUB", "r != 1 - 1", bigZero, result); LL_SUB( result, bigTwo, bigOne ); if ( LL_CMP( result, !=, bigOne )) ResultFailed( "LL_SUB", "r != 2 - 1", bigOne, result); LL_SUB( result, largeValPlusOne, bigOne ); if ( LL_CMP( result, !=, largeVal )) ResultFailed( "LL_SUB", "r != lVP1 - 1", largeVal, result); /* Multiply */ LL_MUL( result, largeVal, bigTwo ); if ( LL_CMP( result, !=, largeValTimesTwo )) ResultFailed( "LL_MUL", "r != lV*2", largeValTimesTwo, result); LL_MUL( result, largeMultCand, big64K ); if ( LL_CMP( result, !=, largeMultCandx64K )) ResultFailed( "LL_MUL", "r != lV*64K", largeMultCandx64K, result); LL_NEG( result2, largeMultCand ); LL_MUL( result, largeMultCand, bigMinusOne ); if ( LL_CMP( result, !=, result2 )) ResultFailed( "LL_MUL", "r != -lMC", result2, result); LL_SHL( result2, bigZeroFox, 5); LL_MUL( result, bigZeroFox, bigThirtyTwo ); if ( LL_CMP( result, !=, largeNumSHL5 )) ResultFailed( "LL_MUL", "r != 0f<<5", largeNumSHL5, result ); /* LL_DIV() Division */ LL_DIV( result, bigOne, bigOne); if ( LL_CMP( result, !=, bigOne )) ResultFailed( "LL_DIV", "1 != 1", bigOne, result); LL_DIV( result, bigNumber, bigOne ); if ( LL_CMP( result, !=, bigNumber )) ResultFailed( "LL_DIV", "r != n / 1", bigNumber, result); LL_DIV( result, bigNumber, bigMinusOne ); if ( LL_CMP( result, !=, bigMinusNumber )) ResultFailed( "LL_DIV", "r != n / -1", bigMinusNumber, result); LL_DIV( result, bigMinusNumber, bigMinusOne ); if ( LL_CMP( result, !=, bigNumber )) ResultFailed( "LL_DIV", "r != -n / -1", bigNumber, result); LL_SHL( result2, bigZeroFox, 5 ); LL_DIV( result, result2, bigOne ); if ( LL_CMP( result, !=, result2 )) ResultFailed( "LL_DIV", "0f<<5 != 0f<<5", result2, result); LL_SHL( result2, bigZeroFox, 5 ); LL_NEG( result2, result2 ); LL_DIV( result, result2, bigOne ); if ( LL_CMP( result, !=, result2 )) ResultFailed( "LL_DIV", "-0f<<5 != -0f<<5", result2, result); LL_SHL( result2, bigZeroFox, 17 ); LL_DIV( result, result2, bigMinusOne ); LL_NEG( result2, result2 ); if ( LL_CMP( result, !=, result2 )) ResultFailed( "LL_DIV", "-0f<<17 != -0f<<17", result2, result); /* LL_MOD() Modulo Division */ LL_ADD( result2, bigThirtyTwo, bigOne ); LL_MOD( result, result2, bigSixTeen ); if ( LL_CMP( result, !=, bigOne )) ResultFailed( "LL_MOD", "r != 1", bigSixTeen, result); LL_MUL( result2, bigZeroFox, bigThirtyTwo ); LL_ADD( result2, result2, bigSixTeen); LL_MOD( result, result2, bigThirtyTwo ); if ( LL_CMP( result, !=, bigSixTeen )) ResultFailed( "LL_MOD", "r != 16", bigSixTeen, result); /* LL_UDIVMOD */ LL_DIV( result, bigOne, bigOne); if ( LL_CMP( result, !=, bigOne )) ResultFailed( "LL_DIV", "r != 16", bigSixTeen, result); return; } static void TestWellknowns(void) { PRInt64 max = LL_MAXINT, min = LL_MININT, zero = LL_ZERO; PRInt64 mmax = LL_MaxInt(), mmin = LL_MinInt(), mzero = LL_Zero(); if (LL_NE(max, mmax)) ResultFailed( "max, mmax", "max != mmax", max, mmax); if (LL_NE(min, mmin)) ResultFailed( "min, mmin", "min != mmin", max, mmin); if (LL_NE(zero, mzero)) ResultFailed( "zero, mzero", "zero != mzero", zero, mzero); } /* TestWellknowns */ /* ** Initialize() -- Initialize the test case ** ** Parse command line options ** */ static PRIntn Initialize( PRIntn argc, char **argv ) { PLOptState *opt = PL_CreateOptState(argc, argv, "dvh"); PLOptStatus os; /* ** Parse command line options */ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* set debug mode */ debugMode = PR_TRUE; break; case 'v': /* set verbose mode */ verboseMode = PR_TRUE; debugMode = PR_TRUE; break; case 'h': /* user wants some guidance */ default: PR_fprintf(output, "You get help.\n"); return(1); } } PL_DestroyOptState(opt); return(0); } int main(int argc, char **argv) { PR_STDIO_INIT(); output = PR_GetSpecialFD(PR_StandardError); if ( Initialize( argc, argv )) return(1); TestAssignment(); TestComparisons(); TestLogicalOperations(); TestConversion(); TestShift(); TestArithmetic(); TestWellknowns(); /* ** That's all folks! */ if ( failedAlready ) { PR_fprintf(output, "FAIL\n");\ } else { PR_fprintf(output, "PASS\n");\ } return failedAlready; } /* end main() */ nspr-4.11/nspr/pr/tests/lock.c0000644000000000000000000003654012623070344014421 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: lock.c ** Purpose: test basic locking functions ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ** ** 11-Aug-97 LarryH. Win16 port of NSPR. ** - Added "PASS", "FAIL" messages on completion. ** - Change stack variables to static scope variables ** because of shadow-stack use by Win16 ** - Added PR_CALLBACK attribute to functions called by NSPR ** - Added command line arguments: ** - l to control the number of loops ** - c to control the number of CPUs. ** (was positional argv). ** ** ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prio.h" #include "prcmon.h" #include "prinit.h" #include "prinrval.h" #include "prprf.h" #include "prlock.h" #include "prlog.h" #include "prmon.h" #include "prmem.h" #include "prthread.h" #include "prtypes.h" #include "plstr.h" #include #if defined(XP_UNIX) #include #endif static PRIntn failed_already=0; static PRFileDesc *std_err = NULL; static PRBool verbosity = PR_FALSE; static PRBool debug_mode = PR_FALSE; const static PRIntervalTime contention_interval = 50; typedef struct LockContentious_s { PRLock *ml; PRInt32 loops; PRUint32 contender; PRUint32 contentious; PRIntervalTime overhead; PRIntervalTime interval; } LockContentious_t; typedef struct MonitorContentious_s { PRMonitor *ml; PRInt32 loops; PRUint32 contender; PRUint32 contentious; PRIntervalTime overhead; PRIntervalTime interval; } MonitorContentious_t; static PRIntervalTime Sleeper(PRUint32 loops) { PRIntervalTime predicted = 0; while (loops-- > 0) { predicted += contention_interval; (void)PR_Sleep(contention_interval); } return predicted; } /* Sleeper */ /* ** BASIC LOCKS */ static PRIntervalTime MakeLock(PRUint32 loops) { PRLock *ml = NULL; while (loops-- > 0) { ml = PR_NewLock(); PR_DestroyLock(ml); ml = NULL; } return 0; } /* MakeLock */ static PRIntervalTime NonContentiousLock(PRUint32 loops) { PRLock *ml = NULL; ml = PR_NewLock(); while (loops-- > 0) { PR_Lock(ml); PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(ml); PR_Unlock(ml); } PR_DestroyLock(ml); return 0; } /* NonContentiousLock */ static void PR_CALLBACK LockContender(void *arg) { LockContentious_t *contention = (LockContentious_t*)arg; while (contention->loops-- > 0) { PR_Lock(contention->ml); PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml); contention->contender+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml); PR_Unlock(contention->ml); } } /* LockContender */ static PRIntervalTime ContentiousLock(PRUint32 loops) { PRStatus status; PRThread *thread = NULL; LockContentious_t * contention; PRIntervalTime rv, overhead, timein = PR_IntervalNow(); contention = PR_NEWZAP(LockContentious_t); contention->loops = loops; contention->overhead = 0; contention->ml = PR_NewLock(); contention->interval = contention_interval; thread = PR_CreateThread( PR_USER_THREAD, LockContender, contention, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(thread != NULL); overhead = PR_IntervalNow() - timein; while (contention->loops-- > 0) { PR_Lock(contention->ml); PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml); contention->contentious+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(contention->ml); PR_Unlock(contention->ml); } timein = PR_IntervalNow(); status = PR_JoinThread(thread); PR_DestroyLock(contention->ml); overhead += (PR_IntervalNow() - timein); rv = overhead + contention->overhead; if (verbosity) PR_fprintf( std_err, "Access ratio: %u to %u\n", contention->contentious, contention->contender); PR_Free(contention); return rv; } /* ContentiousLock */ /* ** MONITORS */ static PRIntervalTime MakeMonitor(PRUint32 loops) { PRMonitor *ml = NULL; while (loops-- > 0) { ml = PR_NewMonitor(); PR_DestroyMonitor(ml); ml = NULL; } return 0; } /* MakeMonitor */ static PRIntervalTime NonContentiousMonitor(PRUint32 loops) { PRMonitor *ml = NULL; ml = PR_NewMonitor(); while (loops-- > 0) { PR_EnterMonitor(ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml); PR_ExitMonitor(ml); } PR_DestroyMonitor(ml); return 0; } /* NonContentiousMonitor */ static void PR_CALLBACK TryEntry(void *arg) { PRMonitor *ml = (PRMonitor*)arg; if (debug_mode) PR_fprintf(std_err, "Reentrant thread created\n"); PR_EnterMonitor(ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml); if (debug_mode) PR_fprintf(std_err, "Reentrant thread acquired monitor\n"); PR_ExitMonitor(ml); if (debug_mode) PR_fprintf(std_err, "Reentrant thread released monitor\n"); } /* TryEntry */ static PRIntervalTime ReentrantMonitor(PRUint32 loops) { PRStatus status; PRThread *thread; PRMonitor *ml = PR_NewMonitor(); if (debug_mode) PR_fprintf(std_err, "\nMonitor created for reentrant test\n"); PR_EnterMonitor(ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml); PR_EnterMonitor(ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml); if (debug_mode) PR_fprintf(std_err, "Monitor acquired twice\n"); thread = PR_CreateThread( PR_USER_THREAD, TryEntry, ml, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(thread != NULL); PR_Sleep(PR_SecondsToInterval(1)); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml); PR_ExitMonitor(ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(ml); if (debug_mode) PR_fprintf(std_err, "Monitor released first time\n"); PR_ExitMonitor(ml); if (debug_mode) PR_fprintf(std_err, "Monitor released second time\n"); status = PR_JoinThread(thread); if (debug_mode) PR_fprintf(std_err, "Reentrant thread joined %s\n", (status == PR_SUCCESS) ? "successfully" : "in error"); PR_DestroyMonitor(ml); return 0; } /* ReentrantMonitor */ static void PR_CALLBACK MonitorContender(void *arg) { MonitorContentious_t *contention = (MonitorContentious_t*)arg; while (contention->loops-- > 0) { PR_EnterMonitor(contention->ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml); contention->contender+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml); PR_ExitMonitor(contention->ml); } } /* MonitorContender */ static PRUint32 ContentiousMonitor(PRUint32 loops) { PRStatus status; PRThread *thread = NULL; MonitorContentious_t * contention; PRIntervalTime rv, overhead, timein = PR_IntervalNow(); contention = PR_NEWZAP(MonitorContentious_t); contention->loops = loops; contention->overhead = 0; contention->ml = PR_NewMonitor(); contention->interval = contention_interval; thread = PR_CreateThread( PR_USER_THREAD, MonitorContender, contention, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(thread != NULL); overhead = PR_IntervalNow() - timein; while (contention->loops-- > 0) { PR_EnterMonitor(contention->ml); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml); contention->contentious+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_ASSERT_CURRENT_THREAD_IN_MONITOR(contention->ml); PR_ExitMonitor(contention->ml); } timein = PR_IntervalNow(); status = PR_JoinThread(thread); PR_DestroyMonitor(contention->ml); overhead += (PR_IntervalNow() - timein); rv = overhead + contention->overhead; if (verbosity) PR_fprintf( std_err, "Access ratio: %u to %u\n", contention->contentious, contention->contender); PR_Free(contention); return rv; } /* ContentiousMonitor */ /* ** CACHED MONITORS */ static PRIntervalTime NonContentiousCMonitor(PRUint32 loops) { MonitorContentious_t contention; while (loops-- > 0) { PR_CEnterMonitor(&contention); PR_CExitMonitor(&contention); } return 0; } /* NonContentiousCMonitor */ static void PR_CALLBACK Contender(void *arg) { MonitorContentious_t *contention = (MonitorContentious_t*)arg; while (contention->loops-- > 0) { PR_CEnterMonitor(contention); contention->contender+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_CExitMonitor(contention); } } /* Contender */ static PRIntervalTime ContentiousCMonitor(PRUint32 loops) { PRStatus status; PRThread *thread = NULL; MonitorContentious_t * contention; PRIntervalTime overhead, timein = PR_IntervalNow(); contention = PR_NEWZAP(MonitorContentious_t); contention->ml = NULL; contention->loops = loops; contention->interval = contention_interval; thread = PR_CreateThread( PR_USER_THREAD, Contender, contention, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(thread != NULL); overhead = PR_IntervalNow() - timein; while (contention->loops-- > 0) { PR_CEnterMonitor(contention); contention->contentious+= 1; contention->overhead += contention->interval; PR_Sleep(contention->interval); PR_CExitMonitor(contention); } timein = PR_IntervalNow(); status = PR_JoinThread(thread); overhead += (PR_IntervalNow() - timein); overhead += overhead + contention->overhead; if (verbosity) PR_fprintf( std_err, "Access ratio: %u to %u\n", contention->contentious, contention->contender); PR_Free(contention); return overhead; } /* ContentiousCMonitor */ static PRIntervalTime Test( const char* msg, PRUint32 (*test)(PRUint32 loops), PRUint32 loops, PRIntervalTime overhead) { /* * overhead - overhead not measured by the test. * duration - wall clock time it took to perform test. * predicted - extra time test says should not be counted * * Time accountable to the test is duration - overhead - predicted * All times are Intervals and accumulated for all iterations. */ PRFloat64 elapsed; PRIntervalTime accountable, duration; PRUintn spaces = PL_strlen(msg); PRIntervalTime timeout, timein = PR_IntervalNow(); PRIntervalTime predicted = test(loops); timeout = PR_IntervalNow(); duration = timeout - timein; if (debug_mode) { accountable = duration - predicted; accountable -= overhead; elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable); PR_fprintf(PR_STDOUT, "%s:", msg); while (spaces++ < 50) PR_fprintf(PR_STDOUT, " "); if ((PRInt32)accountable < 0) PR_fprintf(PR_STDOUT, "*****.** usecs/iteration\n"); else PR_fprintf(PR_STDOUT, "%8.2f usecs/iteration\n", elapsed/loops); } return duration; } /* Test */ int main(int argc, char **argv) { PRBool rv = PR_TRUE; PRIntervalTime duration; PRUint32 cpu, cpus = 2, loops = 100; PR_STDIO_INIT(); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Command line argument -l sets the number of loops. Command line argument -c sets the number of cpus. Usage: lock [-d] [-l ] [-c ] */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dvl:c:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'v': /* debug mode */ verbosity = PR_TRUE; break; case 'l': /* number of loops */ loops = atoi(opt->value); break; case 'c': /* number of cpus */ cpus = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); } /* main test */ PR_SetConcurrency(8); if (loops == 0) loops = 100; if (debug_mode) { std_err = PR_STDERR; PR_fprintf(std_err, "Lock: Using %d loops\n", loops); } if (cpus == 0) cpus = 2; if (debug_mode) PR_fprintf(std_err, "Lock: Using %d cpu(s)\n", cpus); (void)Sleeper(10); /* try filling in the caches */ for (cpu = 1; cpu <= cpus; ++cpu) { if (debug_mode) PR_fprintf(std_err, "\nLock: Using %d CPU(s)\n", cpu); PR_SetConcurrency(cpu); duration = Test("Overhead of PR_Sleep", Sleeper, loops, 0); duration = 0; (void)Test("Lock creation/deletion", MakeLock, loops, 0); (void)Test("Lock non-contentious locking/unlocking", NonContentiousLock, loops, 0); (void)Test("Lock contentious locking/unlocking", ContentiousLock, loops, duration); (void)Test("Monitor creation/deletion", MakeMonitor, loops, 0); (void)Test("Monitor non-contentious locking/unlocking", NonContentiousMonitor, loops, 0); (void)Test("Monitor contentious locking/unlocking", ContentiousMonitor, loops, duration); (void)Test("Cached monitor non-contentious locking/unlocking", NonContentiousCMonitor, loops, 0); (void)Test("Cached monitor contentious locking/unlocking", ContentiousCMonitor, loops, duration); (void)ReentrantMonitor(loops); } if (debug_mode) PR_fprintf( std_err, "%s: test %s\n", "Lock(mutex) test", ((rv) ? "passed" : "failed")); else { if (!rv) failed_already=1; } if(failed_already) { PR_fprintf(PR_STDOUT, "FAIL\n"); return 1; } else { PR_fprintf(PR_STDOUT, "PASS\n"); return 0; } } /* main */ /* testlock.c */ nspr-4.11/nspr/pr/tests/lockfile.c0000644000000000000000000001552512623070344015261 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: lockfile.c ** Purpose: test basic locking functions ** Just because this times stuff, don't think its a perforamnce ** test!!! ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prcmon.h" #include "prerror.h" #include "prinit.h" #include "prinrval.h" #include "prlock.h" #include "prlog.h" #include "prmon.h" #include "prthread.h" #include "prtypes.h" #include "private/pprio.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; const static PRIntervalTime contention_interval = 50; typedef struct LockContentious_s { PRLock *ml; PRInt32 loops; PRIntervalTime overhead; PRIntervalTime interval; } LockContentious_t; #define LOCKFILE "prlock.fil" static PRIntervalTime NonContentiousLock(PRInt32 loops) { PRFileDesc *_lockfile; while (loops-- > 0) { _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666); if (!_lockfile) { if (debug_mode) printf( "could not create lockfile: %d [%d]\n", PR_GetError(), PR_GetOSError()); return PR_INTERVAL_NO_TIMEOUT; } PR_LockFile(_lockfile); PR_UnlockFile(_lockfile); PR_Close(_lockfile); } return 0; } /* NonContentiousLock */ static void PR_CALLBACK LockContender(void *arg) { LockContentious_t *contention = (LockContentious_t*)arg; PRFileDesc *_lockfile; while (contention->loops-- > 0) { _lockfile = PR_Open(LOCKFILE, PR_CREATE_FILE|PR_RDWR, 0666); if (!_lockfile) { if (debug_mode) printf( "could not create lockfile: %d [%d]\n", PR_GetError(), PR_GetOSError()); break; } PR_LockFile(_lockfile); PR_Sleep(contention->interval); PR_UnlockFile(_lockfile); PR_Close(_lockfile); } } /* LockContender */ /* ** Win16 requires things passed to Threads not be on the stack */ static LockContentious_t contention; static PRIntervalTime ContentiousLock(PRInt32 loops) { PRStatus status; PRThread *thread = NULL; PRIntervalTime overhead, timein = PR_IntervalNow(); contention.loops = loops; contention.overhead = 0; contention.ml = PR_NewLock(); contention.interval = contention_interval; thread = PR_CreateThread( PR_USER_THREAD, LockContender, &contention, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_ASSERT(thread != NULL); overhead = PR_IntervalNow() - timein; while (contention.loops > 0) { PR_Lock(contention.ml); contention.overhead += contention.interval; PR_Sleep(contention.interval); PR_Unlock(contention.ml); } timein = PR_IntervalNow(); status = PR_JoinThread(thread); PR_DestroyLock(contention.ml); overhead += (PR_IntervalNow() - timein); return overhead + contention.overhead; } /* ContentiousLock */ static PRIntervalTime Test( const char* msg, PRIntervalTime (*test)(PRInt32 loops), PRInt32 loops, PRIntervalTime overhead) { /* * overhead - overhead not measured by the test. * duration - wall clock time it took to perform test. * predicted - extra time test says should not be counted * * Time accountable to the test is duration - overhead - predicted * All times are Intervals and accumulated for all iterations. */ PRFloat64 elapsed; PRIntervalTime accountable, duration; PRUintn spaces = strlen(msg); PRIntervalTime timeout, timein = PR_IntervalNow(); PRIntervalTime predicted = test(loops); timeout = PR_IntervalNow(); duration = timeout - timein; accountable = duration - predicted; accountable -= overhead; elapsed = (PRFloat64)PR_IntervalToMicroseconds(accountable); if (debug_mode) printf("%s:", msg); while (spaces++ < 50) if (debug_mode) printf(" "); if ((PRInt32)accountable < 0) { if (debug_mode) printf("*****.** usecs/iteration\n"); } else { if (debug_mode) printf("%8.2f usecs/iteration\n", elapsed/loops); } return duration; } /* Test */ int main(int argc, char **argv) { PRIntervalTime duration; PRUint32 cpu, cpus = 2; PRInt32 loops = 100; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (argc > 1) loops = atoi(argv[1]); if (loops == 0) loops = 100; if (debug_mode) printf("Lock: Using %d loops\n", loops); cpus = (argc < 3) ? 2 : atoi(argv[2]); if (cpus == 0) cpus = 2; if (debug_mode) printf("Lock: Using %d cpu(s)\n", cpus); for (cpu = 1; cpu <= cpus; ++cpu) { if (debug_mode) printf("\nLockFile: Using %d CPU(s)\n", cpu); PR_SetConcurrency(cpu); duration = Test("LockFile non-contentious locking/unlocking", NonContentiousLock, loops, 0); (void)Test("LockFile contentious locking/unlocking", ContentiousLock, loops, duration); } PR_Delete(LOCKFILE); /* try to get rid of evidence */ if (debug_mode) printf("%s: test %s\n", "Lock(mutex) test", ((failed_already) ? "failed" : "passed")); if(failed_already) return 1; else return 0; } /* main */ /* testlock.c */ nspr-4.11/nspr/pr/tests/logfile.c0000644000000000000000000000210112623070344015074 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A regression test for bug 491441. NSPR should not crash on startup in * PR_SetLogFile when the NSPR_LOG_MODULES and NSPR_LOG_FILE environment * variables are set. * * This test could be extended to be a full-blown test for NSPR_LOG_FILE. */ #include "prinit.h" #include "prlog.h" #include #include int main() { PRLogModuleInfo *test_lm; if (putenv("NSPR_LOG_MODULES=all:5") != 0) { fprintf(stderr, "putenv failed\n"); exit(1); } if (putenv("NSPR_LOG_FILE=logfile.log") != 0) { fprintf(stderr, "putenv failed\n"); exit(1); } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); test_lm = PR_NewLogModule("test"); PR_LOG(test_lm, PR_LOG_MIN, ("logfile: test log message")); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/logger.c0000644000000000000000000000567412623070344014754 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: logger.c * Description: test program for logging's basic functions */ #include "prinit.h" #include "prlog.h" #include "prlock.h" #include "prcvar.h" #include "prthread.h" #include "prinrval.h" #include /* lth. re-define PR_LOG() */ #if 0 #undef PR_LOG_TEST #undef PR_LOG #define PR_LOG_TEST(_module,_level) ((_module)->level <= (_level)) #define PR_LOG(_module,_level,_args) \ { \ if (PR_LOG_TEST(_module,_level)) \ PR_LogPrint _args ; \ } #endif static void Error(const char* msg) { printf("\t%s\n", msg); } /* Error */ static void PR_CALLBACK forked(void *arg) { PRIntn i; PRLock *ml; PRCondVar *cv; PR_LogPrint("%s logging creating mutex\n", (const char*)arg); ml = PR_NewLock(); PR_LogPrint("%s logging creating condition variable\n", (const char*)arg); cv = PR_NewCondVar(ml); PR_LogPrint("%s waiting on condition timeout 10 times\n", (const char*)arg); for (i = 0; i < 10; ++i) { PR_Lock(ml); PR_WaitCondVar(cv, PR_SecondsToInterval(1)); PR_Unlock(ml); } PR_LogPrint("%s logging destroying condition variable\n", (const char*)arg); PR_DestroyCondVar(cv); PR_LogPrint("%s logging destroying mutex\n", (const char*)arg); PR_DestroyLock(ml); PR_LogPrint("%s forked thread exiting\n", (const char*)arg); } static void UserLogStuff( void ) { PRLogModuleInfo *myLM; PRIntn i; myLM = PR_NewLogModule( "userStuff" ); if (! myLM ) { printf("UserLogStuff(): can't create new log module\n" ); return; } PR_LOG( myLM, PR_LOG_NOTICE, ("Log a Notice %d\n", 1 )); for (i = 0; i < 10 ; i++ ) { PR_LOG( myLM, PR_LOG_DEBUG, ("Log Debug number: %d\n", i)); PR_Sleep( 300 ); } } /* end UserLogStuff() */ int main(int argc, char **argv) { PRThread *thread; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (argc > 1) { if (!PR_SetLogFile(argv[1])) { Error("Access: Cannot create log file"); goto exit; } } /* Start logging something here */ PR_LogPrint("%s logging into %s\n", argv[0], argv[1]); PR_LogPrint("%s creating new thread\n", argv[0]); /* ** Now change buffering. */ PR_SetLogBuffering( 65500 ); thread = PR_CreateThread( PR_USER_THREAD, forked, (void*)argv[0], PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_LogPrint("%s joining thread\n", argv[0]); UserLogStuff(); PR_JoinThread(thread); PR_LogFlush(); return 0; exit: return -1; } /* logger.c */ nspr-4.11/nspr/pr/tests/makedir.c0000644000000000000000000000371112623070344015077 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This test calls PR_MakeDir to create a bunch of directories * with various mode bits. */ #include "prio.h" #include #include int main(int argc, char **argv) { if (PR_MakeDir("tdir0400", 0400) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0200", 0200) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0100", 0100) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0500", 0500) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0600", 0600) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0300", 0300) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0700", 0700) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0640", 0640) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0660", 0660) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0644", 0644) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0664", 0664) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } if (PR_MakeDir("tdir0666", 0666) == PR_FAILURE) { fprintf(stderr, "PR_MakeDir failed\n"); exit(1); } return 0; } nspr-4.11/nspr/pr/tests/many_cv.c0000644000000000000000000000612012623070344015114 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include "prprf.h" #include "prthread.h" #include "prcvar.h" #include "prlock.h" #include "prlog.h" #include "prmem.h" #include "primpl.h" #include "plgetopt.h" #include static PRInt32 RandomNum(void) { PRInt32 ran = rand() >> 16; return ran; } /* RandomNum */ static void Help(void) { PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); PR_fprintf(err, "many_cv usage: [-c n] [-l n] [-h]\n"); PR_fprintf(err, "\t-c n Number of conditions per lock (default: 10)\n"); PR_fprintf(err, "\t-l n Number of times to loop the test (default: 1)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { PLOptStatus os; PRIntn index, nl; PRLock *ml = NULL; PRCondVar **cv = NULL; PRBool stats = PR_FALSE; PRIntn nc, loops = 1, cvs = 10; PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); PLOptState *opt = PL_CreateOptState(argc, argv, "hsc:l:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 's': /* number of CVs to association with lock */ stats = PR_TRUE; break; case 'c': /* number of CVs to association with lock */ cvs = atoi(opt->value); break; case 'l': /* number of times to run the tests */ loops = atoi(opt->value); break; case 'h': /* user wants some guidance */ default: Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); PR_fprintf(err, "Settings\n"); PR_fprintf(err, "\tConditions / lock: %d\n", cvs); PR_fprintf(err, "\tLoops to run test: %d\n", loops); ml = PR_NewLock(); PR_ASSERT(NULL != ml); cv = (PRCondVar**)PR_CALLOC(sizeof(PRCondVar*) * cvs); PR_ASSERT(NULL != cv); for (index = 0; index < cvs; ++index) { cv[index] = PR_NewCondVar(ml); PR_ASSERT(NULL != cv[index]); } for (index = 0; index < loops; ++index) { PR_Lock(ml); for (nl = 0; nl < cvs; ++nl) { PRInt32 ran = RandomNum() % 8; if (0 == ran) PR_NotifyAllCondVar(cv[nl]); else for (nc = 0; nc < ran; ++nc) PR_NotifyCondVar(cv[nl]); } PR_Unlock(ml); } for (index = 0; index < cvs; ++index) PR_DestroyCondVar(cv[index]); PR_DELETE(cv); PR_DestroyLock(ml); printf("PASS\n"); PT_FPrintStats(err, "\nPThread Statistics\n"); return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/mbcs.c0000644000000000000000000001163512623070344014413 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: mbcs.c ** ** Synopsis: mbcs {dirName} ** ** where dirName is the directory to be traversed. dirName is required. ** ** Description: ** mbcs.c tests use of multi-byte characters, as would be passed to ** NSPR funtions by internationalized applications. ** ** mbcs.c, when run on any single-byte platform, should run correctly. ** In truth, running the mbcs test on a single-byte platform is ** really meaningless. mbcs.c, nor any NSPR library or test is not ** intended for use with any wide character set, including Unicode. ** mbcs.c should not be included in runtests.ksh because it requires ** extensive user intervention to set-up and run. ** ** mbcs.c should be run on a platform using some form of multi-byte ** characters. The initial platform for this test is a Japanese ** language Windows NT 4.0 machine. ... Thank you Noriko Hoshi. ** ** To run mbcs.c, the tester should create a directory tree containing ** some files in the same directory from which the test is run; i.e. ** the current working directory. The directory and files should be ** named such that when represented in the local multi-byte character ** set, one or more characters of the name is longer than a single ** byte. ** */ #include #include #include #include #include /* ** Test harness infrastructure */ PRLogModuleInfo *lm; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRIntn debug = 0; PRUint32 failed_already = 0; /* end Test harness infrastructure */ char *dirName = NULL; /* directory name to traverse */ /* ** Traverse directory */ static void TraverseDirectory( unsigned char *dir ) { PRDir *cwd; PRDirEntry *dirEntry; PRFileInfo info; PRStatus rc; PRInt32 err; PRFileDesc *fd; char nextDir[256]; char file[256]; printf("Directory: %s\n", dir ); cwd = PR_OpenDir( dir ); if ( NULL == cwd ) { printf("PR_OpenDir() failed on directory: %s, with error: %d, %d\n", dir, PR_GetError(), PR_GetOSError()); exit(1); } while( NULL != (dirEntry = PR_ReadDir( cwd, PR_SKIP_BOTH | PR_SKIP_HIDDEN ))) { sprintf( file, "%s/%s", dir, dirEntry->name ); rc = PR_GetFileInfo( file, &info ); if ( PR_FAILURE == rc ) { printf("PR_GetFileInfo() failed on file: %s, with error: %d, %d\n", dirEntry->name, PR_GetError(), PR_GetOSError()); exit(1); } if ( PR_FILE_FILE == info.type ) { printf("File: %s \tsize: %ld\n", dirEntry->name, info.size ); fd = PR_Open( file, PR_RDONLY, 0 ); if ( NULL == fd ) { printf("PR_Open() failed. Error: %ld, OSError: %ld\n", PR_GetError(), PR_GetOSError()); } rc = PR_Close( fd ); if ( PR_FAILURE == rc ) { printf("PR_Close() failed. Error: %ld, OSError: %ld\n", PR_GetError(), PR_GetOSError()); } } else if ( PR_FILE_DIRECTORY == info.type ) { sprintf( nextDir, "%s/%s", dir, dirEntry->name ); TraverseDirectory(nextDir); } else { printf("type is not interesting for file: %s\n", dirEntry->name ); /* keep going */ } } /* assume end-of-file, actually could be error */ rc = PR_CloseDir( cwd ); if ( PR_FAILURE == rc ) { printf("PR_CloseDir() failed on directory: %s, with error: %d, %d\n", dir, PR_GetError(), PR_GetOSError()); } } /* end TraverseDirectory() */ int main(int argc, char **argv) { { /* get command line options */ /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dv"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_ERROR; break; case 'v': /* verbose mode */ msgLevel = PR_LOG_DEBUG; break; default: dirName = strdup(opt->value); break; } } PL_DestroyOptState(opt); } /* end get command line options */ lm = PR_NewLogModule("Test"); /* Initialize logging */ if ( dirName == NULL ) { printf("you gotta specify a directory as an operand!\n"); exit(1); } TraverseDirectory( dirName ); if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS"); return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */ /* end template.c */ nspr-4.11/nspr/pr/tests/monref.c0000644000000000000000000000342212623070344014750 0ustar 00000000000000/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This test program demonstrates that PR_ExitMonitor needs to add a * reference to the PRMonitor object before unlocking the internal * mutex. */ #include "prlog.h" #include "prmon.h" #include "prthread.h" #include #include /* Protected by the PRMonitor 'mon' in the main function. */ static PRBool done = PR_FALSE; static void ThreadFunc(void *arg) { PRMonitor *mon = (PRMonitor *)arg; PRStatus rv; PR_EnterMonitor(mon); done = PR_TRUE; rv = PR_Notify(mon); PR_ASSERT(rv == PR_SUCCESS); rv = PR_ExitMonitor(mon); PR_ASSERT(rv == PR_SUCCESS); } int main() { PRMonitor *mon; PRThread *thread; PRStatus rv; mon = PR_NewMonitor(); if (!mon) { fprintf(stderr, "PR_NewMonitor failed\n"); exit(1); } thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, mon, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (!thread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } PR_EnterMonitor(mon); while (!done) { rv = PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(rv == PR_SUCCESS); } rv = PR_ExitMonitor(mon); PR_ASSERT(rv == PR_SUCCESS); /* * Do you agree it should be safe to destroy 'mon' now? * See bug 844784 comment 27. */ PR_DestroyMonitor(mon); rv = PR_JoinThread(thread); PR_ASSERT(rv == PR_SUCCESS); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/multiacc.c0000644000000000000000000001501712623070344015266 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: multiacc.c * * Description: * This test creates multiple threads that accept on the * same listening socket. */ #include "nspr.h" #include #include #include #define NUM_SERVER_THREADS 10 static int num_server_threads = NUM_SERVER_THREADS; static PRThreadScope thread_scope = PR_GLOBAL_THREAD; static PRBool exit_flag = PR_FALSE; static void ServerThreadFunc(void *arg) { PRFileDesc *listenSock = (PRFileDesc *) arg; PRFileDesc *acceptSock; PRErrorCode err; PRStatus status; while (!exit_flag) { acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == acceptSock) { err = PR_GetError(); if (PR_PENDING_INTERRUPT_ERROR == err) { printf("server thread is interrupted\n"); fflush(stdout); continue; } fprintf(stderr, "PR_Accept failed: %d\n", err); exit(1); } status = PR_Close(acceptSock); if (PR_FAILURE == status) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } } int main(int argc, char **argv) { PRNetAddr serverAddr; PRFileDesc *dummySock; PRFileDesc *listenSock; PRFileDesc *clientSock; PRThread *dummyThread; PRThread **serverThreads; PRStatus status; PRUint16 port; int idx; PRInt32 nbytes; char buf[1024]; serverThreads = (PRThread **) PR_Malloc(num_server_threads * sizeof(PRThread *)); if (NULL == serverThreads) { fprintf(stderr, "PR_Malloc failed\n"); exit(1); } /* * Create a dummy listening socket and have the first * (dummy) thread listen on it. This is to ensure that * the first thread becomes the I/O continuation thread * in the pthreads implementation (see ptio.c) and remains * so throughout the test, so that we never have to * recycle the I/O continuation thread. */ dummySock = PR_NewTCPSocket(); if (NULL == dummySock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&serverAddr, 0, sizeof(serverAddr)); status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr); if (PR_FAILURE == status) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } status = PR_Bind(dummySock, &serverAddr); if (PR_FAILURE == status) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } status = PR_Listen(dummySock, 5); if (PR_FAILURE == status) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } listenSock = PR_NewTCPSocket(); if (NULL == listenSock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&serverAddr, 0, sizeof(serverAddr)); status = PR_InitializeNetAddr(PR_IpAddrAny, 0, &serverAddr); if (PR_FAILURE == status) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } status = PR_Bind(listenSock, &serverAddr); if (PR_FAILURE == status) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } status = PR_GetSockName(listenSock, &serverAddr); if (PR_FAILURE == status) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } port = PR_ntohs(serverAddr.inet.port); status = PR_Listen(listenSock, 5); if (PR_FAILURE == status) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } printf("creating dummy thread\n"); fflush(stdout); dummyThread = PR_CreateThread(PR_USER_THREAD, ServerThreadFunc, dummySock, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (NULL == dummyThread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } printf("sleeping one second before creating server threads\n"); fflush(stdout); PR_Sleep(PR_SecondsToInterval(1)); for (idx = 0; idx < num_server_threads; idx++) { serverThreads[idx] = PR_CreateThread(PR_USER_THREAD, ServerThreadFunc, listenSock, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (NULL == serverThreads[idx]) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } } memset(&serverAddr, 0, sizeof(serverAddr)); PR_InitializeNetAddr(PR_IpAddrLoopback, port, &serverAddr); clientSock = PR_NewTCPSocket(); if (NULL == clientSock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } printf("sleeping one second before connecting\n"); fflush(stdout); PR_Sleep(PR_SecondsToInterval(1)); status = PR_Connect(clientSock, &serverAddr, PR_INTERVAL_NO_TIMEOUT); if (PR_FAILURE == status) { fprintf(stderr, "PR_Connect failed\n"); exit(1); } nbytes = PR_Read(clientSock, buf, sizeof(buf)); if (nbytes != 0) { fprintf(stderr, "expected 0 bytes but got %d bytes\n", nbytes); exit(1); } status = PR_Close(clientSock); if (PR_FAILURE == status) { fprintf(stderr, "PR_Close failed\n"); exit(1); } printf("sleeping one second before shutting down server threads\n"); fflush(stdout); PR_Sleep(PR_SecondsToInterval(1)); exit_flag = PR_TRUE; status = PR_Interrupt(dummyThread); if (PR_FAILURE == status) { fprintf(stderr, "PR_Interrupt failed\n"); exit(1); } status = PR_JoinThread(dummyThread); if (PR_FAILURE == status) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } for (idx = 0; idx < num_server_threads; idx++) { status = PR_Interrupt(serverThreads[idx]); if (PR_FAILURE == status) { fprintf(stderr, "PR_Interrupt failed\n"); exit(1); } status = PR_JoinThread(serverThreads[idx]); if (PR_FAILURE == status) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } } PR_Free(serverThreads); status = PR_Close(dummySock); if (PR_FAILURE == status) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(listenSock); if (PR_FAILURE == status) { fprintf(stderr, "PR_Close failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/multiwait.c0000644000000000000000000005246112623070344015510 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prprf.h" #include "prlog.h" #include "prmem.h" #include "pratom.h" #include "prlock.h" #include "prmwait.h" #include "prclist.h" #include "prerror.h" #include "prinrval.h" #include "prnetdb.h" #include "prthread.h" #include "plstr.h" #include "plerror.h" #include "plgetopt.h" #include typedef struct Shared { const char *title; PRLock *list_lock; PRWaitGroup *group; PRIntervalTime timeout; } Shared; typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity; static PRFileDesc *debug = NULL; static PRInt32 desc_allocated = 0; static PRUint16 default_port = 12273; static enum Verbosity verbosity = quiet; static PRInt32 ops_required = 1000, ops_done = 0; static PRThreadScope thread_scope = PR_LOCAL_THREAD; static PRIntn client_threads = 20, worker_threads = 2, wait_objects = 50; #if defined(DEBUG) #define MW_ASSERT(_expr) \ ((_expr)?((void)0):_MW_Assert(# _expr,__FILE__,__LINE__)) static void _MW_Assert(const char *s, const char *file, PRIntn ln) { if (NULL != debug) PL_FPrintError(debug, NULL); PR_Assert(s, file, ln); } /* _MW_Assert */ #else #define MW_ASSERT(_expr) #endif static void PrintRecvDesc(PRRecvWait *desc, const char *msg) { const char *tag[] = { "PR_MW_INTERRUPT", "PR_MW_TIMEOUT", "PR_MW_FAILURE", "PR_MW_SUCCESS", "PR_MW_PENDING"}; PR_fprintf( debug, "%s: PRRecvWait(@0x%x): {fd: 0x%x, outcome: %s, tmo: %u}\n", msg, desc, desc->fd, tag[desc->outcome + 3], desc->timeout); } /* PrintRecvDesc */ static Shared *MakeShared(const char *title) { Shared *shared = PR_NEWZAP(Shared); shared->group = PR_CreateWaitGroup(1); shared->timeout = PR_SecondsToInterval(1); shared->list_lock = PR_NewLock(); shared->title = title; return shared; } /* MakeShared */ static void DestroyShared(Shared *shared) { PRStatus rv; if (verbosity > quiet) PR_fprintf(debug, "%s: destroying group\n", shared->title); rv = PR_DestroyWaitGroup(shared->group); MW_ASSERT(PR_SUCCESS == rv); PR_DestroyLock(shared->list_lock); PR_DELETE(shared); } /* DestroyShared */ static PRRecvWait *CreateRecvWait(PRFileDesc *fd, PRIntervalTime timeout) { PRRecvWait *desc_out = PR_NEWZAP(PRRecvWait); MW_ASSERT(NULL != desc_out); MW_ASSERT(NULL != fd); desc_out->fd = fd; desc_out->timeout = timeout; desc_out->buffer.length = 120; desc_out->buffer.start = PR_CALLOC(120); PR_AtomicIncrement(&desc_allocated); if (verbosity > chatty) PrintRecvDesc(desc_out, "Allocated"); return desc_out; } /* CreateRecvWait */ static void DestroyRecvWait(PRRecvWait *desc_out) { if (verbosity > chatty) PrintRecvDesc(desc_out, "Destroying"); PR_Close(desc_out->fd); if (NULL != desc_out->buffer.start) PR_DELETE(desc_out->buffer.start); PR_Free(desc_out); (void)PR_AtomicDecrement(&desc_allocated); } /* DestroyRecvWait */ static void CancelGroup(Shared *shared) { PRRecvWait *desc_out; if (verbosity > quiet) PR_fprintf(debug, "%s Reclaiming wait descriptors\n", shared->title); do { desc_out = PR_CancelWaitGroup(shared->group); if (NULL != desc_out) DestroyRecvWait(desc_out); } while (NULL != desc_out); MW_ASSERT(0 == desc_allocated); MW_ASSERT(PR_GROUP_EMPTY_ERROR == PR_GetError()); } /* CancelGroup */ static void PR_CALLBACK ClientThread(void* arg) { PRStatus rv; PRInt32 bytes; PRIntn empty_flags = 0; PRNetAddr server_address; unsigned char buffer[100]; Shared *shared = (Shared*)arg; PRFileDesc *server = PR_NewTCPSocket(); if ((NULL == server) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) return; MW_ASSERT(NULL != server); if (verbosity > chatty) PR_fprintf(debug, "%s: Server socket @0x%x\n", shared->title, server); /* Initialize the buffer so that Purify won't complain */ memset(buffer, 0, sizeof(buffer)); rv = PR_InitializeNetAddr(PR_IpAddrLoopback, default_port, &server_address); MW_ASSERT(PR_SUCCESS == rv); if (verbosity > quiet) PR_fprintf(debug, "%s: Client opening connection\n", shared->title); rv = PR_Connect(server, &server_address, PR_INTERVAL_NO_TIMEOUT); if (PR_FAILURE == rv) { if (verbosity > silent) PL_FPrintError(debug, "Client connect failed"); return; } while (ops_done < ops_required) { bytes = PR_Send( server, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT); if ((-1 == bytes) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break; MW_ASSERT(sizeof(buffer) == bytes); if (verbosity > chatty) PR_fprintf( debug, "%s: Client sent %d bytes\n", shared->title, sizeof(buffer)); bytes = PR_Recv( server, buffer, sizeof(buffer), empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf( debug, "%s: Client received %d bytes\n", shared->title, sizeof(buffer)); if ((-1 == bytes) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) break; MW_ASSERT(sizeof(buffer) == bytes); PR_Sleep(shared->timeout); } rv = PR_Close(server); MW_ASSERT(PR_SUCCESS == rv); } /* ClientThread */ static void OneInThenCancelled(Shared *shared) { PRStatus rv; PRRecvWait *desc_out, *desc_in = PR_NEWZAP(PRRecvWait); shared->timeout = PR_INTERVAL_NO_TIMEOUT; desc_in->fd = PR_NewTCPSocket(); desc_in->timeout = shared->timeout; if (verbosity > chatty) PrintRecvDesc(desc_in, "Adding desc"); rv = PR_AddWaitFileDesc(shared->group, desc_in); MW_ASSERT(PR_SUCCESS == rv); if (verbosity > chatty) PrintRecvDesc(desc_in, "Cancelling"); rv = PR_CancelWaitFileDesc(shared->group, desc_in); MW_ASSERT(PR_SUCCESS == rv); desc_out = PR_WaitRecvReady(shared->group); MW_ASSERT(desc_out == desc_in); MW_ASSERT(PR_MW_INTERRUPT == desc_out->outcome); MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError()); if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready"); rv = PR_Close(desc_in->fd); MW_ASSERT(PR_SUCCESS == rv); if (verbosity > quiet) PR_fprintf(debug, "%s: destroying group\n", shared->title); PR_DELETE(desc_in); } /* OneInThenCancelled */ static void OneOpOneThread(Shared *shared) { PRStatus rv; PRRecvWait *desc_out, *desc_in = PR_NEWZAP(PRRecvWait); desc_in->fd = PR_NewTCPSocket(); desc_in->timeout = shared->timeout; if (verbosity > chatty) PrintRecvDesc(desc_in, "Adding desc"); rv = PR_AddWaitFileDesc(shared->group, desc_in); MW_ASSERT(PR_SUCCESS == rv); desc_out = PR_WaitRecvReady(shared->group); MW_ASSERT(desc_out == desc_in); MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome); MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError()); if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready"); rv = PR_Close(desc_in->fd); MW_ASSERT(PR_SUCCESS == rv); PR_DELETE(desc_in); } /* OneOpOneThread */ static void ManyOpOneThread(Shared *shared) { PRStatus rv; PRIntn index; PRRecvWait *desc_in; PRRecvWait *desc_out; if (verbosity > quiet) PR_fprintf(debug, "%s: adding %d descs\n", shared->title, wait_objects); for (index = 0; index < wait_objects; ++index) { desc_in = CreateRecvWait(PR_NewTCPSocket(), shared->timeout); rv = PR_AddWaitFileDesc(shared->group, desc_in); MW_ASSERT(PR_SUCCESS == rv); } while (ops_done < ops_required) { desc_out = PR_WaitRecvReady(shared->group); MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome); MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError()); if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready/readding"); rv = PR_AddWaitFileDesc(shared->group, desc_out); MW_ASSERT(PR_SUCCESS == rv); (void)PR_AtomicIncrement(&ops_done); } CancelGroup(shared); } /* ManyOpOneThread */ static void PR_CALLBACK SomeOpsThread(void *arg) { PRRecvWait *desc_out; PRStatus rv = PR_SUCCESS; Shared *shared = (Shared*)arg; do /* until interrupted */ { desc_out = PR_WaitRecvReady(shared->group); if (NULL == desc_out) { MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError()); if (verbosity > quiet) PR_fprintf(debug, "Aborted\n"); break; } MW_ASSERT(PR_MW_TIMEOUT == desc_out->outcome); MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError()); if (verbosity > chatty) PrintRecvDesc(desc_out, "Ready"); if (verbosity > chatty) PrintRecvDesc(desc_out, "Re-Adding"); desc_out->timeout = shared->timeout; rv = PR_AddWaitFileDesc(shared->group, desc_out); PR_AtomicIncrement(&ops_done); if (ops_done > ops_required) break; } while (PR_SUCCESS == rv); MW_ASSERT(PR_SUCCESS == rv); } /* SomeOpsThread */ static void SomeOpsSomeThreads(Shared *shared) { PRStatus rv; PRThread **thread; PRIntn index; PRRecvWait *desc_in; thread = (PRThread**)PR_CALLOC(sizeof(PRThread*) * worker_threads); /* Create some threads */ if (verbosity > quiet) PR_fprintf(debug, "%s: creating threads\n", shared->title); for (index = 0; index < worker_threads; ++index) { thread[index] = PR_CreateThread( PR_USER_THREAD, SomeOpsThread, shared, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); } /* then create some operations */ if (verbosity > quiet) PR_fprintf(debug, "%s: creating desc\n", shared->title); for (index = 0; index < wait_objects; ++index) { desc_in = CreateRecvWait(PR_NewTCPSocket(), shared->timeout); rv = PR_AddWaitFileDesc(shared->group, desc_in); MW_ASSERT(PR_SUCCESS == rv); } if (verbosity > quiet) PR_fprintf(debug, "%s: sleeping\n", shared->title); while (ops_done < ops_required) PR_Sleep(shared->timeout); if (verbosity > quiet) PR_fprintf(debug, "%s: interrupting/joining threads\n", shared->title); for (index = 0; index < worker_threads; ++index) { rv = PR_Interrupt(thread[index]); MW_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(thread[index]); MW_ASSERT(PR_SUCCESS == rv); } PR_DELETE(thread); CancelGroup(shared); } /* SomeOpsSomeThreads */ static PRStatus ServiceRequest(Shared *shared, PRRecvWait *desc) { PRInt32 bytes_out; if (verbosity > chatty) PR_fprintf( debug, "%s: Service received %d bytes\n", shared->title, desc->bytesRecv); if (0 == desc->bytesRecv) goto quitting; if ((-1 == desc->bytesRecv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) goto aborted; bytes_out = PR_Send( desc->fd, desc->buffer.start, desc->bytesRecv, 0, shared->timeout); if (verbosity > chatty) PR_fprintf( debug, "%s: Service sent %d bytes\n", shared->title, bytes_out); if ((-1 == bytes_out) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) goto aborted; MW_ASSERT(bytes_out == desc->bytesRecv); return PR_SUCCESS; aborted: quitting: return PR_FAILURE; } /* ServiceRequest */ static void PR_CALLBACK ServiceThread(void *arg) { PRStatus rv = PR_SUCCESS; PRRecvWait *desc_out = NULL; Shared *shared = (Shared*)arg; do /* until interrupted */ { if (NULL != desc_out) { desc_out->timeout = PR_INTERVAL_NO_TIMEOUT; if (verbosity > chatty) PrintRecvDesc(desc_out, "Service re-adding"); rv = PR_AddWaitFileDesc(shared->group, desc_out); MW_ASSERT(PR_SUCCESS == rv); } desc_out = PR_WaitRecvReady(shared->group); if (NULL == desc_out) { MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError()); break; } switch (desc_out->outcome) { case PR_MW_SUCCESS: { PR_AtomicIncrement(&ops_done); if (verbosity > chatty) PrintRecvDesc(desc_out, "Service ready"); rv = ServiceRequest(shared, desc_out); break; } case PR_MW_INTERRUPT: MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError()); rv = PR_FAILURE; /* if interrupted, then exit */ break; case PR_MW_TIMEOUT: MW_ASSERT(PR_IO_TIMEOUT_ERROR == PR_GetError()); case PR_MW_FAILURE: if (verbosity > silent) PL_FPrintError(debug, "RecvReady failure"); break; default: break; } } while (PR_SUCCESS == rv); if (NULL != desc_out) DestroyRecvWait(desc_out); } /* ServiceThread */ static void PR_CALLBACK EnumerationThread(void *arg) { PRStatus rv; PRIntn count; PRRecvWait *desc; Shared *shared = (Shared*)arg; PRIntervalTime five_seconds = PR_SecondsToInterval(5); PRMWaitEnumerator *enumerator = PR_CreateMWaitEnumerator(shared->group); MW_ASSERT(NULL != enumerator); while (PR_SUCCESS == PR_Sleep(five_seconds)) { count = 0; desc = NULL; while (NULL != (desc = PR_EnumerateWaitGroup(enumerator, desc))) { if (verbosity > chatty) PrintRecvDesc(desc, shared->title); count += 1; } if (verbosity > silent) PR_fprintf(debug, "%s Enumerated %d objects\n", shared->title, count); } MW_ASSERT(PR_PENDING_INTERRUPT_ERROR == PR_GetError()); rv = PR_DestroyMWaitEnumerator(enumerator); MW_ASSERT(PR_SUCCESS == rv); } /* EnumerationThread */ static void PR_CALLBACK ServerThread(void *arg) { PRStatus rv; PRIntn index; PRRecvWait *desc_in; PRThread **worker_thread; Shared *shared = (Shared*)arg; PRFileDesc *listener, *service; PRNetAddr server_address, client_address; worker_thread = (PRThread**)PR_CALLOC(sizeof(PRThread*) * worker_threads); if (verbosity > quiet) PR_fprintf(debug, "%s: Server creating worker_threads\n", shared->title); for (index = 0; index < worker_threads; ++index) { worker_thread[index] = PR_CreateThread( PR_USER_THREAD, ServiceThread, shared, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); } rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &server_address); MW_ASSERT(PR_SUCCESS == rv); listener = PR_NewTCPSocket(); MW_ASSERT(NULL != listener); if (verbosity > chatty) PR_fprintf( debug, "%s: Server listener socket @0x%x\n", shared->title, listener); rv = PR_Bind(listener, &server_address); MW_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(listener, 10); MW_ASSERT(PR_SUCCESS == rv); while (ops_done < ops_required) { if (verbosity > quiet) PR_fprintf(debug, "%s: Server accepting connection\n", shared->title); service = PR_Accept(listener, &client_address, PR_INTERVAL_NO_TIMEOUT); if (NULL == service) { if (PR_PENDING_INTERRUPT_ERROR == PR_GetError()) break; PL_PrintError("Accept failed"); MW_ASSERT(PR_FALSE && "Accept failed"); } else { desc_in = CreateRecvWait(service, shared->timeout); desc_in->timeout = PR_INTERVAL_NO_TIMEOUT; if (verbosity > chatty) PrintRecvDesc(desc_in, "Service adding"); rv = PR_AddWaitFileDesc(shared->group, desc_in); MW_ASSERT(PR_SUCCESS == rv); } } if (verbosity > quiet) PR_fprintf(debug, "%s: Server interrupting worker_threads\n", shared->title); for (index = 0; index < worker_threads; ++index) { rv = PR_Interrupt(worker_thread[index]); MW_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(worker_thread[index]); MW_ASSERT(PR_SUCCESS == rv); } PR_DELETE(worker_thread); PR_Close(listener); CancelGroup(shared); } /* ServerThread */ static void RealOneGroupIO(Shared *shared) { /* ** Create a server that listens for connections and then services ** requests that come in over those connections. The server never ** deletes a connection and assumes a basic RPC model of operation. ** ** Use worker_threads threads to service how every many open ports ** there might be. ** ** Oh, ya. Almost forget. Create (some) clients as well. */ PRStatus rv; PRIntn index; PRThread *server_thread, *enumeration_thread, **client_thread; if (verbosity > quiet) PR_fprintf(debug, "%s: creating server_thread\n", shared->title); server_thread = PR_CreateThread( PR_USER_THREAD, ServerThread, shared, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); if (verbosity > quiet) PR_fprintf(debug, "%s: creating enumeration_thread\n", shared->title); enumeration_thread = PR_CreateThread( PR_USER_THREAD, EnumerationThread, shared, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); if (verbosity > quiet) PR_fprintf(debug, "%s: snoozing before creating clients\n", shared->title); PR_Sleep(5 * shared->timeout); if (verbosity > quiet) PR_fprintf(debug, "%s: creating client_threads\n", shared->title); client_thread = (PRThread**)PR_CALLOC(sizeof(PRThread*) * client_threads); for (index = 0; index < client_threads; ++index) { client_thread[index] = PR_CreateThread( PR_USER_THREAD, ClientThread, shared, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); } while (ops_done < ops_required) PR_Sleep(shared->timeout); if (verbosity > quiet) PR_fprintf(debug, "%s: interrupting/joining client_threads\n", shared->title); for (index = 0; index < client_threads; ++index) { rv = PR_Interrupt(client_thread[index]); MW_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(client_thread[index]); MW_ASSERT(PR_SUCCESS == rv); } PR_DELETE(client_thread); if (verbosity > quiet) PR_fprintf(debug, "%s: interrupting/joining enumeration_thread\n", shared->title); rv = PR_Interrupt(enumeration_thread); MW_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(enumeration_thread); MW_ASSERT(PR_SUCCESS == rv); if (verbosity > quiet) PR_fprintf(debug, "%s: interrupting/joining server_thread\n", shared->title); rv = PR_Interrupt(server_thread); MW_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); MW_ASSERT(PR_SUCCESS == rv); } /* RealOneGroupIO */ static void RunThisOne( void (*func)(Shared*), const char *name, const char *test_name) { Shared *shared; if ((NULL == test_name) || (0 == PL_strcmp(name, test_name))) { if (verbosity > silent) PR_fprintf(debug, "%s()\n", name); shared = MakeShared(name); ops_done = 0; func(shared); /* run the test */ MW_ASSERT(0 == desc_allocated); DestroyShared(shared); } } /* RunThisOne */ static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta) { PRIntn verbage = (PRIntn)verbosity; return (Verbosity)(verbage += delta); } /* ChangeVerbosity */ int main(int argc, char **argv) { PLOptStatus os; const char *test_name = NULL; PLOptState *opt = PL_CreateOptState(argc, argv, "dqGc:o:p:t:w:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: test_name = opt->value; break; case 'd': /* debug mode */ if (verbosity < noisy) verbosity = ChangeVerbosity(verbosity, 1); break; case 'q': /* debug mode */ if (verbosity > silent) verbosity = ChangeVerbosity(verbosity, -1); break; case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'c': /* number of client threads */ client_threads = atoi(opt->value); break; case 'o': /* operations to compelete */ ops_required = atoi(opt->value); break; case 'p': /* default port */ default_port = atoi(opt->value); break; case 't': /* number of threads waiting */ worker_threads = atoi(opt->value); break; case 'w': /* number of wait objects */ wait_objects = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (verbosity > 0) debug = PR_GetSpecialFD(PR_StandardError); RunThisOne(OneInThenCancelled, "OneInThenCancelled", test_name); RunThisOne(OneOpOneThread, "OneOpOneThread", test_name); RunThisOne(ManyOpOneThread, "ManyOpOneThread", test_name); RunThisOne(SomeOpsSomeThreads, "SomeOpsSomeThreads", test_name); RunThisOne(RealOneGroupIO, "RealOneGroupIO", test_name); return 0; } /* main */ /* multwait.c */ nspr-4.11/nspr/pr/tests/nameshm1.c0000644000000000000000000004100712623070344015174 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: nameshm1.c -- Test Named Shared Memory ** ** Description: ** nameshm1 tests Named Shared Memory. nameshm1 performs two tests of ** named shared memory. ** ** The first test is a basic test. The basic test operates as a single ** process. The process exercises all the API elements of the facility. ** This test also attempts to write to all locations in the shared ** memory. ** ** The second test is a client-server test. The client-server test ** creates a new instance of nameshm1, passing the -C argument to the ** new process; this creates the client-side process. The server-side ** (the instance of nameshm1 created from the command line) and the ** client-side interact via inter-process semaphores to verify that the ** shared memory segment can be read and written by both sides in a ** synchronized maner. ** ** Note: Because this test runs in two processes, the log files created ** by the test are not in chronological sequence; makes it hard to read. ** As a temporary circumvention, I changed the definition(s) of the ** _PUT_LOG() macro in prlog.c to force a flushall(), or equivalent. ** This causes the log entries to be emitted in true chronological ** order. ** ** Synopsis: nameshm1 [options] [name] ** ** Options: ** -d Enables debug trace via PR_LOG() ** -v Enables verbose mode debug trace via PR_LOG() ** -w Causes the basic test to attempt to write to the segment ** mapped as read-only. When this option is specified, the ** test should crash with a seg-fault; this is a destructive ** test and is considered successful when it seg-faults. ** ** -C Causes nameshm1 to start as the client-side of a ** client-server pair of processes. Only the instance ** of nameshm1 operating as the server-side process should ** specify the -C option when creating the client-side process; ** the -C option should not be specified at the command line. ** The client-side uses the shared memory segment created by ** the server-side to communicate with the server-side ** process. ** ** -p Specify the number of iterations the client-server tests ** should perform. Default: 1000. ** ** -s Size, in KBytes (1024), of the shared memory segment. ** Default: (10 * 1024) ** ** -i Number of client-side iterations. Default: 3 ** ** name specifies the name of the shared memory segment to be used. ** Default: /tmp/xxxNSPRshm ** ** ** See also: prshm.h ** ** /lth. Aug-1999. */ #include #include #include #include #include #ifdef SYMBIAN #define SEM_NAME1 "c:\\data\\nameshmSEM1" #define SEM_NAME2 "c:\\data\\nameshmSEM2" #define OPT_NAME "c:\\data\\xxxNSPRshm" #define EXE_NAME "nspr_tests_nameshm1.exe" #else #define SEM_NAME1 "/tmp/nameshmSEM1" #define SEM_NAME2 "/tmp/nameshmSEM2" #define OPT_NAME "/tmp/xxxNSPRshm" #define EXE_NAME "nameshm1" #endif #define SEM_MODE 0666 #define SHM_MODE 0666 #define NameSize (1024) PRIntn debug = 0; PRIntn failed_already = 0; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRLogModuleInfo *lm; /* command line options */ PRIntn optDebug = 0; PRIntn optVerbose = 0; PRUint32 optWriteRO = 0; /* test write to read-only memory. should crash */ PRUint32 optClient = 0; PRUint32 optCreate = 1; PRUint32 optAttachRW = 1; PRUint32 optAttachRO = 1; PRUint32 optClose = 1; PRUint32 optDelete = 1; PRInt32 optPing = 1000; PRUint32 optSize = (10 * 1024 ); PRInt32 optClientIterations = 3; char optName[NameSize] = OPT_NAME; char buf[1024] = ""; static void BasicTest( void ) { PRSharedMemory *shm; char *addr; /* address of shared memory segment */ PRUint32 i; PRInt32 rc; PR_LOG( lm, msgLevel, ( "nameshm1: Begin BasicTest" )); if ( PR_FAILURE == PR_DeleteSharedMemory( optName )) { PR_LOG( lm, msgLevel, ("nameshm1: Initial PR_DeleteSharedMemory() failed. No problem")); } else PR_LOG( lm, msgLevel, ("nameshm1: Initial PR_DeleteSharedMemory() success")); shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE ); if ( NULL == shm ) { PR_LOG( lm, msgLevel, ( "nameshm1: RW Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RW Create: success: %p", shm )); addr = PR_AttachSharedMemory( shm , 0 ); if ( NULL == addr ) { PR_LOG( lm, msgLevel, ( "nameshm1: RW Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RW Attach: success: %p", addr )); /* fill memory with i */ for ( i = 0; i < optSize ; i++ ) { *(addr + i) = i; } rc = PR_DetachSharedMemory( shm, addr ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: RW Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RW Detach: success: " )); rc = PR_CloseSharedMemory( shm ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: RW Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RW Close: success: " )); rc = PR_DeleteSharedMemory( optName ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: RW Delete: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RW Delete: success: " )); PR_LOG( lm, msgLevel, ("nameshm1: BasicTest(): Passed")); return; } /* end BasicTest() */ static void ReadOnlyTest( void ) { PRSharedMemory *shm; char *roAddr; /* read-only address of shared memory segment */ PRInt32 rc; PR_LOG( lm, msgLevel, ( "nameshm1: Begin ReadOnlyTest" )); shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE); if ( NULL == shm ) { PR_LOG( lm, msgLevel, ( "nameshm1: RO Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RO Create: success: %p", shm )); roAddr = PR_AttachSharedMemory( shm , PR_SHM_READONLY ); if ( NULL == roAddr ) { PR_LOG( lm, msgLevel, ( "nameshm1: RO Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RO Attach: success: %p", roAddr )); if ( optWriteRO ) { *roAddr = 0x00; /* write to read-only memory */ failed_already = 1; PR_LOG( lm, msgLevel, ("nameshm1: Wrote to read-only memory segment!")); return; } rc = PR_DetachSharedMemory( shm, roAddr ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: RO Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RO Detach: success: " )); rc = PR_CloseSharedMemory( shm ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: RO Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RO Close: success: " )); rc = PR_DeleteSharedMemory( optName ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: RO Destroy: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: RO Destroy: success: " )); PR_LOG( lm, msgLevel, ("nameshm1: ReadOnlyTest(): Passed")); return; } /* end ReadOnlyTest() */ static void DoClient( void ) { PRStatus rc; PRSem *sem1, *sem2; PRSharedMemory *shm; PRUint32 *addr; PRInt32 i; PR_LOG( lm, msgLevel, ("nameshm1: DoClient(): Starting")); sem1 = PR_OpenSemaphore( SEM_NAME1, 0, 0, 0 ); PR_ASSERT( sem1 ); sem2 = PR_OpenSemaphore( SEM_NAME2, 0, 0, 0 ); PR_ASSERT( sem1 ); shm = PR_OpenSharedMemory( optName, optSize, 0, SHM_MODE ); if ( NULL == shm ) { PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Create: success: %p", shm )); addr = PR_AttachSharedMemory( shm , 0 ); if ( NULL == addr ) { PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Attach: success: %p", addr )); PR_LOG( lm, msgLevel, ( "Client found: %s", addr)); PR_Sleep(PR_SecondsToInterval(4)); for ( i = 0 ; i < optPing ; i++ ) { rc = PR_WaitSemaphore( sem2 ); PR_ASSERT( PR_FAILURE != rc ); (*addr)++; PR_ASSERT( (*addr % 2) == 0 ); if ( optVerbose ) PR_LOG( lm, msgLevel, ( "nameshm1: Client ping: %d, i: %d", *addr, i)); rc = PR_PostSemaphore( sem1 ); PR_ASSERT( PR_FAILURE != rc ); } rc = PR_CloseSemaphore( sem1 ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_CloseSemaphore( sem2 ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_DetachSharedMemory( shm, addr ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Detach: success: " )); rc = PR_CloseSharedMemory( shm ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: DoClient(): Close: success: " )); return; } /* end DoClient() */ static void ClientServerTest( void ) { PRStatus rc; PRSem *sem1, *sem2; PRProcess *proc; PRInt32 exit_status; PRSharedMemory *shm; PRUint32 *addr; PRInt32 i; char *child_argv[8]; char buf[24]; PR_LOG( lm, msgLevel, ( "nameshm1: Begin ClientServerTest" )); rc = PR_DeleteSharedMemory( optName ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: Server: Destroy: failed. No problem")); } else PR_LOG( lm, msgLevel, ( "nameshm1: Server: Destroy: success" )); shm = PR_OpenSharedMemory( optName, optSize, (PR_SHM_CREATE | PR_SHM_EXCL), SHM_MODE); if ( NULL == shm ) { PR_LOG( lm, msgLevel, ( "nameshm1: Server: Create: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: Server: Create: success: %p", shm )); addr = PR_AttachSharedMemory( shm , 0 ); if ( NULL == addr ) { PR_LOG( lm, msgLevel, ( "nameshm1: Server: Attach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: Server: Attach: success: %p", addr )); sem1 = PR_OpenSemaphore( SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0 ); PR_ASSERT( sem1 ); sem2 = PR_OpenSemaphore( SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 1 ); PR_ASSERT( sem1 ); strcpy( (char*)addr, "FooBar" ); child_argv[0] = EXE_NAME; child_argv[1] = "-C"; child_argv[2] = "-p"; sprintf( buf, "%d", optPing ); child_argv[3] = buf; child_argv[4] = optName; child_argv[5] = NULL; proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); PR_ASSERT( proc ); PR_Sleep( PR_SecondsToInterval(4)); *addr = 1; for ( i = 0 ; i < optPing ; i++ ) { rc = PR_WaitSemaphore( sem1 ); PR_ASSERT( PR_FAILURE != rc ); (*addr)++; PR_ASSERT( (*addr % 2) == 1 ); if ( optVerbose ) PR_LOG( lm, msgLevel, ( "nameshm1: Server pong: %d, i: %d", *addr, i)); rc = PR_PostSemaphore( sem2 ); PR_ASSERT( PR_FAILURE != rc ); } rc = PR_WaitProcess( proc, &exit_status ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_CloseSemaphore( sem1 ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_CloseSemaphore( sem2 ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_DeleteSemaphore( SEM_NAME1 ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_DeleteSemaphore( SEM_NAME2 ); PR_ASSERT( PR_FAILURE != rc ); rc = PR_DetachSharedMemory( shm, addr ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: Server: Detach: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: Server: Detach: success: " )); rc = PR_CloseSharedMemory( shm ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: Server: Close: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: Server: Close: success: " )); rc = PR_DeleteSharedMemory( optName ); if ( PR_FAILURE == rc ) { PR_LOG( lm, msgLevel, ( "nameshm1: Server: Destroy: Error: %ld. OSError: %ld", PR_GetError(), PR_GetOSError())); failed_already = 1; return; } PR_LOG( lm, msgLevel, ( "nameshm1: Server: Destroy: success" )); return; } /* end ClientServerTest() */ int main(int argc, char **argv) { { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "Cdvw:s:p:i:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'v': /* debug mode */ optVerbose = 1; /* no break! fall into debug option */ case 'd': /* debug mode */ debug = 1; msgLevel = PR_LOG_DEBUG; break; case 'w': /* try writing to memory mapped read-only */ optWriteRO = 1; break; case 'C': optClient = 1; break; case 's': optSize = atol(opt->value) * 1024; break; case 'p': optPing = atol(opt->value); break; case 'i': optClientIterations = atol(opt->value); break; default: strcpy( optName, opt->value ); break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ PR_LOG( lm, msgLevel, ( "nameshm1: Starting" )); if ( optClient ) { DoClient(); } else { BasicTest(); if ( failed_already != 0 ) goto Finished; ReadOnlyTest(); if ( failed_already != 0 ) goto Finished; ClientServerTest(); } Finished: if ( debug ) printf("%s\n", (failed_already)? "FAIL" : "PASS" ); return( (failed_already)? 1 : 0 ); } /* main() */ /* end instrumt.c */ nspr-4.11/nspr/pr/tests/nbconn.c0000644000000000000000000003330612623070344014743 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A test for nonblocking connect. Functions tested include PR_Connect, * PR_Poll, and PR_GetConnectStatus. * * The test should be invoked with a host name, for example: * nbconn www.netscape.com * It will do a nonblocking connect to port 80 (HTTP) on that host, * and when connected, issue the "GET /" HTTP command. * * You should run this test in three ways: * 1. To a known web site, such as www.netscape.com. The HTML of the * top-level page at the web site should be printed. * 2. To a machine not running a web server at port 80. This test should * fail. Ideally the error code should be PR_CONNECT_REFUSED_ERROR. * But it is possible to return PR_UNKNOWN_ERROR on certain platforms. * 3. To an unreachable machine, for example, a machine that is off line. * The test should fail after the connect times out. Ideally the * error code should be PR_IO_TIMEOUT_ERROR, but it is possible to * return PR_UNKNOWN_ERROR on certain platforms. */ #include "nspr.h" #include "plgetopt.h" #include #include #define SERVER_MAX_BIND_COUNT 100 #define DATA_BUF_SIZE 256 #define TCP_SERVER_PORT 10000 #define TCP_UNUSED_PORT 211 typedef struct Server_Param { PRFileDesc *sp_fd; /* server port */ } Server_Param; static void PR_CALLBACK TCP_Server(void *arg); int _debug_on; #define DPRINTF(arg) if (_debug_on) printf arg static PRIntn connection_success_test(); static PRIntn connection_failure_test(); int main(int argc, char **argv) { PRHostEnt he; char buf[1024]; PRNetAddr addr; PRPollDesc pd; PRStatus rv; PRSocketOptionData optData; const char *hostname = NULL; PRIntn default_case, n, bytes_read, bytes_sent; PRInt32 failed_already = 0; /* * -d debug mode */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* debug mode */ hostname = opt->value; break; case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); if (hostname) default_case = 0; else default_case = 1; if (default_case) { /* * In the default case the following tests are executed: * 1. successful connection: a server thread accepts a connection * from the main thread * 2. unsuccessful connection: the main thread tries to connect to a * nonexistent port and expects to get an error */ rv = connection_success_test(); if (rv == 0) rv = connection_failure_test(); return rv; } else { PRFileDesc *sock; if (PR_GetHostByName(argv[1], buf, sizeof(buf), &he) == PR_FAILURE) { printf( "Unknown host: %s\n", argv[1]); exit(1); } else { printf( "host: %s\n", buf); } PR_EnumerateHostEnt(0, &he, 80, &addr); sock = PR_NewTCPSocket(); optData.option = PR_SockOpt_Nonblocking; optData.value.non_blocking = PR_TRUE; PR_SetSocketOption(sock, &optData); rv = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); if (rv == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) { printf( "Connect in progress\n"); } pd.fd = sock; pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (n == -1) { printf( "PR_Poll failed\n"); exit(1); } printf( "PR_Poll returns %d\n", n); if (pd.out_flags & PR_POLL_READ) { printf( "PR_POLL_READ\n"); } if (pd.out_flags & PR_POLL_WRITE) { printf( "PR_POLL_WRITE\n"); } if (pd.out_flags & PR_POLL_EXCEPT) { printf( "PR_POLL_EXCEPT\n"); } if (pd.out_flags & PR_POLL_ERR) { printf( "PR_POLL_ERR\n"); } if (pd.out_flags & PR_POLL_NVAL) { printf( "PR_POLL_NVAL\n"); } if (PR_GetConnectStatus(&pd) == PR_SUCCESS) { printf("PR_GetConnectStatus: connect succeeded\n"); PR_Write(sock, "GET /\r\n\r\n", 9); PR_Shutdown(sock, PR_SHUTDOWN_SEND); pd.in_flags = PR_POLL_READ; while (1) { n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); printf( "poll returns %d\n", n); n = PR_Read(sock, buf, sizeof(buf)); printf( "read returns %d\n", n); if (n <= 0) { break; } PR_Write(PR_STDOUT, buf, n); } } else { if (PR_GetError() == PR_IN_PROGRESS_ERROR) { printf( "PR_GetConnectStatus: connect still in progress\n"); exit(1); } printf( "PR_GetConnectStatus: connect failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); } PR_Close(sock); printf( "PASS\n"); return 0; } } /* * TCP Server * Server Thread * Accept a connection from the client and write some data */ static void PR_CALLBACK TCP_Server(void *arg) { Server_Param *sp = (Server_Param *) arg; PRFileDesc *sockfd, *newsockfd; char data_buf[DATA_BUF_SIZE]; PRIntn rv, bytes_read; sockfd = sp->sp_fd; if ((newsockfd = PR_Accept(sockfd, NULL, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"ERROR - PR_Accept failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); return; } bytes_read = 0; while (bytes_read != DATA_BUF_SIZE) { rv = PR_Read(newsockfd, data_buf + bytes_read , DATA_BUF_SIZE - bytes_read); if (rv < 0) { fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); PR_Close(newsockfd); return; } PR_ASSERT(rv != 0); bytes_read += rv; } DPRINTF(("Bytes read from client - %d\n",bytes_read)); rv = PR_Write(newsockfd, data_buf,DATA_BUF_SIZE); if (rv < 0) { fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); PR_Close(newsockfd); return; } PR_ASSERT(rv == DATA_BUF_SIZE); DPRINTF(("Bytes written to client - %d\n",rv)); PR_Close(newsockfd); } /* * test for successful connection using a non-blocking socket */ static PRIntn connection_success_test() { PRFileDesc *sockfd = NULL, *conn_fd = NULL; PRNetAddr netaddr; PRInt32 i, rv; PRPollDesc pd; PRSocketOptionData optData; PRThread *thr = NULL; Server_Param sp; char send_buf[DATA_BUF_SIZE], recv_buf[DATA_BUF_SIZE]; PRIntn default_case, n, bytes_read, bytes_sent; PRIntn failed_already = 0; /* * Create a tcp socket */ if ((sockfd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"Error - PR_NewTCPSocket failed\n"); failed_already=1; goto def_exit; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = PR_AF_INET; netaddr.inet.port = PR_htons(TCP_SERVER_PORT); netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } if (PR_Listen(sockfd, 32) < 0) { fprintf(stderr,"ERROR - PR_Listen failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } if ((conn_fd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"Error - PR_NewTCPSocket failed\n"); failed_already=1; goto def_exit; } optData.option = PR_SockOpt_Nonblocking; optData.value.non_blocking = PR_TRUE; PR_SetSocketOption(conn_fd, &optData); rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv == PR_FAILURE) { if (PR_GetError() == PR_IN_PROGRESS_ERROR) { DPRINTF(("Connect in progress\n")); } else { fprintf(stderr,"Error - PR_Connect failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } } /* * Now create a thread to accept a connection */ sp.sp_fd = sockfd; thr = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)&sp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (thr == NULL) { fprintf(stderr,"Error - PR_CreateThread failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } DPRINTF(("Created TCP_Server thread [0x%x]\n",thr)); pd.fd = conn_fd; pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (n == -1) { fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } if (PR_GetConnectStatus(&pd) == PR_SUCCESS) { PRInt32 rv; DPRINTF(("Connection successful\n")); /* * Write some data, read it back and check data integrity to * make sure the connection is good */ pd.in_flags = PR_POLL_WRITE; bytes_sent = 0; memset(send_buf, 'a', DATA_BUF_SIZE); while (bytes_sent != DATA_BUF_SIZE) { rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (rv < 0) { fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_WRITE)); rv = PR_Write(conn_fd, send_buf + bytes_sent, DATA_BUF_SIZE - bytes_sent); if (rv < 0) { fprintf(stderr,"Error - PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } PR_ASSERT(rv > 0); bytes_sent += rv; } DPRINTF(("Bytes written to server - %d\n",bytes_sent)); PR_Shutdown(conn_fd, PR_SHUTDOWN_SEND); pd.in_flags = PR_POLL_READ; bytes_read = 0; memset(recv_buf, 0, DATA_BUF_SIZE); while (bytes_read != DATA_BUF_SIZE) { rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (rv < 0) { fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } PR_ASSERT((rv == 1) && (pd.out_flags == PR_POLL_READ)); rv = PR_Read(conn_fd, recv_buf + bytes_read , DATA_BUF_SIZE - bytes_read); if (rv < 0) { fprintf(stderr,"Error - PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } PR_ASSERT(rv != 0); bytes_read += rv; } DPRINTF(("Bytes read from server - %d\n",bytes_read)); /* * verify the data read */ if (memcmp(send_buf, recv_buf, DATA_BUF_SIZE) != 0) { fprintf(stderr,"ERROR - data corruption\n"); failed_already=1; goto def_exit; } DPRINTF(("Data integrity verified\n")); } else { fprintf(stderr,"PR_GetConnectStatus: connect failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already = 1; goto def_exit; } def_exit: if (thr) { PR_JoinThread(thr); thr = NULL; } if (sockfd) { PR_Close(sockfd); sockfd = NULL; } if (conn_fd) { PR_Close(conn_fd); conn_fd = NULL; } if (failed_already) return 1; else return 0; } /* * test for connection to a nonexistent port using a non-blocking socket */ static PRIntn connection_failure_test() { PRFileDesc *sockfd = NULL, *conn_fd = NULL; PRNetAddr netaddr; PRInt32 i, rv; PRPollDesc pd; PRSocketOptionData optData; PRIntn n, failed_already = 0; /* * Create a tcp socket */ if ((sockfd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"Error - PR_NewTCPSocket failed\n"); failed_already=1; goto def_exit; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = PR_AF_INET; netaddr.inet.port = PR_htons(TCP_SERVER_PORT); netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"ERROR - PR_Bind failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"ERROR - PR_GetSockName failed: (%d,%d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } #ifdef AIX /* * On AIX, set to unused/reserved port */ netaddr.inet.port = PR_htons(TCP_UNUSED_PORT); #endif if ((conn_fd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"Error - PR_NewTCPSocket failed\n"); failed_already=1; goto def_exit; } optData.option = PR_SockOpt_Nonblocking; optData.value.non_blocking = PR_TRUE; PR_SetSocketOption(conn_fd, &optData); rv = PR_Connect(conn_fd, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv == PR_FAILURE) { DPRINTF(("PR_Connect to a non-listen port failed: (%d, %d)\n", PR_GetError(), PR_GetOSError())); } else { PR_ASSERT(rv == PR_SUCCESS); fprintf(stderr,"Error - PR_Connect succeeded, expected to fail\n"); failed_already=1; goto def_exit; } pd.fd = conn_fd; pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (n == -1) { fprintf(stderr,"Error - PR_Poll failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto def_exit; } if (PR_GetConnectStatus(&pd) == PR_SUCCESS) { PRInt32 rv; fprintf(stderr,"PR_GetConnectStatus succeeded, expected to fail\n"); failed_already = 1; goto def_exit; } rv = PR_GetError(); DPRINTF(("Connection failed, successfully with PR_Error %d\n",rv)); def_exit: if (sockfd) { PR_Close(sockfd); sockfd = NULL; } if (conn_fd) { PR_Close(conn_fd); conn_fd = NULL; } if (failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/nblayer.c0000644000000000000000000005655712623070344015137 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prmem.h" #include "prprf.h" #include "prlog.h" #include "prerror.h" #include "prnetdb.h" #include "prthread.h" #include "plerror.h" #include "plgetopt.h" #include "prwin16.h" #include #include /* ** Testing layering of I/O ** ** The layered server ** A thread that acts as a server. It creates a TCP listener with a dummy ** layer pushed on top. Then listens for incoming connections. Each connection ** request for connection will be layered as well, accept one request, echo ** it back and close. ** ** The layered client ** Pretty much what you'd expect. */ static PRFileDesc *logFile; static PRDescIdentity identity; static PRNetAddr server_address; static PRIOMethods myMethods; typedef enum {rcv_get_debit, rcv_send_credit, rcv_data} RcvState; typedef enum {xmt_send_debit, xmt_recv_credit, xmt_data} XmtState; struct PRFilePrivate { RcvState rcvstate; XmtState xmtstate; PRInt32 rcvreq, rcvinprogress; PRInt32 xmtreq, xmtinprogress; }; typedef enum Verbosity {silent, quiet, chatty, noisy} Verbosity; static PRIntn minor_iterations = 5; static PRIntn major_iterations = 1; static Verbosity verbosity = quiet; static PRUint16 default_port = 12273; static PRFileDesc *PushLayer(PRFileDesc *stack) { PRStatus rv; PRFileDesc *layer = PR_CreateIOLayerStub(identity, &myMethods); layer->secret = PR_NEWZAP(PRFilePrivate); rv = PR_PushIOLayer(stack, PR_GetLayersIdentity(stack), layer); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > quiet) PR_fprintf(logFile, "Pushed layer(0x%x) onto stack(0x%x)\n", layer, stack); return stack; } /* PushLayer */ static PRFileDesc *PopLayer(PRFileDesc *stack) { PRFileDesc *popped = PR_PopIOLayer(stack, identity); if (verbosity > quiet) PR_fprintf(logFile, "Popped layer(0x%x) from stack(0x%x)\n", popped, stack); PR_DELETE(popped->secret); popped->dtor(popped); return stack; } /* PopLayer */ static void PR_CALLBACK Client(void *arg) { PRStatus rv; PRIntn mits; PRInt32 ready; PRUint8 buffer[100]; PRPollDesc polldesc; PRIntn empty_flags = 0; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; /* Initialize the buffer so that Purify won't complain */ memset(buffer, 0, sizeof(buffer)); rv = PR_Connect(stack, &server_address, PR_INTERVAL_NO_TIMEOUT); if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR == PR_GetError())) { if (verbosity > quiet) PR_fprintf(logFile, "Client connect 'in progress'\n"); do { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } if (verbosity > quiet) PR_fprintf( logFile, "Client connect 'in progress' [0x%x]\n", polldesc.out_flags); rv = PR_GetConnectStatus(&polldesc); if ((PR_FAILURE == rv) && (PR_IN_PROGRESS_ERROR != PR_GetError())) break; } while (PR_FAILURE == rv); } PR_ASSERT(PR_SUCCESS == rv); if (verbosity > chatty) PR_fprintf(logFile, "Client created connection\n"); for (mits = 0; mits < minor_iterations; ++mits) { bytes_sent = 0; if (verbosity > quiet) PR_fprintf(logFile, "Client sending %d bytes\n", sizeof(buffer)); do { if (verbosity > chatty) PR_fprintf( logFile, "Client sending %d bytes\n", sizeof(buffer) - bytes_sent); ready = PR_Send( stack, buffer + bytes_sent, sizeof(buffer) - bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Client send status [%d]\n", ready); if (0 < ready) bytes_sent += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_sent < sizeof(buffer)); PR_ASSERT(sizeof(buffer) == bytes_sent); bytes_read = 0; do { if (verbosity > chatty) PR_fprintf( logFile, "Client receiving %d bytes\n", bytes_sent - bytes_read); ready = PR_Recv( stack, buffer + bytes_read, bytes_sent - bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf( logFile, "Client receive status [%d]\n", ready); if (0 < ready) bytes_read += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_read < bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Client received %d bytes\n", bytes_read); PR_ASSERT(bytes_read == bytes_sent); } if (verbosity > quiet) PR_fprintf(logFile, "Client shutting down stack\n"); rv = PR_Shutdown(stack, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); } /* Client */ static void PR_CALLBACK Server(void *arg) { PRStatus rv; PRInt32 ready; PRUint8 buffer[100]; PRFileDesc *service; PRUintn empty_flags = 0; struct PRPollDesc polldesc; PRIntn bytes_read, bytes_sent; PRFileDesc *stack = (PRFileDesc*)arg; PRNetAddr client_address; do { if (verbosity > chatty) PR_fprintf(logFile, "Server accepting connection\n"); service = PR_Accept(stack, &client_address, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server accept status [0x%p]\n", service); if ((NULL == service) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = stack; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ | PR_POLL_EXCEPT; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } } while (NULL == service); PR_ASSERT(NULL != service); if (verbosity > quiet) PR_fprintf(logFile, "Server accepting connection\n"); do { bytes_read = 0; do { if (verbosity > chatty) PR_fprintf( logFile, "Server receiving %d bytes\n", sizeof(buffer) - bytes_read); ready = PR_Recv( service, buffer + bytes_read, sizeof(buffer) - bytes_read, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (verbosity > chatty) PR_fprintf(logFile, "Server receive status [%d]\n", ready); if (0 < ready) bytes_read += ready; else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = service; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_READ; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_read < sizeof(buffer)); if (0 != bytes_read) { if (verbosity > chatty) PR_fprintf(logFile, "Server received %d bytes\n", bytes_read); PR_ASSERT(bytes_read > 0); bytes_sent = 0; do { ready = PR_Send( service, buffer + bytes_sent, bytes_read - bytes_sent, empty_flags, PR_INTERVAL_NO_TIMEOUT); if (0 < ready) { bytes_sent += ready; } else if ((-1 == ready) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) { polldesc.fd = service; polldesc.out_flags = 0; polldesc.in_flags = PR_POLL_WRITE; ready = PR_Poll(&polldesc, 1, PR_INTERVAL_NO_TIMEOUT); if ((1 != ready) /* if not 1, then we're dead */ || (0 == (polldesc.in_flags & polldesc.out_flags))) { PR_NOT_REACHED("Whoa!"); break; } } else break; } while (bytes_sent < bytes_read); PR_ASSERT(bytes_read == bytes_sent); if (verbosity > chatty) PR_fprintf(logFile, "Server sent %d bytes\n", bytes_sent); } } while (0 != bytes_read); if (verbosity > quiet) PR_fprintf(logFile, "Server shutting down stack\n"); rv = PR_Shutdown(service, PR_SHUTDOWN_BOTH); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); } /* Server */ static PRStatus PR_CALLBACK MyClose(PRFileDesc *fd) { PR_DELETE(fd->secret); /* manage my secret file object */ return (PR_GetDefaultIOMethods())->close(fd); /* let him do all the work */ } /* MyClose */ static PRInt16 PR_CALLBACK MyPoll( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags) { PRInt16 my_flags, new_flags; PRFilePrivate *mine = (PRFilePrivate*)fd->secret; if (0 != (PR_POLL_READ & in_flags)) { /* client thinks he's reading */ switch (mine->rcvstate) { case rcv_send_credit: my_flags = (in_flags & ~PR_POLL_READ) | PR_POLL_WRITE; break; case rcv_data: case rcv_get_debit: my_flags = in_flags; default: break; } } else if (0 != (PR_POLL_WRITE & in_flags)) { /* client thinks he's writing */ switch (mine->xmtstate) { case xmt_recv_credit: my_flags = (in_flags & ~PR_POLL_WRITE) | PR_POLL_READ; break; case xmt_send_debit: case xmt_data: my_flags = in_flags; default: break; } } else PR_NOT_REACHED("How'd I get here?"); new_flags = (fd->lower->methods->poll)(fd->lower, my_flags, out_flags); if (verbosity > chatty) PR_fprintf( logFile, "Poll [i: 0x%x, m: 0x%x, o: 0x%x, n: 0x%x]\n", in_flags, my_flags, *out_flags, new_flags); return new_flags; } /* MyPoll */ static PRFileDesc * PR_CALLBACK MyAccept( PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout) { PRStatus rv; PRFileDesc *newfd, *layer = fd; PRFileDesc *newstack; PRFilePrivate *newsecret; PR_ASSERT(fd != NULL); PR_ASSERT(fd->lower != NULL); newstack = PR_NEW(PRFileDesc); if (NULL == newstack) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } newsecret = PR_NEW(PRFilePrivate); if (NULL == newsecret) { PR_DELETE(newstack); PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } *newstack = *fd; /* make a copy of the accepting layer */ *newsecret = *fd->secret; newstack->secret = newsecret; newfd = (fd->lower->methods->accept)(fd->lower, addr, timeout); if (NULL == newfd) { PR_DELETE(newsecret); PR_DELETE(newstack); return NULL; } /* this PR_PushIOLayer call cannot fail */ rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack); PR_ASSERT(PR_SUCCESS == rv); return newfd; /* that's it */ } static PRInt32 PR_CALLBACK MyRecv( PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { char *b; PRInt32 rv; PRFileDesc *lo = fd->lower; PRFilePrivate *mine = (PRFilePrivate*)fd->secret; do { switch (mine->rcvstate) { case rcv_get_debit: b = (char*)&mine->rcvreq; mine->rcvreq = amount; rv = lo->methods->recv( lo, b + mine->rcvinprogress, sizeof(mine->rcvreq) - mine->rcvinprogress, flags, timeout); if (0 == rv) goto closed; if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break; mine->rcvinprogress += rv; /* accumulate the read */ if (mine->rcvinprogress < sizeof(mine->rcvreq)) break; /* loop */ mine->rcvstate = rcv_send_credit; mine->rcvinprogress = 0; case rcv_send_credit: b = (char*)&mine->rcvreq; rv = lo->methods->send( lo, b + mine->rcvinprogress, sizeof(mine->rcvreq) - mine->rcvinprogress, flags, timeout); if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break; mine->rcvinprogress += rv; /* accumulate the read */ if (mine->rcvinprogress < sizeof(mine->rcvreq)) break; /* loop */ mine->rcvstate = rcv_data; mine->rcvinprogress = 0; case rcv_data: b = (char*)buf; rv = lo->methods->recv( lo, b + mine->rcvinprogress, mine->rcvreq - mine->rcvinprogress, flags, timeout); if (0 == rv) goto closed; if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break; mine->rcvinprogress += rv; /* accumulate the read */ if (mine->rcvinprogress < amount) break; /* loop */ mine->rcvstate = rcv_get_debit; mine->rcvinprogress = 0; return mine->rcvreq; /* << -- that's it! */ default: break; } } while (-1 != rv); return rv; closed: mine->rcvinprogress = 0; mine->rcvstate = rcv_get_debit; return 0; } /* MyRecv */ static PRInt32 PR_CALLBACK MySend( PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { char *b; PRInt32 rv; PRFileDesc *lo = fd->lower; PRFilePrivate *mine = (PRFilePrivate*)fd->secret; do { switch (mine->xmtstate) { case xmt_send_debit: b = (char*)&mine->xmtreq; mine->xmtreq = amount; rv = lo->methods->send( lo, b - mine->xmtinprogress, sizeof(mine->xmtreq) - mine->xmtinprogress, flags, timeout); if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break; mine->xmtinprogress += rv; if (mine->xmtinprogress < sizeof(mine->xmtreq)) break; mine->xmtstate = xmt_recv_credit; mine->xmtinprogress = 0; case xmt_recv_credit: b = (char*)&mine->xmtreq; rv = lo->methods->recv( lo, b + mine->xmtinprogress, sizeof(mine->xmtreq) - mine->xmtinprogress, flags, timeout); if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break; mine->xmtinprogress += rv; if (mine->xmtinprogress < sizeof(mine->xmtreq)) break; mine->xmtstate = xmt_data; mine->xmtinprogress = 0; case xmt_data: b = (char*)buf; rv = lo->methods->send( lo, b + mine->xmtinprogress, mine->xmtreq - mine->xmtinprogress, flags, timeout); if ((-1 == rv) && (PR_WOULD_BLOCK_ERROR == PR_GetError())) break; mine->xmtinprogress += rv; if (mine->xmtinprogress < amount) break; mine->xmtstate = xmt_send_debit; mine->xmtinprogress = 0; return mine->xmtreq; /* <<-- That's the one! */ default: break; } } while (-1 != rv); return rv; } /* MySend */ static Verbosity ChangeVerbosity(Verbosity verbosity, PRIntn delta) { PRIntn verbage = (PRIntn)verbosity + delta; if (verbage < (PRIntn)silent) verbage = (PRIntn)silent; else if (verbage > (PRIntn)noisy) verbage = (PRIntn)noisy; return (Verbosity)verbage; } /* ChangeVerbosity */ int main(int argc, char **argv) { PRStatus rv; PLOptStatus os; PRFileDesc *client, *service; PRNetAddr any_address; const char *server_name = NULL; const PRIOMethods *stubMethods; PRThread *client_thread, *server_thread; PRThreadScope thread_scope = PR_LOCAL_THREAD; PRSocketOptionData socket_noblock, socket_nodelay; PLOptState *opt = PL_CreateOptState(argc, argv, "dqGC:c:p:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: server_name = opt->value; break; case 'd': /* debug mode */ if (verbosity < noisy) verbosity = ChangeVerbosity(verbosity, 1); break; case 'q': /* debug mode */ if (verbosity > silent) verbosity = ChangeVerbosity(verbosity, -1); break; case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'C': /* number of threads waiting */ major_iterations = atoi(opt->value); break; case 'c': /* number of client threads */ minor_iterations = atoi(opt->value); break; case 'p': /* default port */ default_port = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); logFile = PR_GetSpecialFD(PR_StandardError); identity = PR_GetUniqueIdentity("Dummy"); stubMethods = PR_GetDefaultIOMethods(); /* ** The protocol we're going to implement is one where in order to initiate ** a send, the sender must first solicit permission. Therefore, every ** send is really a send - receive - send sequence. */ myMethods = *stubMethods; /* first get the entire batch */ myMethods.accept = MyAccept; /* then override the ones we care about */ myMethods.recv = MyRecv; /* then override the ones we care about */ myMethods.send = MySend; /* then override the ones we care about */ myMethods.close = MyClose; /* then override the ones we care about */ myMethods.poll = MyPoll; /* then override the ones we care about */ if (NULL == server_name) rv = PR_InitializeNetAddr( PR_IpAddrLoopback, default_port, &server_address); else { rv = PR_StringToNetAddr(server_name, &server_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_InitializeNetAddr( PR_IpAddrNull, default_port, &server_address); } PR_ASSERT(PR_SUCCESS == rv); socket_noblock.value.non_blocking = PR_TRUE; socket_noblock.option = PR_SockOpt_Nonblocking; socket_nodelay.value.no_delay = PR_TRUE; socket_nodelay.option = PR_SockOpt_NoDelay; /* one type w/o layering */ while (major_iterations-- > 0) { if (verbosity > silent) PR_fprintf(logFile, "Beginning non-layered test\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); rv = PR_SetSocketOption(client, &socket_noblock); PR_ASSERT(PR_SUCCESS == rv); rv = PR_SetSocketOption(service, &socket_noblock); PR_ASSERT(PR_SUCCESS == rv); rv = PR_SetSocketOption(client, &socket_nodelay); PR_ASSERT(PR_SUCCESS == rv); rv = PR_SetSocketOption(service, &socket_nodelay); PR_ASSERT(PR_SUCCESS == rv); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); server_thread = PR_CreateThread( PR_USER_THREAD, Server, service, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(client); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(service); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > silent) PR_fprintf(logFile, "Ending non-layered test\n"); /* with layering */ if (verbosity > silent) PR_fprintf(logFile, "Beginning layered test\n"); client = PR_NewTCPSocket(); PR_ASSERT(NULL != client); service = PR_NewTCPSocket(); PR_ASSERT(NULL != service); rv = PR_SetSocketOption(client, &socket_noblock); PR_ASSERT(PR_SUCCESS == rv); rv = PR_SetSocketOption(service, &socket_noblock); PR_ASSERT(PR_SUCCESS == rv); rv = PR_SetSocketOption(client, &socket_nodelay); PR_ASSERT(PR_SUCCESS == rv); rv = PR_SetSocketOption(service, &socket_nodelay); PR_ASSERT(PR_SUCCESS == rv); PushLayer(client); PushLayer(service); rv = PR_InitializeNetAddr(PR_IpAddrAny, default_port, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(service, &any_address); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(service, 10); PR_ASSERT(PR_SUCCESS == rv); server_thread = PR_CreateThread( PR_USER_THREAD, Server, service, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != server_thread); client_thread = PR_CreateThread( PR_USER_THREAD, Client, client, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 16 * 1024); PR_ASSERT(NULL != client_thread); rv = PR_JoinThread(client_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_JoinThread(server_thread); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(PopLayer(client)); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Close(PopLayer(service)); PR_ASSERT(PR_SUCCESS == rv); if (verbosity > silent) PR_fprintf(logFile, "Ending layered test\n"); } return 0; } /* main */ /* nblayer.c */ nspr-4.11/nspr/pr/tests/nonblock.c0000644000000000000000000001450112623070344015267 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "prio.h" #include "prerror.h" #include "prlog.h" #include "prprf.h" #include "prnetdb.h" #include "plerror.h" #include "obsolete/probslet.h" #include #include #include #define NUMBER_ROUNDS 5 #if defined(WIN16) /* ** Make win16 unit_time interval 300 milliseconds, others get 100 */ #define UNIT_TIME 200 /* unit time in milliseconds */ #elif defined(SYMBIAN) #define UNIT_TIME 5000 /* unit time in milliseconds */ #else #define UNIT_TIME 100 /* unit time in milliseconds */ #endif #define CHUNK_SIZE 10 #undef USE_PR_SELECT /* If defined, we use PR_Select. * If not defined, use PR_Poll instead. */ #if defined(USE_PR_SELECT) #include "pprio.h" #endif static void PR_CALLBACK clientThreadFunc(void *arg) { PRUintn port = (PRUintn)arg; PRFileDesc *sock; PRNetAddr addr; char buf[CHUNK_SIZE]; int i; PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME); PRSocketOptionData optval; PRStatus retVal; PRInt32 nBytes; /* Initialize the buffer so that Purify won't complain */ memset(buf, 0, sizeof(buf)); addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons((PRUint16)port); addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.ip); /* time 1 */ PR_Sleep(unitTime); sock = PR_NewTCPSocket(); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(sock, &optval); retVal = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); if (retVal == PR_FAILURE && PR_GetError() == PR_IN_PROGRESS_ERROR) { #if !defined(USE_PR_SELECT) PRPollDesc pd; PRInt32 n; fprintf(stderr, "connect: EWOULDBLOCK, good\n"); pd.fd = sock; pd.in_flags = PR_POLL_WRITE; n = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(n == 1); PR_ASSERT(pd.out_flags == PR_POLL_WRITE); #else PR_fd_set writeSet; PRInt32 n; fprintf(stderr, "connect: EWOULDBLOCK, good\n"); PR_FD_ZERO(&writeSet); PR_FD_SET(sock, &writeSet); n = PR_Select(0, NULL, &writeSet, NULL, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(n == 1); PR_ASSERT(PR_FD_ISSET(sock, &writeSet)); #endif } printf("client connected\n"); fflush(stdout); /* time 4, 7, 11, etc. */ for (i = 0; i < NUMBER_ROUNDS; i++) { PR_Sleep(3 * unitTime); nBytes = PR_Write(sock, buf, sizeof(buf)); if (nBytes == -1) { if (PR_GetError() == PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "write: EWOULDBLOCK\n"); exit(1); } else { fprintf(stderr, "write: failed\n"); } } printf("client sent %d bytes\n", nBytes); fflush(stdout); } PR_Close(sock); } static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { PRFileDesc *listenSock, *sock; PRUint16 listenPort; PRNetAddr addr; char buf[CHUNK_SIZE]; PRThread *clientThread; PRInt32 retVal; PRSocketOptionData optval; PRIntn i; PRIntervalTime unitTime = PR_MillisecondsToInterval(UNIT_TIME); /* Create a listening socket */ if ((listenSock = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } PR_snprintf(buf, sizeof(buf), "The server thread is listening on port %hu\n\n", listenPort); printf("%s", buf); clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("client thread created.\n"); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock, &optval); /* time 0 */ sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock != NULL || PR_GetError() != PR_WOULD_BLOCK_ERROR) { PL_PrintError("First Accept\n"); fprintf(stderr, "First PR_Accept() xxx\n" ); exit(1); } printf("accept: EWOULDBLOCK, good\n"); fflush(stdout); /* time 2 */ PR_Sleep(2 * unitTime); sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { PL_PrintError("Second Accept\n"); fprintf(stderr, "Second PR_Accept() failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("accept: succeeded, good\n"); fflush(stdout); PR_Close(listenSock); PR_SetSocketOption(sock, &optval); /* time 3, 5, 6, 8, etc. */ for (i = 0; i < NUMBER_ROUNDS; i++) { PR_Sleep(unitTime); retVal = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_WOULD_BLOCK_ERROR) { PL_PrintError("First Receive:\n"); fprintf(stderr, "First PR_Recv: retVal: %ld, Error: %ld\n", retVal, PR_GetError()); exit(1); } printf("read: EWOULDBLOCK, good\n"); fflush(stdout); PR_Sleep(2 * unitTime); retVal = PR_Recv(sock, buf, sizeof(buf), 0, PR_INTERVAL_NO_TIMEOUT); if (retVal != CHUNK_SIZE) { PL_PrintError("Second Receive:\n"); fprintf(stderr, "Second PR_Recv: retVal: %ld, Error: %ld\n", retVal, PR_GetError()); exit(1); } printf("read: %d bytes, good\n", retVal); fflush(stdout); } PR_Close(sock); printf("All tests finished\n"); printf("PASS\n"); return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/ntioto.c0000644000000000000000000002004412623070344014775 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: ntioto.c ** Description: ** This test, ntioto.c, was designed to reproduce a bug reported by NES ** on WindowsNT (fibers implementation). NSPR was asserting in ntio.c ** after PR_AcceptRead() had timed out. I/O performed subsequent to the ** call to PR_AcceptRead() could complete on a CPU other than the one ** on which it was started. The assert in ntio.c detected this, then ** asserted. ** ** Design: ** This test will fail with an assert in ntio.c if the problem it was ** designed to catch occurs. It returns 0 otherwise. ** ** The main() thread initializes and tears things down. A file is ** opened for writing; this file will be written to by AcceptThread() ** and JitterThread(). Main() creates a socket for reading, listens ** and binds the socket. ** ** ConnectThread() connects to the socket created by main, then polls ** the "state" variable. When state is AllDone, ConnectThread() exits. ** ** AcceptThread() calls PR_AcceptRead() on the socket. He fully expects ** it to time out. After the timeout, AccpetThread() interacts with ** JitterThread() via a common condition variable and the state ** variable. The two threads ping-pong back and forth, each thread ** writes the the file opened by main. This should provoke the ** condition reported by NES (if we didn't fix it). ** ** The failure is not solid. It may fail within a few ping-pongs between ** AcceptThread() and JitterThread() or may take a while. The default ** iteration count, jitter, is set by DEFAULT_JITTER. This may be ** modified at the command line with the -j option. ** */ #include #include #include #include #include /* ** Test harness infrastructure */ PRLogModuleInfo *lm; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRIntn debug = 0; PRIntn verbose = 0; PRUint32 failed_already = 0; /* end Test harness infrastructure */ /* JITTER_DEFAULT: the number of times AcceptThread() and JitterThread() ping-pong */ #define JITTER_DEFAULT 100000 #define BASE_PORT 9867 PRIntervalTime timeout; PRNetAddr listenAddr; PRFileDesc *listenSock; PRLock *ml; PRCondVar *cv; volatile enum { RunJitter, RunAcceptRead, AllDone } state = RunAcceptRead; PRFileDesc *file1; PRIntn iCounter = 0; PRIntn jitter = JITTER_DEFAULT; PRBool resume = PR_FALSE; /* ** Emit help text for this test */ static void Help( void ) { printf("Template: Help(): display your help message(s) here"); exit(1); } /* end Help() */ /* ** static computation of PR_AcceptRead() buffer size. */ #define ACCEPT_READ_DATASIZE 10 #define ACCEPT_READ_BUFSIZE (PR_ACCEPT_READ_BUF_OVERHEAD + ACCEPT_READ_DATASIZE) static void AcceptThread(void *arg) { PRIntn bytesRead; char dataBuf[ACCEPT_READ_BUFSIZE]; PRFileDesc *arSock; PRNetAddr *arAddr; bytesRead = PR_AcceptRead( listenSock, &arSock, &arAddr, dataBuf, ACCEPT_READ_DATASIZE, PR_SecondsToInterval(1)); if ( bytesRead == -1 && PR_GetError() == PR_IO_TIMEOUT_ERROR ) { if ( debug ) printf("AcceptRead timed out\n"); } else { if ( debug ) printf("Oops! read: %d, error: %d\n", bytesRead, PR_GetError()); } while( state != AllDone ) { PR_Lock( ml ); while( state != RunAcceptRead ) PR_WaitCondVar( cv, PR_INTERVAL_NO_TIMEOUT ); if ( ++iCounter >= jitter ) state = AllDone; else state = RunJitter; if ( verbose ) printf("."); PR_NotifyCondVar( cv ); PR_Unlock( ml ); PR_Write( file1, ".", 1 ); } return; } /* end AcceptThread() */ static void JitterThread(void *arg) { while( state != AllDone ) { PR_Lock( ml ); while( state != RunJitter && state != AllDone ) PR_WaitCondVar( cv, PR_INTERVAL_NO_TIMEOUT ); if ( state != AllDone) state = RunAcceptRead; if ( verbose ) printf("+"); PR_NotifyCondVar( cv ); PR_Unlock( ml ); PR_Write( file1, "+", 1 ); } return; } /* end Goofy() */ static void ConnectThread( void *arg ) { PRStatus rv; PRFileDesc *clientSock; PRNetAddr serverAddress; clientSock = PR_NewTCPSocket(); PR_ASSERT(clientSock); if ( resume ) { if ( debug ) printf("pausing 3 seconds before connect\n"); PR_Sleep( PR_SecondsToInterval(3)); } memset(&serverAddress, 0, sizeof(serverAddress)); rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &serverAddress); PR_ASSERT( PR_SUCCESS == rv ); rv = PR_Connect( clientSock, &serverAddress, PR_SecondsToInterval(1)); PR_ASSERT( PR_SUCCESS == rv ); /* that's all we do. ... Wait for the acceptread() to timeout */ while( state != AllDone ) PR_Sleep( PR_SecondsToInterval(1)); return; } /* end ConnectThread() */ int main(int argc, char **argv) { PRThread *tJitter; PRThread *tAccept; PRThread *tConnect; PRStatus rv; /* This test if valid for WinNT only! */ #if !defined(WINNT) return 0; #endif { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hdrvj:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_ERROR; break; case 'v': /* verbose mode */ verbose = 1; msgLevel = PR_LOG_DEBUG; break; case 'j': jitter = atoi(opt->value); if ( jitter == 0) jitter = JITTER_DEFAULT; break; case 'r': resume = PR_TRUE; break; case 'h': /* help message */ Help(); break; default: break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ /* set concurrency */ PR_SetConcurrency( 4 ); /* setup thread synchronization mechanics */ ml = PR_NewLock(); cv = PR_NewCondVar( ml ); /* setup a tcp socket */ memset(&listenAddr, 0, sizeof(listenAddr)); rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr); PR_ASSERT( PR_SUCCESS == rv ); listenSock = PR_NewTCPSocket(); PR_ASSERT( listenSock ); rv = PR_Bind( listenSock, &listenAddr); PR_ASSERT( PR_SUCCESS == rv ); rv = PR_Listen( listenSock, 5 ); PR_ASSERT( PR_SUCCESS == rv ); /* open a file for writing, provoke bug */ file1 = PR_Open("xxxTestFile", PR_CREATE_FILE | PR_RDWR, 666); /* create Connect thread */ tConnect = PR_CreateThread( PR_USER_THREAD, ConnectThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0 ); PR_ASSERT( tConnect ); /* create jitter off thread */ tJitter = PR_CreateThread( PR_USER_THREAD, JitterThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0 ); PR_ASSERT( tJitter ); /* create acceptread thread */ tAccept = PR_CreateThread( PR_USER_THREAD, AcceptThread, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0 ); PR_ASSERT( tAccept ); /* wait for all threads to quit, then terminate gracefully */ PR_JoinThread( tConnect ); PR_JoinThread( tAccept ); PR_JoinThread( tJitter ); PR_Close( listenSock ); PR_DestroyCondVar(cv); PR_DestroyLock(ml); PR_Close( file1 ); PR_Delete( "xxxTestFile"); /* test return and exit */ if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS"); return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */ /* end ntioto.c */ nspr-4.11/nspr/pr/tests/ntoh.c0000644000000000000000000000515512623070344014437 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A test program for PR_htons, PR_ntohs, PR_htonl, PR_ntohl, * PR_htonll, and PR_ntohll. */ #include "prnetdb.h" #include #include #include /* Byte sequence in network byte order */ static unsigned char bytes_n[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; /* Integers in host byte order */ static PRUint16 s_h = 0x0102; static PRUint32 l_h = 0x01020304; static PRUint64 ll_h = LL_INIT(0x01020304, 0x05060708); int main(int argc, char **argv) { union { PRUint16 s; PRUint32 l; PRUint64 ll; unsigned char bytes[8]; } un; un.s = s_h; printf("%u %u\n", un.bytes[0], un.bytes[1]); un.s = PR_htons(un.s); printf("%u %u\n", un.bytes[0], un.bytes[1]); if (memcmp(un.bytes, bytes_n, 2)) { fprintf(stderr, "PR_htons failed\n"); exit(1); } un.s = PR_ntohs(un.s); printf("%u %u\n", un.bytes[0], un.bytes[1]); if (un.s != s_h) { fprintf(stderr, "PR_ntohs failed\n"); exit(1); } un.l = l_h; printf("%u %u %u %u\n", un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]); un.l = PR_htonl(un.l); printf("%u %u %u %u\n", un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]); if (memcmp(un.bytes, bytes_n, 4)) { fprintf(stderr, "PR_htonl failed\n"); exit(1); } un.l = PR_ntohl(un.l); printf("%u %u %u %u\n", un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3]); if (un.l != l_h) { fprintf(stderr, "PR_ntohl failed\n"); exit(1); } un.ll = ll_h; printf("%u %u %u %u %u %u %u %u\n", un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3], un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]); un.ll = PR_htonll(un.ll); printf("%u %u %u %u %u %u %u %u\n", un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3], un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]); if (memcmp(un.bytes, bytes_n, 8)) { fprintf(stderr, "PR_htonll failed\n"); exit(1); } un.ll = PR_ntohll(un.ll); printf("%u %u %u %u %u %u %u %u\n", un.bytes[0], un.bytes[1], un.bytes[2], un.bytes[3], un.bytes[4], un.bytes[5], un.bytes[6], un.bytes[7]); if (LL_NE(un.ll, ll_h)) { fprintf(stderr, "PR_ntohll failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/obsints.c0000644000000000000000000000207712623070344015150 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test: obsints.c * * Description: make sure that protypes.h defines the obsolete integer * types intn, uintn, uint, int8, uint8, int16, uint16, int32, uint32, * int64, and uint64. */ #include #ifdef NO_NSPR_10_SUPPORT /* nothing to do */ int main(int argc, char **argv) { printf("PASS\n"); return 0; } #else /* NO_NSPR_10_SUPPORT */ #include "prtypes.h" /* which includes protypes.h */ int main(int argc, char **argv) { /* * Compilation fails if any of these integer types are not * defined by protypes.h. */ intn in; uintn uin; uint ui; int8 i8; uint8 ui8; int16 i16; uint16 ui16; int32 i32; uint32 ui32; int64 i64; uint64 ui64; printf("PASS\n"); return 0; } #endif /* NO_NSPR_10_SUPPORT */ nspr-4.11/nspr/pr/tests/op_2long.c0000644000000000000000000000337512623070344015210 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: op_2long.c ** ** Description: Test Program to verify the PR_NAME_TOO_LONG_ERROR ** ** Modification History: ** 03-June-97 AGarcia- Initial version ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "prinit.h" #include "prmem.h" #include "prio.h" #include "prerror.h" #include #include "plerror.h" #include "plgetopt.h" static PRFileDesc *t1; PRIntn error_code; /* * should exceed any system's maximum file name length * Note: was set at 4096. This is legal on some unix (Linux 2.1+) platforms. * */ #define TOO_LONG 5000 int main(int argc, char **argv) { char nameTooLong[TOO_LONG]; int i; /* Generate a really long pathname */ for (i = 0; i < TOO_LONG - 1; i++) { if (i % 10 == 0) { nameTooLong[i] = '/'; } else { nameTooLong[i] = 'a'; } } nameTooLong[TOO_LONG - 1] = 0; PR_STDIO_INIT(); t1 = PR_Open(nameTooLong, PR_RDWR, 0666); if (t1 == NULL) { if (PR_GetError() == PR_NAME_TOO_LONG_ERROR) { PL_PrintError("error code is"); printf ("PASS\n"); return 0; } else { PL_PrintError("error code is"); printf ("FAIL\n"); return 1; } } else { printf ("Test passed\n"); return 0; } } nspr-4.11/nspr/pr/tests/op_excl.c0000644000000000000000000000637412623070344015124 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: op_excl.c ** ** Description: Test Program to verify function of PR_EXCL open flag ** ** Modification History: ** 27-Oct-1999 lth. Initial version ***********************************************************************/ #include #include #include #include /* ** Test harness infrastructure */ PRLogModuleInfo *lm; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRIntn debug = 0; PRUint32 failed_already = 0; /* end Test harness infrastructure */ /* ** Emit help text for this test */ static void Help( void ) { printf("op_excl: Help"); printf("op_excl [-d]"); printf("-d enables debug messages"); exit(1); } /* end Help() */ int main(int argc, char **argv) { PRFileDesc *fd; PRStatus rv; PRInt32 written; char outBuf[] = "op_excl.c test file"; #define OUT_SIZE sizeof(outBuf) #define NEW_FILENAME "xxxExclNewFile" { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hd"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_ERROR; break; case 'h': /* help message */ Help(); break; default: break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ /* ** First, open a file, PR_EXCL, we believe not to exist */ fd = PR_Open( NEW_FILENAME, PR_CREATE_FILE | PR_EXCL | PR_WRONLY, 0666 ); if ( NULL == fd ) { if (debug) fprintf( stderr, "Open exclusive. Expected success, got failure\n"); failed_already = 1; goto Finished; } written = PR_Write( fd, outBuf, OUT_SIZE ); if ( OUT_SIZE != written ) { if (debug) fprintf( stderr, "Write after open exclusive failed\n"); failed_already = 1; goto Finished; } rv = PR_Close(fd); if ( PR_FAILURE == rv ) { if (debug) fprintf( stderr, "Close after open exclusive failed\n"); failed_already = 1; goto Finished; } /* ** Second, open the same file, PR_EXCL, expect it to fail */ fd = PR_Open( NEW_FILENAME, PR_CREATE_FILE | PR_EXCL | PR_WRONLY, 0666 ); if ( NULL != fd ) { if (debug) fprintf( stderr, "Open exclusive. Expected failure, got success\n"); failed_already = 1; PR_Close(fd); } rv = PR_Delete( NEW_FILENAME ); if ( PR_FAILURE == rv ) { if (debug) fprintf( stderr, "PR_Delete() failed\n"); failed_already = 1; } Finished: if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS"); return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */ /* end op_excl.c */ nspr-4.11/nspr/pr/tests/op_filnf.c0000644000000000000000000000274012623070344015260 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: op_filnf.c ** ** Description: Test Program to verify the PR_FILE_NOT_FOUND_ERROR ** This test program also uses the TRUNCATE option ** ** Modification History: ** 03-June-97 AGarcia- Initial version ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "prinit.h" #include "prmem.h" #include "prio.h" #include "prerror.h" #include #include "plgetopt.h" static PRFileDesc *t1; PRIntn error_code; int main(int argc, char **argv) { PR_STDIO_INIT(); t1 = PR_Open("/usr/tmp/ttools/err03.tmp", PR_TRUNCATE | PR_RDWR, 0666); if (t1 == NULL) { if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) { printf ("error code is %d \n", PR_GetError()); printf ("PASS\n"); return 0; } else { printf ("error code is %d \n", PR_GetError()); printf ("FAIL\n"); return 1; } } PR_Close(t1); printf ("opened a file that should not exist\n"); printf ("FAIL\n"); return 1; } nspr-4.11/nspr/pr/tests/op_filok.c0000644000000000000000000000252312623070344015265 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: op_filok.c ** ** Description: Test Program to verify the PR_Open finding an existing file. ** ** Modification History: ** 03-June-97 AGarcia- Initial version ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "prinit.h" #include "prmem.h" #include "prio.h" #include "prerror.h" #include static PRFileDesc *t1; int main(int argc, char **argv) { PR_STDIO_INIT(); t1 = PR_Open(argv[0], PR_RDONLY, 0666); if (t1 == NULL) { printf ("error code is %d \n", PR_GetError()); printf ("File %s should be found\n", argv[0]); return 1; } else { if (PR_Close(t1) == PR_SUCCESS) { printf ("Test passed \n"); return 0; } else { printf ("cannot close file\n"); printf ("error code is %d\n", PR_GetError()); return 1; } } } nspr-4.11/nspr/pr/tests/op_noacc.c0000644000000000000000000000272012623070344015243 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: op_noacc.c ** ** Description: Test Program to verify the PR_NO_ACCESS_RIGHTS_ERROR in PR_Open ** ** Modification History: ** 03-June-97 AGarcia- Initial version ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "prinit.h" #include "prmem.h" #include "prio.h" #include "prerror.h" #include #include "plgetopt.h" static PRFileDesc *err01; PRIntn error_code; int main(int argc, char **argv) { #ifdef XP_PC printf("op_noacc: Test not valid on MS-Windows.\n\tNo concept of 'mode' on Open() call\n"); return(0); #endif PR_STDIO_INIT(); err01 = PR_Open("err01.tmp", PR_CREATE_FILE | PR_RDWR, 0); if (err01 == NULL) { int error = PR_GetError(); printf ("error code is %d\n", error); if (error == PR_NO_ACCESS_RIGHTS_ERROR) { printf ("PASS\n"); return 0; } } printf ("FAIL\n"); return 1; } nspr-4.11/nspr/pr/tests/op_nofil.c0000644000000000000000000000311712623070344015270 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: op_nofil.c ** ** Description: Test Program to verify the PR_FILE_NOT_FOUND_ERROR ** ** Modification History: ** 03-June-97 AGarcia- Initial version ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "prinit.h" #include "prmem.h" #include "prio.h" #include "prerror.h" #include #include "plgetopt.h" /* * A file name that cannot exist */ #define NO_SUCH_FILE "/no/such/file.tmp" static PRFileDesc *t1; int main(int argc, char **argv) { PR_STDIO_INIT(); t1 = PR_Open(NO_SUCH_FILE, PR_RDONLY, 0666); if (t1 == NULL) { if (PR_GetError() == PR_FILE_NOT_FOUND_ERROR) { printf ("error code is PR_FILE_NOT_FOUND_ERROR, as expected\n"); printf ("PASS\n"); return 0; } else { printf ("error code is %d \n", PR_GetError()); printf ("FAIL\n"); return 1; } } printf ("File %s exists on this machine!?\n", NO_SUCH_FILE); if (PR_Close(t1) == PR_FAILURE) { printf ("cannot close file\n"); printf ("error code is %d \n", PR_GetError()); } printf ("FAIL\n"); return 1; } nspr-4.11/nspr/pr/tests/openfile.c0000644000000000000000000000620612623070344015266 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This test calls PR_OpenFile to create a bunch of files * with various file modes. */ #include "prio.h" #include "prerror.h" #include "prinit.h" #include #include #define TEMPLATE_FILE_NAME "template.txt" int main(int argc, char **argv) { FILE *template; char buf[32]; PRInt32 nbytes; PRFileDesc *fd; /* Write in text mode. Let stdio deal with line endings. */ template = fopen(TEMPLATE_FILE_NAME, "w"); fputs("line 1\nline 2\n", template); fclose(template); /* Read in binary mode */ fd = PR_OpenFile(TEMPLATE_FILE_NAME, PR_RDONLY, 0666); nbytes = PR_Read(fd, buf, sizeof(buf)); PR_Close(fd); PR_Delete(TEMPLATE_FILE_NAME); fd = PR_OpenFile("tfil0700.txt", PR_RDWR | PR_CREATE_FILE, 0700); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0500.txt", PR_RDWR | PR_CREATE_FILE, 0500); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0400.txt", PR_RDWR | PR_CREATE_FILE, 0400); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0644.txt", PR_RDWR | PR_CREATE_FILE, 0644); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0664.txt", PR_RDWR | PR_CREATE_FILE, 0664); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0660.txt", PR_RDWR | PR_CREATE_FILE, 0660); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0666.txt", PR_RDWR | PR_CREATE_FILE, 0666); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); fd = PR_OpenFile("tfil0640.txt", PR_RDWR | PR_CREATE_FILE, 0640); if (NULL == fd) { fprintf(stderr, "PR_OpenFile failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } PR_Write(fd, buf, nbytes); PR_Close(fd); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/parent.c0000644000000000000000000000633012623070344014754 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** file: parent.c ** description: test the process machinery */ #include "prmem.h" #include "prprf.h" #include "prinit.h" #include "prproces.h" #include "prinrval.h" typedef struct Child { const char *name; char **argv; PRProcess *process; PRProcessAttr *attr; } Child; /* for the default test 'cvar -c 2000' */ static char *default_argv[] = {"cvar", "-c", "2000", NULL}; static void PrintUsage(void) { PR_fprintf(PR_GetSpecialFD(PR_StandardError), "Usage: parent [-d] child [options]\n"); } int main(int argc, char **argv) { PRStatus rv; PRInt32 test_status = 1; PRIntervalTime t_start, t_elapsed; PRFileDesc *debug = NULL; Child *child = PR_NEWZAP(Child); if (1 == argc) { /* no command-line arguments: run the default test */ child->argv = default_argv; } else { argv += 1; /* don't care about our program name */ while (*argv != NULL && argv[0][0] == '-') { if (argv[0][1] == 'd') debug = PR_GetSpecialFD(PR_StandardError); else { PrintUsage(); return 2; /* not sufficient */ } argv += 1; } child->argv = argv; } if (NULL == *child->argv) { PrintUsage(); return 2; } child->name = *child->argv; if (NULL != debug) PR_fprintf(debug, "Forking %s\n", child->name); child->attr = PR_NewProcessAttr(); PR_ProcessAttrSetStdioRedirect( child->attr, PR_StandardOutput, PR_GetSpecialFD(PR_StandardOutput)); PR_ProcessAttrSetStdioRedirect( child->attr, PR_StandardError, PR_GetSpecialFD(PR_StandardError)); t_start = PR_IntervalNow(); child->process = PR_CreateProcess( child->name, child->argv, NULL, child->attr); t_elapsed = (PRIntervalTime) (PR_IntervalNow() - t_start); PR_DestroyProcessAttr(child->attr); test_status = (NULL == child->process) ? 1 : 0; if (NULL != debug) { PR_fprintf( debug, "Child was %sforked\n", (0 == test_status) ? "" : "NOT "); if (0 == test_status) PR_fprintf( debug, "PR_CreateProcess took %lu microseconds\n", PR_IntervalToMicroseconds(t_elapsed)); } if (0 == test_status) { if (NULL != debug) PR_fprintf(debug, "Waiting for child to exit\n"); rv = PR_WaitProcess(child->process, &test_status); if (PR_SUCCESS == rv) { if (NULL != debug) PR_fprintf( debug, "Child exited %s\n", (0 == test_status) ? "successfully" : "with error"); } else { test_status = 1; if (NULL != debug) PR_fprintf(debug, "PR_WaitProcess failed\n"); } } PR_DELETE(child); PR_Cleanup(); return test_status; } /* main */ /* parent.c */ nspr-4.11/nspr/pr/tests/parsetm.c0000644000000000000000000000471412623070344015142 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This test program should eventually become a full-blown test for * PR_ParseTimeString. Right now it just verifies that PR_ParseTimeString * doesn't crash on an out-of-range time string (bug 480740). */ #include "prtime.h" #include #include #include #include PRBool debug_mode = PR_TRUE; static char *dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" }; static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" }; static void PrintExplodedTime(const PRExplodedTime *et) { PRInt32 totalOffset; PRInt32 hourOffset, minOffset; const char *sign; /* Print day of the week, month, day, hour, minute, and second */ if (debug_mode) printf("%s %s %ld %02ld:%02ld:%02ld ", dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday, et->tm_hour, et->tm_min, et->tm_sec); /* Print time zone */ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset; if (totalOffset == 0) { if (debug_mode) printf("UTC "); } else { sign = "+"; if (totalOffset < 0) { totalOffset = -totalOffset; sign = "-"; } hourOffset = totalOffset / 3600; minOffset = (totalOffset % 3600) / 60; if (debug_mode) printf("%s%02ld%02ld ", sign, hourOffset, minOffset); } /* Print year */ if (debug_mode) printf("%hd", et->tm_year); } int main(int argc, char **argv) { PRTime ct; PRExplodedTime et; PRStatus rv; char *sp1 = "Sat, 1 Jan 3001 00:00:00"; /* no time zone */ char *sp2 = "Fri, 31 Dec 3000 23:59:60"; /* no time zone, not normalized */ #if _MSC_VER >= 1400 && !defined(WINCE) /* Run this test in the US Pacific Time timezone. */ _putenv_s("TZ", "PST8PDT"); _tzset(); #endif rv = PR_ParseTimeString(sp1, PR_FALSE, &ct); printf("rv = %d\n", rv); PR_ExplodeTime(ct, PR_GMTParameters, &et); PrintExplodedTime(&et); printf("\n"); rv = PR_ParseTimeString(sp2, PR_FALSE, &ct); printf("rv = %d\n", rv); PR_ExplodeTime(ct, PR_GMTParameters, &et); PrintExplodedTime(&et); printf("\n"); return 0; } nspr-4.11/nspr/pr/tests/peek.c0000644000000000000000000002604412623070344014413 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A test case for the PR_MSG_PEEK flag of PR_Recv(). * * Test both blocking and non-blocking sockets. */ #include "nspr.h" #include #include #include #define BUFFER_SIZE 1024 static int iterations = 10; /* * In iteration i, recv_amount[i] is the number of bytes we * wish to receive, and send_amount[i] is the number of bytes * we actually send. Therefore, the number of elements in the * recv_amount or send_amount array should equal to 'iterations'. * For this test to pass we need to ensure that * recv_amount[i] <= BUFFER_SIZE, * send_amount[i] <= BUFFER_SIZE, * send_amount[i] <= recv_amount[i]. */ static PRInt32 recv_amount[10] = { 16, 128, 256, 1024, 512, 512, 128, 256, 32, 32}; static PRInt32 send_amount[10] = { 16, 64, 128, 1024, 512, 256, 128, 64, 16, 32}; /* Blocking I/O */ static void ServerB(void *arg) { PRFileDesc *listenSock = (PRFileDesc *) arg; PRFileDesc *sock; char buf[BUFFER_SIZE]; PRInt32 nbytes; int i; int j; sock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == sock) { fprintf(stderr, "PR_Accept failed\n"); exit(1); } for (i = 0; i < iterations; i++) { memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i, buf[j]); exit(1); } } fprintf(stderr, "server: peeked expected data\n"); memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i, buf[j]); exit(1); } } fprintf(stderr, "server: peeked expected data\n"); memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i, buf[j]); exit(1); } } fprintf(stderr, "server: received expected data\n"); PR_Sleep(PR_SecondsToInterval(1)); memset(buf, 2*i+1, send_amount[i]); nbytes = PR_Send(sock, buf, send_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Send failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); exit(1); } } if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } /* Non-blocking I/O */ static void ClientNB(void *arg) { PRFileDesc *sock; PRSocketOptionData opt; PRUint16 port = (PRUint16) arg; PRNetAddr addr; char buf[BUFFER_SIZE]; PRPollDesc pd; PRInt32 npds; PRInt32 nbytes; int i; int j; sock = PR_OpenTCPSocket(PR_AF_INET6); if (NULL == sock) { fprintf(stderr, "PR_OpenTCPSocket failed\n"); exit(1); } opt.option = PR_SockOpt_Nonblocking; opt.value.non_blocking = PR_TRUE; if (PR_SetSocketOption(sock, &opt) == PR_FAILURE) { fprintf(stderr, "PR_SetSocketOption failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, port, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { if (PR_GetError() != PR_IN_PROGRESS_ERROR) { fprintf(stderr, "PR_Connect failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT; npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (-1 == npds) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } if (1 != npds) { fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); exit(1); } if (PR_GetConnectStatus(&pd) == PR_FAILURE) { fprintf(stderr, "PR_GetConnectStatus failed\n"); exit(1); } } for (i = 0; i < iterations; i++) { PR_Sleep(PR_SecondsToInterval(1)); memset(buf, 2*i, send_amount[i]); while ((nbytes = PR_Send(sock, buf, send_amount[i], 0, PR_INTERVAL_NO_TIMEOUT)) == -1) { if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "PR_Send failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_WRITE; npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (-1 == npds) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } if (1 != npds) { fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); exit(1); } } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Send returned %d, absurd!\n", nbytes); exit(1); } memset(buf, 0, sizeof(buf)); while ((nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT)) == -1) { if (PR_GetError() != PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_READ; npds = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (-1 == npds) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } if (1 != npds) { fprintf(stderr, "PR_Poll returned %d, absurd!\n", npds); exit(1); } } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i+1) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i+1, buf[j]); exit(1); } } fprintf(stderr, "client: peeked expected data\n"); memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], PR_MSG_PEEK, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i+1) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i+1, buf[j]); exit(1); } } fprintf(stderr, "client: peeked expected data\n"); memset(buf, 0, sizeof(buf)); nbytes = PR_Recv(sock, buf, recv_amount[i], 0, PR_INTERVAL_NO_TIMEOUT); if (-1 == nbytes) { fprintf(stderr, "PR_Recv failed\n"); exit(1); } if (send_amount[i] != nbytes) { fprintf(stderr, "PR_Recv returned %d, absurd!\n", nbytes); exit(1); } for (j = 0; j < nbytes; j++) { if (buf[j] != 2*i+1) { fprintf(stderr, "byte %d should be %d but is %d\n", j, 2*i+1, buf[j]); exit(1); } } fprintf(stderr, "client: received expected data\n"); } if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } static void RunTest(PRThreadScope scope, PRFileDesc *listenSock, PRUint16 port) { PRThread *server, *client; server = PR_CreateThread(PR_USER_THREAD, ServerB, listenSock, PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (NULL == server) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } client = PR_CreateThread( PR_USER_THREAD, ClientNB, (void *) port, PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (NULL == client) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } if (PR_JoinThread(server) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } if (PR_JoinThread(client) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } } int main(int argc, char **argv) { PRFileDesc *listenSock; PRNetAddr addr; PRUint16 port; listenSock = PR_OpenTCPSocket(PR_AF_INET6); if (NULL == listenSock) { fprintf(stderr, "PR_OpenTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_SetNetAddr failed\n"); exit(1); } if (PR_Bind(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } port = PR_ntohs(addr.ipv6.port); if (PR_Listen(listenSock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } fprintf(stderr, "Running the test with local threads\n"); RunTest(PR_LOCAL_THREAD, listenSock, port); fprintf(stderr, "Running the test with global threads\n"); RunTest(PR_GLOBAL_THREAD, listenSock, port); if (PR_Close(listenSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/perf.c0000644000000000000000000002621312623070344014421 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #include #include int _debug_on = 0; #define DPRINTF(arg) if (_debug_on) printf arg #include "obsolete/prsem.h" PRLock *lock; PRMonitor *mon; PRMonitor *mon2; #define DEFAULT_COUNT 1000 PRInt32 count; static void nop(int a, int b, int c) { } static void LocalProcedureCall(void) { PRInt32 i; for (i = 0; i < count; i++) { nop(i, i, 5); } } static void DLLProcedureCall(void) { PRInt32 i; PRThreadState state; PRThread *self = PR_GetCurrentThread(); for (i = 0; i < count; i++) { state = PR_GetThreadState(self); } } static void Now(void) { PRInt32 i; PRTime time; for (i = 0; i < count; i++) { time = PR_Now(); } } static void Interval(void) { PRInt32 i; PRIntervalTime time; for (i = 0; i < count; i++) { time = PR_IntervalNow(); } } static void IdleLock(void) { PRInt32 i; for (i = 0; i < count; i++) { PR_Lock(lock); PR_Unlock(lock); } } static void IdleMonitor(void) { PRInt32 i; for (i = 0; i < count; i++) { PR_EnterMonitor(mon); PR_ExitMonitor(mon); } } static void IdleCMonitor(void) { PRInt32 i; for (i = 0; i < count; i++) { PR_CEnterMonitor((void*)7); PR_CExitMonitor((void*)7); } } /************************************************************************/ static void PR_CALLBACK dull(void *arg) { } static void CDThread(void) { PRInt32 i; int num_threads = count; /* * Cannot create too many threads */ if (num_threads > 1000) num_threads = 1000; for (i = 0; i < num_threads; i++) { PRThread *t = PR_CreateThread(PR_USER_THREAD, dull, 0, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (NULL == t) { fprintf(stderr, "CDThread: cannot create thread %3d\n", i); } else { DPRINTF(("CDThread: created thread %3d \n",i)); } PR_Sleep(0); } } static int alive; static int cxq; static void PR_CALLBACK CXReader(void *arg) { PRInt32 i, n; PR_EnterMonitor(mon); n = count / 2; for (i = 0; i < n; i++) { while (cxq == 0) { DPRINTF(("CXReader: thread = 0x%lx waiting\n", PR_GetCurrentThread())); PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } --cxq; PR_Notify(mon); } PR_ExitMonitor(mon); PR_EnterMonitor(mon2); --alive; PR_Notify(mon2); PR_ExitMonitor(mon2); DPRINTF(("CXReader: thread = 0x%lx exiting\n", PR_GetCurrentThread())); } static void PR_CALLBACK CXWriter(void *arg) { PRInt32 i, n; PR_EnterMonitor(mon); n = count / 2; for (i = 0; i < n; i++) { while (cxq == 1) { DPRINTF(("CXWriter: thread = 0x%lx waiting\n", PR_GetCurrentThread())); PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } ++cxq; PR_Notify(mon); } PR_ExitMonitor(mon); PR_EnterMonitor(mon2); --alive; PR_Notify(mon2); PR_ExitMonitor(mon2); DPRINTF(("CXWriter: thread = 0x%lx exiting\n", PR_GetCurrentThread())); } static void ContextSwitch(PRThreadScope scope1, PRThreadScope scope2) { PRThread *t1, *t2; PR_EnterMonitor(mon2); alive = 2; cxq = 0; t1 = PR_CreateThread(PR_USER_THREAD, CXReader, 0, PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0); if (NULL == t1) { fprintf(stderr, "ContextSwitch: cannot create thread\n"); } else { DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n", (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"), t1)); } t2 = PR_CreateThread(PR_USER_THREAD, CXWriter, 0, PR_PRIORITY_NORMAL, scope2, PR_UNJOINABLE_THREAD, 0); if (NULL == t2) { fprintf(stderr, "ContextSwitch: cannot create thread\n"); } else { DPRINTF(("ContextSwitch: created %s thread = 0x%lx\n", (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"), t2)); } /* Wait for both of the threads to exit */ while (alive) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(mon2); } static void ContextSwitchUU(void) { ContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD); } static void ContextSwitchUK(void) { ContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); } static void ContextSwitchKU(void) { ContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); } static void ContextSwitchKK(void) { ContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); } /************************************************************************/ static void PR_CALLBACK SemaThread(void *argSema) { PRSemaphore **sem = (PRSemaphore **)argSema; PRInt32 i, n; n = count / 2; for (i = 0; i < n; i++) { DPRINTF(("SemaThread: thread = 0x%lx waiting on sem = 0x%lx\n", PR_GetCurrentThread(), sem[0])); PR_WaitSem(sem[0]); DPRINTF(("SemaThread: thread = 0x%lx posting on sem = 0x%lx\n", PR_GetCurrentThread(), sem[1])); PR_PostSem(sem[1]); } PR_EnterMonitor(mon2); --alive; PR_Notify(mon2); PR_ExitMonitor(mon2); DPRINTF(("SemaThread: thread = 0x%lx exiting\n", PR_GetCurrentThread())); } static PRSemaphore *sem_set1[2]; static PRSemaphore *sem_set2[2]; static void SemaContextSwitch(PRThreadScope scope1, PRThreadScope scope2) { PRThread *t1, *t2; sem_set1[0] = PR_NewSem(1); sem_set1[1] = PR_NewSem(0); sem_set2[0] = sem_set1[1]; sem_set2[1] = sem_set1[0]; PR_EnterMonitor(mon2); alive = 2; cxq = 0; t1 = PR_CreateThread(PR_USER_THREAD, SemaThread, sem_set1, PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0); if (NULL == t1) { fprintf(stderr, "SemaContextSwitch: cannot create thread\n"); } else { DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n", (scope1 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"), t1)); } t2 = PR_CreateThread(PR_USER_THREAD, SemaThread, sem_set2, PR_PRIORITY_NORMAL, scope2, PR_UNJOINABLE_THREAD, 0); if (NULL == t2) { fprintf(stderr, "SemaContextSwitch: cannot create thread\n"); } else { DPRINTF(("SemaContextSwitch: created %s thread = 0x%lx\n", (scope2 == PR_GLOBAL_THREAD ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD"), t2)); } /* Wait for both of the threads to exit */ while (alive) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(mon2); PR_DestroySem(sem_set1[0]); PR_DestroySem(sem_set1[1]); } static void SemaContextSwitchUU(void) { SemaContextSwitch(PR_LOCAL_THREAD, PR_LOCAL_THREAD); } static void SemaContextSwitchUK(void) { SemaContextSwitch(PR_LOCAL_THREAD, PR_GLOBAL_THREAD); } static void SemaContextSwitchKU(void) { SemaContextSwitch(PR_GLOBAL_THREAD, PR_LOCAL_THREAD); } static void SemaContextSwitchKK(void) { SemaContextSwitch(PR_GLOBAL_THREAD, PR_GLOBAL_THREAD); } /************************************************************************/ static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow() - start; d = (double)PR_IntervalToMicroseconds(stop); printf("%40s: %6.2f usec\n", msg, d / count); } int main(int argc, char **argv) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dc:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; case 'c': /* loop count */ count = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (0 == count) count = DEFAULT_COUNT; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_BlockClockInterrupts(); PR_UnblockClockInterrupts(); PR_STDIO_INIT(); lock = PR_NewLock(); mon = PR_NewMonitor(); mon2 = PR_NewMonitor(); Measure(LocalProcedureCall, "local procedure call overhead"); Measure(DLLProcedureCall, "DLL procedure call overhead"); Measure(Now, "current calendar time"); Measure(Interval, "interval time"); Measure(IdleLock, "idle lock lock/unlock pair"); Measure(IdleMonitor, "idle monitor entry/exit pair"); Measure(IdleCMonitor, "idle cache monitor entry/exit pair"); Measure(CDThread, "create/destroy thread pair"); Measure(ContextSwitchUU, "context switch - user/user"); Measure(ContextSwitchUK, "context switch - user/kernel"); Measure(ContextSwitchKU, "context switch - kernel/user"); Measure(ContextSwitchKK, "context switch - kernel/kernel"); Measure(SemaContextSwitchUU, "sema context switch - user/user"); Measure(SemaContextSwitchUK, "sema context switch - user/kernel"); Measure(SemaContextSwitchKU, "sema context switch - kernel/user"); Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel"); printf("--------------\n"); printf("Adding 7 additional CPUs\n"); PR_SetConcurrency(8); printf("--------------\n"); Measure(LocalProcedureCall, "local procedure call overhead"); Measure(DLLProcedureCall, "DLL procedure call overhead"); Measure(Now, "current calendar time"); Measure(Interval, "interval time"); Measure(IdleLock, "idle lock lock/unlock pair"); Measure(IdleMonitor, "idle monitor entry/exit pair"); Measure(IdleCMonitor, "idle cache monitor entry/exit pair"); Measure(CDThread, "create/destroy thread pair"); Measure(ContextSwitchUU, "context switch - user/user"); Measure(ContextSwitchUK, "context switch - user/kernel"); Measure(ContextSwitchKU, "context switch - kernel/user"); Measure(ContextSwitchKK, "context switch - kernel/kernel"); Measure(SemaContextSwitchUU, "sema context switch - user/user"); Measure(SemaContextSwitchUK, "sema context switch - user/kernel"); Measure(SemaContextSwitchKU, "sema context switch - kernel/user"); Measure(SemaContextSwitchKK, "sema context switch - kernel/kernel"); PR_DestroyLock(lock); PR_DestroyMonitor(mon); PR_DestroyMonitor(mon2); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/pipeping.c0000644000000000000000000001100512623070344015271 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pipeping.c * * Description: * This test runs in conjunction with the pipepong test. * This test creates two pipes and redirects the stdin and * stdout of the pipepong test to the pipes. Then this * test writes "ping" to the pipepong test and the pipepong * test writes "pong" back. To run this pair of tests, * just invoke pipeping. * * Tested areas: process creation, pipes, file descriptor * inheritance, standard I/O redirection. */ #include "prerror.h" #include "prio.h" #include "prproces.h" #include #include #include #ifdef XP_OS2 static char *child_argv[] = { "pipepong.exe", NULL }; #else static char *child_argv[] = { "pipepong", NULL }; #endif #define NUM_ITERATIONS 10 int main(int argc, char **argv) { PRFileDesc *in_pipe[2]; PRFileDesc *out_pipe[2]; PRStatus status; PRProcess *process; PRProcessAttr *attr; char buf[1024]; PRInt32 nBytes; PRInt32 exitCode; int idx; status = PR_CreatePipe(&in_pipe[0], &in_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } status = PR_CreatePipe(&out_pipe[0], &out_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } status = PR_SetFDInheritable(in_pipe[0], PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } status = PR_SetFDInheritable(in_pipe[1], PR_TRUE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } status = PR_SetFDInheritable(out_pipe[0], PR_TRUE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } status = PR_SetFDInheritable(out_pipe[1], PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } attr = PR_NewProcessAttr(); if (attr == NULL) { fprintf(stderr, "PR_NewProcessAttr failed\n"); exit(1); } PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, out_pipe[0]); PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, in_pipe[1]); process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr); if (process == NULL) { fprintf(stderr, "PR_CreateProcess failed\n"); exit(1); } PR_DestroyProcessAttr(attr); status = PR_Close(out_pipe[0]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(in_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { strcpy(buf, "ping"); printf("ping process: sending \"%s\"\n", buf); nBytes = PR_Write(out_pipe[1], buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } memset(buf, 0, sizeof(buf)); nBytes = PR_Read(in_pipe[0], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("ping process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "pong") != 0) { fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n", buf); exit(1); } } status = PR_Close(in_pipe[0]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(out_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_WaitProcess(process, &exitCode); if (status == PR_FAILURE) { fprintf(stderr, "PR_WaitProcess failed\n"); exit(1); } if (exitCode == 0) { printf("PASS\n"); return 0; } else { printf("FAIL\n"); return 1; } } nspr-4.11/nspr/pr/tests/pipeping2.c0000644000000000000000000001111212623070344015352 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pipeping2.c * * Description: * This test runs in conjunction with the pipepong2 test. * This test creates two pipes and passes two pipe fd's * to the pipepong2 test. Then this test writes "ping" to * to the pipepong2 test and the pipepong2 test writes "pong" * back. To run this pair of tests, just invoke pipeping2. * * Tested areas: process creation, pipes, file descriptor * inheritance. */ #include "prerror.h" #include "prio.h" #include "prproces.h" #include #include #include #define NUM_ITERATIONS 10 static char *child_argv[] = { "pipepong2", NULL }; int main(int argc, char **argv) { PRFileDesc *in_pipe[2]; PRFileDesc *out_pipe[2]; PRStatus status; PRProcess *process; PRProcessAttr *attr; char buf[1024]; PRInt32 nBytes; PRInt32 exitCode; int idx; status = PR_CreatePipe(&in_pipe[0], &in_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } status = PR_CreatePipe(&out_pipe[0], &out_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } status = PR_SetFDInheritable(in_pipe[0], PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } status = PR_SetFDInheritable(in_pipe[1], PR_TRUE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } status = PR_SetFDInheritable(out_pipe[0], PR_TRUE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } status = PR_SetFDInheritable(out_pipe[1], PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } attr = PR_NewProcessAttr(); if (attr == NULL) { fprintf(stderr, "PR_NewProcessAttr failed\n"); exit(1); } status = PR_ProcessAttrSetInheritableFD(attr, out_pipe[0], "PIPE_READ"); if (status == PR_FAILURE) { fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n"); exit(1); } status = PR_ProcessAttrSetInheritableFD(attr, in_pipe[1], "PIPE_WRITE"); if (status == PR_FAILURE) { fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n"); exit(1); } process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr); if (process == NULL) { fprintf(stderr, "PR_CreateProcess failed\n"); exit(1); } PR_DestroyProcessAttr(attr); status = PR_Close(out_pipe[0]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(in_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { strcpy(buf, "ping"); printf("ping process: sending \"%s\"\n", buf); nBytes = PR_Write(out_pipe[1], buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } memset(buf, 0, sizeof(buf)); nBytes = PR_Read(in_pipe[0], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed\n"); exit(1); } printf("ping process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "pong") != 0) { fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n", buf); exit(1); } } status = PR_Close(in_pipe[0]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(out_pipe[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_WaitProcess(process, &exitCode); if (status == PR_FAILURE) { fprintf(stderr, "PR_WaitProcess failed\n"); exit(1); } if (exitCode == 0) { printf("PASS\n"); return 0; } else { printf("FAIL\n"); return 1; } } nspr-4.11/nspr/pr/tests/pipepong.c0000644000000000000000000000342612623070344015307 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pipepong.c * * Description: * This test runs in conjunction with the pipeping test. * The pipeping test creates two pipes and redirects the * stdin and stdout of this test to the pipes. Then the * pipeping test writes "ping" to this test and this test * writes "pong" back. Note that this test does not depend * on NSPR at all. To run this pair of tests, just invoke * pipeping. * * Tested areas: process creation, pipes, file descriptor * inheritance, standard I/O redirection. */ #include #include #include #define NUM_ITERATIONS 10 int main(int argc, char **argv) { char buf[1024]; size_t nBytes; int idx; for (idx = 0; idx < NUM_ITERATIONS; idx++) { memset(buf, 0, sizeof(buf)); nBytes = fread(buf, 1, 5, stdin); fprintf(stderr, "pong process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "ping") != 0) { fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n", buf); exit(1); } strcpy(buf, "pong"); fprintf(stderr, "pong process: sending \"%s\"\n", buf); nBytes = fwrite(buf, 1, 5, stdout); if (nBytes != 5) { fprintf(stderr, "pong process: fwrite failed\n"); exit(1); } fflush(stdout); } return 0; } nspr-4.11/nspr/pr/tests/pipepong2.c0000644000000000000000000000546112623070344015372 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pipepong2.c * * Description: * This test runs in conjunction with the pipeping2 test. * The pipeping2 test creates two pipes and passes two * pipe fd's to this test. Then the pipeping2 test writes * "ping" to this test and this test writes "pong" back. * To run this pair of tests, just invoke pipeping2. * * Tested areas: process creation, pipes, file descriptor * inheritance. */ #include "prerror.h" #include "prio.h" #include #include #include #define NUM_ITERATIONS 10 int main(int argc, char **argv) { PRFileDesc *pipe_read, *pipe_write; PRStatus status; char buf[1024]; PRInt32 nBytes; int idx; pipe_read = PR_GetInheritedFD("PIPE_READ"); if (pipe_read == NULL) { fprintf(stderr, "PR_GetInheritedFD failed\n"); exit(1); } status = PR_SetFDInheritable(pipe_read, PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } pipe_write = PR_GetInheritedFD("PIPE_WRITE"); if (pipe_write == NULL) { fprintf(stderr, "PR_GetInheritedFD failed\n"); exit(1); } status = PR_SetFDInheritable(pipe_write, PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { memset(buf, 0, sizeof(buf)); nBytes = PR_Read(pipe_read, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("pong process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "ping") != 0) { fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n", buf); exit(1); } strcpy(buf, "pong"); printf("pong process: sending \"%s\"\n", buf); nBytes = PR_Write(pipe_write, buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed\n"); exit(1); } } status = PR_Close(pipe_read); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(pipe_write); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } return 0; } nspr-4.11/nspr/pr/tests/pipeself.c0000644000000000000000000001447712623070344015305 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: pipeself.c * * Description: * This test has two threads communicating with each other using * two unidirectional pipes. The primordial thread is the ping * thread and the other thread is the pong thread. The ping * thread writes "ping" to the pong thread and the pong thread * writes "pong" back. */ #include "prio.h" #include "prerror.h" #include "prthread.h" #include #include #include #define NUM_ITERATIONS 10 static PRFileDesc *ping_in, *ping_out; static PRFileDesc *pong_in, *pong_out; static void PongThreadFunc(void *arg) { char buf[1024]; int idx; PRInt32 nBytes; PRStatus status; for (idx = 0; idx < NUM_ITERATIONS; idx++) { memset(buf, 0, sizeof(buf)); nBytes = PR_Read(pong_in, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed\n"); exit(1); } printf("pong thread: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "pong thread: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "ping") != 0) { fprintf(stderr, "pong thread: expected \"ping\" but got \"%s\"\n", buf); exit(1); } strcpy(buf, "pong"); printf("pong thread: sending \"%s\"\n", buf); nBytes = PR_Write(pong_out, buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } } status = PR_Close(pong_in); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(pong_out); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } int main(int argc, char **argv) { PRStatus status; PRThread *pongThread; char buf[1024]; PRInt32 nBytes; int idx; status = PR_CreatePipe(&ping_in, &pong_out); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } status = PR_CreatePipe(&pong_in, &ping_out); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } pongThread = PR_CreateThread(PR_USER_THREAD, PongThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (pongThread == NULL) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { strcpy(buf, "ping"); printf("ping thread: sending \"%s\"\n", buf); nBytes = PR_Write(ping_out, buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } memset(buf, 0, sizeof(buf)); nBytes = PR_Read(ping_in, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed\n"); exit(1); } printf("ping thread: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "ping thread: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "pong") != 0) { fprintf(stderr, "ping thread: expected \"pong\" but got \"%s\"\n", buf); exit(1); } } status = PR_Close(ping_in); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(ping_out); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_JoinThread(pongThread); if (status == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } #if defined(XP_UNIX) && !defined(SYMBIAN) /* * Test PR_Available for pipes */ status = PR_CreatePipe(&ping_in, &ping_out); if (status == PR_FAILURE) { fprintf(stderr, "PR_CreatePipe failed\n"); exit(1); } nBytes = PR_Write(ping_out, buf, 250); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } nBytes = PR_Available(ping_in); if (nBytes < 0) { fprintf(stderr, "PR_Available failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } else if (nBytes != 250) { fprintf(stderr, "PR_Available: expected 250 bytes but got %d bytes\n", nBytes); exit(1); } printf("PR_Available: expected %d, got %d bytes\n",250, nBytes); /* read some data */ nBytes = PR_Read(ping_in, buf, 7); if (nBytes == -1) { fprintf(stderr, "PR_Read failed\n"); exit(1); } /* check available data */ nBytes = PR_Available(ping_in); if (nBytes < 0) { fprintf(stderr, "PR_Available failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } else if (nBytes != (250 - 7)) { fprintf(stderr, "PR_Available: expected 243 bytes but got %d bytes\n", nBytes); exit(1); } printf("PR_Available: expected %d, got %d bytes\n",243, nBytes); /* read all data */ nBytes = PR_Read(ping_in, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed\n"); exit(1); } else if (nBytes != 243) { fprintf(stderr, "PR_Read failed: expected %d, got %d bytes\n", 243, nBytes); exit(1); } /* check available data */ nBytes = PR_Available(ping_in); if (nBytes < 0) { fprintf(stderr, "PR_Available failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } else if (nBytes != 0) { fprintf(stderr, "PR_Available: expected 0 bytes but got %d bytes\n", nBytes); exit(1); } printf("PR_Available: expected %d, got %d bytes\n", 0, nBytes); status = PR_Close(ping_in); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_Close(ping_out); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } #endif /* XP_UNIX */ printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/poll_er.c0000755000000000000000000001365012623070344015125 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: prpoll_err.c ** ** Description: This program tests PR_Poll with sockets. ** error reporting operation is tested ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ #ifdef XP_BEOS #include int main() { printf( "This test is not ported to the BeOS\n" ); return 0; } #else /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "primpl.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; static void ClientThreadFunc(void *arg) { PRFileDesc *badFD = (PRFileDesc *) arg; /* * Make the fd invalid */ #if defined(XP_UNIX) close(PR_FileDesc2NativeHandle(badFD)); #elif defined(XP_OS2) soclose(PR_FileDesc2NativeHandle(badFD)); #elif defined(WIN32) || defined(WIN16) closesocket(PR_FileDesc2NativeHandle(badFD)); #else #error "Unknown architecture" #endif } int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("error reporting is tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; npds = 2; /* Testing bad fd */ if (debug_mode) printf("PR_Poll should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); goto exit_now; } pds[2].fd = badFD; pds[2].in_flags = PR_POLL_READ; npds = 3; if (PR_CreateThread(PR_USER_THREAD, ClientThreadFunc, badFD, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0) == NULL) { fprintf(stderr, "cannot create thread\n"); exit(1); } retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Poll returns %d, out_flags is 0x%hx\n", retVal, pds[2].out_flags); failed_already=1; goto exit_now; } if (debug_mode) printf("PR_Poll detected the bad fd. Test passed.\n\n"); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; } #endif /* XP_BEOS */ nspr-4.11/nspr/pr/tests/poll_nm.c0000644000000000000000000002344112623070344015125 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: prpoll_norm.c ** ** Description: This program tests PR_Poll with sockets. ** Normal operation are tested ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prio.h" #include "prlog.h" #include "prprf.h" #include "prnetdb.h" #include "obsolete/probslet.h" #include "private/pprio.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; #define NUM_ITERATIONS 5 static void PR_CALLBACK clientThreadFunc(void *arg) { PRUintn port = (PRUintn) arg; PRFileDesc *sock; PRNetAddr addr; char buf[128]; int i; PRStatus sts; PRInt32 n; addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons((PRUint16)port); addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); memset(buf, 0, sizeof(buf)); PR_snprintf(buf, sizeof(buf), "%hu", port); for (i = 0; i < NUM_ITERATIONS; i++) { sock = PR_NewTCPSocket(); PR_ASSERT(sock != NULL); sts = PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(sts == PR_SUCCESS); n = PR_Write(sock, buf, sizeof(buf)); PR_ASSERT(n >= 0); sts = PR_Close(sock); PR_ASSERT(sts == PR_SUCCESS); } } int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRThread *clientThread; PRPollDesc pds0[20], pds1[20], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRIntn i, j; PRSocketOptionData optval; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); optval.option = PR_SockOpt_Nonblocking; optval.value.non_blocking = PR_TRUE; PR_SetSocketOption(listenSock1, &optval); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); PR_SetSocketOption(listenSock2, &optval); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; /* Add some unused entries to test if they are ignored by PR_Poll() */ memset(&pds[2], 0, sizeof(pds[2])); memset(&pds[3], 0, sizeof(pds[3])); memset(&pds[4], 0, sizeof(pds[4])); npds = 5; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } if (debug_mode) { printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); } /* two clients, three events per iteration: accept, read, close */ i = 0; while (i < 2 * 3 * NUM_ITERATIONS) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); failed_already=1; goto exit_now; } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); failed_already=1; goto exit_now; } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); failed_already=1; goto exit_now; } } for (j = 2; j < npds; j++) { if (NULL == pds[j].fd) { /* * Keep the unused entries in the poll descriptor array * for testing purposes. */ other_pds[nextIndex] = pds[j]; nextIndex++; continue; } PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nAvail; PRInt32 nRead; nEvents++; nAvail = PR_Available(pds[j].fd); nRead = PR_Read(pds[j].fd, buf, sizeof(buf)); PR_ASSERT(nAvail == nRead); if (nRead == -1) { fprintf(stderr, "PR_Read() failed\n"); failed_already=1; goto exit_now; } else if (nRead == 0) { PR_Close(pds[j].fd); continue; } else { /* Just to be safe */ buf[127] = '\0'; if (debug_mode) printf("The server received \"%s\" from a client\n", buf); } } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); failed_already=1; goto exit_now; } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); failed_already=1; goto exit_now; } other_pds[nextIndex] = pds[j]; nextIndex++; } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } if (debug_mode) printf("Tests passed\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/poll_to.c0000644000000000000000000001245612623070344015141 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: prpoll_to.c ** ** Description: This program tests PR_Poll with sockets. ** Timeout operation is tested ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prio.h" #include "prlog.h" #include "prprf.h" #include "prnetdb.h" #include "private/pprio.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; int main(int argc, char **argv) { PRFileDesc *listenSock1 = NULL, *listenSock2 = NULL; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[128]; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Poll with sockets.\n"); printf("Timeout is tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); pds[0].fd = listenSock1; pds[0].in_flags = PR_POLL_READ; pds[1].fd = listenSock2; pds[1].in_flags = PR_POLL_READ; npds = 2; /* Testing timeout */ if (debug_mode) printf("PR_Poll should time out in 5 seconds\n"); retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Poll should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); if (!debug_mode) failed_already=1; goto exit_now; } if (debug_mode) printf("PR_Poll timed out. Test passed.\n\n"); exit_now: if (listenSock1) { PR_Close(listenSock1); } if (listenSock2) { PR_Close(listenSock2); } PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/pollable.c0000644000000000000000000001747612623070344015272 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A test for the pollable events. * * A number of threads are in a ring configuration, each waiting on * a pollable event that is set by its upstream neighbor. */ #include "prinit.h" #include "prio.h" #include "prthread.h" #include "prerror.h" #include "prmem.h" #include "prlog.h" #include "prprf.h" #include "plgetopt.h" #include #define DEFAULT_THREADS 10 #define DEFAULT_LOOPS 100 PRIntn numThreads = DEFAULT_THREADS; PRIntn numIterations = DEFAULT_LOOPS; PRIntervalTime dally = PR_INTERVAL_NO_WAIT; PRFileDesc *debug_out = NULL; PRBool debug_mode = PR_FALSE; PRBool verbosity = PR_FALSE; typedef struct ThreadData { PRFileDesc *event; int index; struct ThreadData *next; } ThreadData; void ThreadRoutine(void *arg) { ThreadData *data = (ThreadData *) arg; PRIntn i; PRPollDesc pd; PRInt32 rv; pd.fd = data->event; pd.in_flags = PR_POLL_READ; for (i = 0; i < numIterations; i++) { rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (rv == -1) { PR_fprintf(PR_STDERR, "PR_Poll failed\n"); exit(1); } if (verbosity) { PR_fprintf(debug_out, "thread %d awakened\n", data->index); } PR_ASSERT(rv != 0); PR_ASSERT(pd.out_flags & PR_POLL_READ); if (PR_WaitForPollableEvent(data->event) == PR_FAILURE) { PR_fprintf(PR_STDERR, "consume event failed\n"); exit(1); } if (dally != PR_INTERVAL_NO_WAIT) { PR_Sleep(dally); } if (verbosity) { PR_fprintf(debug_out, "thread %d posting event\n", data->index); } if (PR_SetPollableEvent(data->next->event) == PR_FAILURE) { PR_fprintf(PR_STDERR, "post event failed\n"); exit(1); } } } static void Help(void) { debug_out = PR_STDOUT; PR_fprintf( debug_out, "Usage: pollable [-c n] [-t n] [-d] [-v] [-G] [-C n] [-D n]\n"); PR_fprintf( debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS); PR_fprintf( debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS); PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n"); PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n"); PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n"); PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n"); PR_fprintf(debug_out, "-D n\tdally setting (msecs) (default: 0)\n"); } /* Help */ int main(int argc, char **argv) { ThreadData selfData; ThreadData *data; PRThread **thread; void *block; PRIntn i; PRIntervalTime timeStart, timeEnd; PRPollDesc pd; PRInt32 rv; PRThreadScope thread_scope = PR_LOCAL_THREAD; PRBool help = PR_FALSE; PRUintn concurrency = 1; PRUintn average; PLOptStatus os; PLOptState *opt; PR_STDIO_INIT(); opt = PL_CreateOptState(argc, argv, "hdvc:t:C:GD:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) { continue; } switch (opt->option) { case 'v': /* verbose mode */ verbosity = PR_TRUE; case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop counter */ numIterations = atoi(opt->value); break; case 't': /* thread limit */ numThreads = atoi(opt->value); break; case 'C': /* Concurrency limit */ concurrency = atoi(opt->value); break; case 'G': /* global threads only */ thread_scope = PR_GLOBAL_THREAD; break; case 'D': /* dally */ dally = PR_MillisecondsToInterval(atoi(opt->value)); break; case 'h': /* help message */ Help(); help = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); if (help) { return 1; } if (concurrency > 1) { PR_SetConcurrency(concurrency); } if (PR_TRUE == debug_mode) { debug_out = PR_STDOUT; PR_fprintf(debug_out, "Test parameters\n"); PR_fprintf(debug_out, "\tThreads involved: %d\n", numThreads); PR_fprintf(debug_out, "\tIteration limit: %d\n", numIterations); PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency); PR_fprintf(debug_out, "\tThread type: %s\n", (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL"); } /* * Malloc a block of memory and divide it into data and thread. */ block = PR_MALLOC(numThreads * (sizeof(ThreadData) + sizeof(PRThread *))); if (block == NULL) { PR_fprintf(PR_STDERR, "cannot malloc, failed\n"); exit(1); } data = (ThreadData *) block; thread = (PRThread **) &data[numThreads]; /* Pollable event */ selfData.event = PR_NewPollableEvent(); if (selfData.event == NULL) { PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); exit(1); } selfData.next = &data[0]; for (i = 0; i < numThreads; i++) { data[i].event = PR_NewPollableEvent(); if (data[i].event == NULL) { PR_fprintf(PR_STDERR, "cannot create event: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); exit(1); } data[i].index = i; if (i != numThreads - 1) { data[i].next = &data[i + 1]; } else { data[i].next = &selfData; } thread[i] = PR_CreateThread(PR_USER_THREAD, ThreadRoutine, &data[i], PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); if (thread[i] == NULL) { PR_fprintf(PR_STDERR, "cannot create thread\n"); exit(1); } } timeStart = PR_IntervalNow(); pd.fd = selfData.event; pd.in_flags = PR_POLL_READ; for (i = 0; i < numIterations; i++) { if (dally != PR_INTERVAL_NO_WAIT) { PR_Sleep(dally); } if (verbosity) { PR_fprintf(debug_out, "main thread posting event\n"); } if (PR_SetPollableEvent(selfData.next->event) == PR_FAILURE) { PR_fprintf(PR_STDERR, "set event failed\n"); exit(1); } rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT); if (rv == -1) { PR_fprintf(PR_STDERR, "wait failed\n"); exit(1); } PR_ASSERT(rv != 0); PR_ASSERT(pd.out_flags & PR_POLL_READ); if (verbosity) { PR_fprintf(debug_out, "main thread awakened\n"); } if (PR_WaitForPollableEvent(selfData.event) == PR_FAILURE) { PR_fprintf(PR_STDERR, "consume event failed\n"); exit(1); } } timeEnd = PR_IntervalNow(); if (debug_mode) { average = PR_IntervalToMicroseconds(timeEnd - timeStart) / (numIterations * numThreads); PR_fprintf(debug_out, "Average switch times %d usecs for %d threads\n", average, numThreads); } for (i = 0; i < numThreads; i++) { if (PR_JoinThread(thread[i]) == PR_FAILURE) { PR_fprintf(PR_STDERR, "join thread failed\n"); exit(1); } PR_DestroyPollableEvent(data[i].event); } PR_DELETE(block); PR_DestroyPollableEvent(selfData.event); PR_fprintf(PR_STDOUT, "PASSED\n"); return 0; } nspr-4.11/nspr/pr/tests/prfdbl.c0000644000000000000000000000160012623070344014727 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This is a simple test of the PR_fprintf() function for doubles. */ #include "prprf.h" int main() { double pi = 3.1415926; double e = 2.71828; double root2 = 1.414; double zero = 0.0; double nan = zero / zero; PR_fprintf(PR_STDOUT, "pi is %f.\n", pi); PR_fprintf(PR_STDOUT, "e is %f.\n", e); PR_fprintf(PR_STDOUT, "The square root of 2 is %f.\n", root2); PR_fprintf(PR_STDOUT, "NaN is %f.\n", nan); PR_fprintf(PR_STDOUT, "pi is %301f.\n", pi); PR_fprintf(PR_STDOUT, "e is %65416.123f.\n", e); PR_fprintf(PR_STDOUT, "e is %0000000000000000000065416.123f.\n", e); PR_fprintf(PR_STDOUT, "NaN is %1024.1f.\n", nan); return 0; } nspr-4.11/nspr/pr/tests/prftest.c0000644000000000000000000000303112623070344015145 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: prftest.c * Description: * This is a simple test of the PR_snprintf() function defined * in prprf.c. */ #include "prlong.h" #include "prprf.h" #include #define BUF_SIZE 128 int main(int argc, char **argv) { PRInt16 i16; PRIntn n; PRInt32 i32; PRInt64 i64; char buf[BUF_SIZE]; char answer[BUF_SIZE]; int i, rv = 0; i16 = -1; n = -1; i32 = -1; LL_I2L(i64, i32); PR_snprintf(buf, BUF_SIZE, "%hx %x %lx %llx", i16, n, i32, i64); strcpy(answer, "ffff "); for (i = PR_BYTES_PER_INT * 2; i; i--) { strcat(answer, "f"); } strcat(answer, " ffffffff ffffffffffffffff"); if (!strcmp(buf, answer)) { printf("PR_snprintf test 1 passed\n"); } else { printf("PR_snprintf test 1 failed\n"); printf("Converted string is %s\n", buf); printf("Should be %s\n", answer); rv = 1; } i16 = -32; n = 30; i32 = 64; LL_I2L(i64, 333); PR_snprintf(buf, BUF_SIZE, "%d %hd %lld %ld", n, i16, i64, i32); if (!strcmp(buf, "30 -32 333 64")) { printf("PR_snprintf test 2 passed\n"); } else { printf("PR_snprintf test 2 failed\n"); printf("Converted string is %s\n", buf); printf("Should be 30 -32 333 64\n"); rv = 1; } return rv; } nspr-4.11/nspr/pr/tests/prftest1.c0000644000000000000000000000635612623070344015243 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prftest1.c ** Description: ** This is a simple test of the PR_snprintf() function defined ** in prprf.c. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prttools.h" #include "prinit.h" #include "prlong.h" #include "prprf.h" #include #define BUF_SIZE 128 /*********************************************************************** ** PRIVATE FUNCTION: Test_Result ** DESCRIPTION: Used in conjunction with the regress tool, prints out the ** status of the test case. ** INPUTS: PASS/FAIL ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: Determine what the status is and print accordingly. ** ***********************************************************************/ static void Test_Result (int result) { if (result == PASS) printf ("PASS\n"); else printf ("FAIL\n"); } int main(int argc, char **argv) { PRInt16 i16; PRIntn n; PRInt32 i32; PRInt64 i64; char buf[BUF_SIZE]; char answer[BUF_SIZE]; int i; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_STDIO_INIT(); i16 = -1; n = -1; i32 = -1; LL_I2L(i64, i32); PR_snprintf(buf, BUF_SIZE, "%hx %x %lx %llx", i16, n, i32, i64); strcpy(answer, "ffff "); for (i = PR_BYTES_PER_INT * 2; i; i--) { strcat(answer, "f"); } strcat(answer, " ffffffff ffffffffffffffff"); if (!strcmp(buf, answer)) { if (debug_mode) printf("PR_snprintf test 1 passed\n"); else Test_Result (PASS); } else { if (debug_mode) { printf("PR_snprintf test 1 failed\n"); printf("Converted string is %s\n", buf); printf("Should be %s\n", answer); } else Test_Result (FAIL); } return 0; } nspr-4.11/nspr/pr/tests/prftest2.c0000644000000000000000000000527612623070344015244 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: prftest2.c ** Description: ** This is a simple test of the PR_snprintf() function defined ** in prprf.c. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prlong.h" #include "prinit.h" #include "prprf.h" #include #define BUF_SIZE 128 PRIntn failed_already=0; PRIntn debug_mode; int main(int argc, char **argv) { PRInt16 i16; PRIntn n; PRInt32 i32; PRInt64 i64; char buf[BUF_SIZE]; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_STDIO_INIT(); i16 = -32; n = 30; i32 = 64; LL_I2L(i64, 333); PR_snprintf(buf, BUF_SIZE, "%d %hd %lld %ld", n, i16, i64, i32); if (!strcmp(buf, "30 -32 333 64")) { if (debug_mode) printf("PR_snprintf test 2 passed\n"); } else { if (debug_mode) { printf("PR_snprintf test 2 failed\n"); printf("Converted string is %s\n", buf); printf("Should be 30 -32 333 64\n"); } else failed_already=1; } if(failed_already) { printf("FAILED\n"); return 1; } else { printf("PASSED\n"); return 0; } } nspr-4.11/nspr/pr/tests/prfz.c0000644000000000000000000000437712623070344014455 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This is a simple test of the PR_fprintf() function for size_t formats. */ #include "prprf.h" #include #include #include int main(int argc, char **argv) { char buffer[128]; size_t unsigned_small = 266; #ifdef XP_UNIX ssize_t signed_small_p = 943; ssize_t signed_small_n = -1; #endif size_t unsigned_max = SIZE_MAX; size_t unsigned_min = 0; #ifdef XP_UNIX ssize_t signed_max = SSIZE_MAX; #endif printf("Test: unsigned small '%%zu' : "); PR_snprintf(buffer, sizeof(buffer), "%zu", unsigned_small); if (strncmp(buffer, "266", sizeof(buffer)) != 0) { printf("Failed, got '%s'\n", buffer); return -1; } printf("OK\n"); #ifdef XP_UNIX printf("Test: signed small positive '%%zd' : "); PR_snprintf(buffer, sizeof(buffer), "%zd", signed_small_p); if (strncmp(buffer, "943", sizeof(buffer)) != 0) { printf("Failed, got '%s'\n", buffer); return -1; } printf("OK\n"); printf("Test: signed small negative '%%zd' : "); PR_snprintf(buffer, sizeof(buffer), "%zd", signed_small_n); if (strncmp(buffer, "-1", sizeof(buffer)) != 0) { printf("Failed, got '%s'\n", buffer); return -1; } printf("OK\n"); #endif printf("Test: 0 '%%zu' : "); PR_snprintf(buffer, sizeof(buffer), "%zu", unsigned_min); if (strncmp(buffer, "0", sizeof(buffer)) != 0) { printf("Failed, got '%s'\n", buffer); return -1; } printf("OK\n"); printf("Test: SIZE_MAX '%%zx' : "); PR_snprintf(buffer, sizeof(buffer), "%zx", unsigned_max); if (strspn(buffer, "f") != sizeof(size_t) * 2) { printf("Failed, got '%s'\n", buffer); return -1; } printf("OK\n"); #ifdef XP_UNIX printf("Test: SSIZE_MAX '%%zx' : "); PR_snprintf(buffer, sizeof(buffer), "%zx", signed_max); if (*buffer != '7' || strspn(buffer + 1, "f") != sizeof(ssize_t) * 2 - 1) { printf("Failed, got '%s'\n", buffer); return -1; } printf("OK\n"); #endif return 0; } nspr-4.11/nspr/pr/tests/primblok.c0000644000000000000000000000577712623070344015320 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: primblok.c * Purpose: testing whether the primordial thread can block in a * native blocking function without affecting the correct * functioning of NSPR I/O functions (Bugzilla bug #30746) */ #if !defined(WINNT) #include int main(int argc, char **argv) { printf("This test is not relevant on this platform\n"); return 0; } #else /* WINNT */ #include "nspr.h" #include #include #include #include #define TEST_FILE_NAME "primblok.dat" /* use InterlockedExchange to update this variable */ static LONG iothread_done; static void PR_CALLBACK IOThread(void *arg) { PRFileDesc *fd; char buf[32]; PRInt32 nbytes; /* Give the primordial thread one second to block */ Sleep(1000); /* * See if our PR_Write call will hang when the primordial * thread is blocking in a native blocking function. */ fd = PR_Open(TEST_FILE_NAME, PR_WRONLY|PR_CREATE_FILE, 0666); if (NULL == fd) { fprintf(stderr, "PR_Open failed\n"); exit(1); } memset(buf, 0xaf, sizeof(buf)); fprintf(stderr, "iothread: calling PR_Write\n"); nbytes = PR_Write(fd, buf, sizeof(buf)); fprintf(stderr, "iothread: PR_Write returned\n"); if (nbytes != sizeof(buf)) { fprintf(stderr, "PR_Write returned %d\n", nbytes); exit(1); } if (PR_Close(fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Delete(TEST_FILE_NAME) == PR_FAILURE) { fprintf(stderr, "PR_Delete failed\n"); exit(1); } /* Tell the main thread that we are done */ InterlockedExchange(&iothread_done, 1); } int main(int argc, char **argv) { PRThread *iothread; /* Must be a global thread */ iothread = PR_CreateThread( PR_USER_THREAD, IOThread, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (iothread == NULL) { fprintf(stderr, "cannot create thread\n"); exit(1); } /* * Block in a native blocking function. * Give iothread 5 seconds to finish its task. */ Sleep(5000); /* * Is iothread done or is it hung? * * I'm actually only interested in reading the value * of iothread_done. I'm using InterlockedExchange as * a thread-safe way to read iothread_done. */ if (InterlockedExchange(&iothread_done, 1) == 0) { fprintf(stderr, "iothread is hung\n"); fprintf(stderr, "FAILED\n"); exit(1); } if (PR_JoinThread(iothread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } printf("PASSED\n"); return 0; } /* main */ #endif /* WINNT */ nspr-4.11/nspr/pr/tests/priotest.c0000644000000000000000000001254512623070344015341 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: priotest.c * Purpose: testing priorities */ #include "prcmon.h" #include "prinit.h" #include "prinrval.h" #include "prlock.h" #include "prlog.h" #include "prmon.h" #include "prprf.h" #include "prthread.h" #include "prtypes.h" #include "plerror.h" #include "plgetopt.h" #include #include #define DEFAULT_DURATION 5 static PRBool failed = PR_FALSE; static PRIntervalTime oneSecond; static PRFileDesc *debug_out = NULL; static PRBool debug_mode = PR_FALSE; static PRUint32 PerSecond(PRIntervalTime timein) { PRUint32 loop = 0; while (((PRIntervalTime)(PR_IntervalNow()) - timein) < oneSecond) loop += 1; return loop; } /* PerSecond */ static void PR_CALLBACK Low(void *arg) { PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg; while (1) { t0 = PerSecond(PR_IntervalNow()); *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8; t3 = t2; t2 = t1; t1 = t0; } } /* Low */ static void PR_CALLBACK High(void *arg) { PRUint32 t3 = 0, t2 = 0, t1 = 0, t0, *tn = (PRUint32*)arg; while (1) { PRIntervalTime timein = PR_IntervalNow(); PR_Sleep(oneSecond >> 2); /* 0.25 seconds */ t0 = PerSecond(timein); *tn = (t3 + 3 * t2 + 3 * t1 + t0) / 8; t3 = t2; t2 = t1; t1 = t0; } } /* High */ static void Help(void) { PR_fprintf( debug_out, "Usage: priotest [-d] [-c n]\n"); PR_fprintf( debug_out, "-c n\tduration of test in seconds (default: %d)\n", DEFAULT_DURATION); PR_fprintf( debug_out, "-d\tturn on debugging output (default: FALSE)\n"); } /* Help */ static void RudimentaryTests(void) { /* ** Try some rudimentary tests like setting valid priority and ** getting it back, or setting invalid priorities and getting ** back a valid answer. */ PRThreadPriority priority; PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT); priority = PR_GetThreadPriority(PR_GetCurrentThread()); failed = ((PR_TRUE == failed) || (PR_PRIORITY_URGENT != priority)) ? PR_TRUE : PR_FALSE; if (debug_mode && (PR_PRIORITY_URGENT != priority)) { PR_fprintf(debug_out, "PR_[S/G]etThreadPriority() failed\n"); } PR_SetThreadPriority( PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_FIRST - 1)); priority = PR_GetThreadPriority(PR_GetCurrentThread()); failed = ((PR_TRUE == failed) || (PR_PRIORITY_FIRST != priority)) ? PR_TRUE : PR_FALSE; if (debug_mode && (PR_PRIORITY_FIRST != priority)) { PR_fprintf(debug_out, "PR_SetThreadPriority(-1) failed\n"); } PR_SetThreadPriority( PR_GetCurrentThread(), (PRThreadPriority)(PR_PRIORITY_LAST + 1)); priority = PR_GetThreadPriority(PR_GetCurrentThread()); failed = ((PR_TRUE == failed) || (PR_PRIORITY_LAST != priority)) ? PR_TRUE : PR_FALSE; if (debug_mode && (PR_PRIORITY_LAST != priority)) { PR_fprintf(debug_out, "PR_SetThreadPriority(+1) failed\n"); } } /* RudimentataryTests */ static void CreateThreads(PRUint32 *lowCount, PRUint32 *highCount) { (void)PR_CreateThread( PR_USER_THREAD, Low, lowCount, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); (void)PR_CreateThread( PR_USER_THREAD, High, highCount, PR_PRIORITY_HIGH, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); } /* CreateThreads */ int main(int argc, char **argv) { PLOptStatus os; PRIntn duration = DEFAULT_DURATION; PRUint32 totalCount, highCount = 0, lowCount = 0; PLOptState *opt = PL_CreateOptState(argc, argv, "hdc:"); debug_out = PR_STDOUT; oneSecond = PR_SecondsToInterval(1); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* test duration */ duration = atoi(opt->value); break; case 'h': /* help message */ default: Help(); return 2; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); if (duration == 0) duration = DEFAULT_DURATION; RudimentaryTests(); printf("Priority test: running for %d seconds\n\n", duration); (void)PerSecond(PR_IntervalNow()); totalCount = PerSecond(PR_IntervalNow()); PR_SetThreadPriority(PR_GetCurrentThread(), PR_PRIORITY_URGENT); if (debug_mode) { PR_fprintf(debug_out, "The high priority thread should get approximately three\n"); PR_fprintf( debug_out, "times what the low priority thread manages. A maximum of \n"); PR_fprintf( debug_out, "%d cycles are available.\n\n", totalCount); } duration = (duration + 4) / 5; CreateThreads(&lowCount, &highCount); while (duration--) { PRIntn loop = 5; while (loop--) PR_Sleep(oneSecond); if (debug_mode) PR_fprintf(debug_out, "high : low :: %d : %d\n", highCount, lowCount); } PR_ProcessExit((failed) ? 1 : 0); PR_NOT_REACHED("You can't get here -- but you did!"); return 1; /* or here */ } /* main */ /* priotest.c */ nspr-4.11/nspr/pr/tests/provider.c0000644000000000000000000012535312623070344015324 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * * Notes: * [1] lth. The call to Sleep() is a hack to get the test case to run * on Windows 95. Without it, the test case fails with an error * WSAECONNRESET following a recv() call. The error is caused by the * server side thread termination without a shutdown() or closesocket() * call. Windows docmunentation suggests that this is predicted * behavior; that other platforms get away with it is ... serindipity. * The test case should shutdown() or closesocket() before * thread termination. I didn't have time to figure out where or how * to do it. The Sleep() call inserts enough delay to allow the * client side to recv() all his data before the server side thread * terminates. Whew! ... * ** Modification History: * 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. * The debug mode will print all of the printfs associated with this test. * The regress mode will be the default mode. Since the regress tool limits * the output to a one line status:PASS or FAIL,all of the printf statements * have been handled with an if (debug_mode) statement. */ #include "prclist.h" #include "prcvar.h" #include "prerror.h" #include "prinit.h" #include "prinrval.h" #include "prio.h" #include "prlock.h" #include "prlog.h" #include "prtime.h" #include "prmem.h" #include "prnetdb.h" #include "prprf.h" #include "prthread.h" #include "pprio.h" #include "primpl.h" #include "plstr.h" #include "plerror.h" #include "plgetopt.h" #include #include #if defined(XP_UNIX) #include #endif /* ** This is the beginning of the test */ #define RECV_FLAGS 0 #define SEND_FLAGS 0 #define BUFFER_SIZE 1024 #define DEFAULT_BACKLOG 5 #define DEFAULT_PORT 13000 #define DEFAULT_CLIENTS 1 #define ALLOWED_IN_ACCEPT 1 #define DEFAULT_CLIPPING 1000 #define DEFAULT_WORKERS_MIN 1 #define DEFAULT_WORKERS_MAX 1 #define DEFAULT_SERVER "localhost" #define DEFAULT_EXECUTION_TIME 10 #define DEFAULT_CLIENT_TIMEOUT 4000 #define DEFAULT_SERVER_TIMEOUT 4000 #define DEFAULT_SERVER_PRIORITY PR_PRIORITY_HIGH typedef enum CSState_e {cs_init, cs_run, cs_stop, cs_exit} CSState_t; static void PR_CALLBACK Worker(void *arg); typedef struct CSPool_s CSPool_t; typedef struct CSWorker_s CSWorker_t; typedef struct CSServer_s CSServer_t; typedef enum Verbosity { TEST_LOG_ALWAYS, TEST_LOG_ERROR, TEST_LOG_WARNING, TEST_LOG_NOTICE, TEST_LOG_INFO, TEST_LOG_STATUS, TEST_LOG_VERBOSE } Verbosity; static enum { thread_nspr, thread_pthread, thread_sproc, thread_win32 } thread_provider; static PRInt32 domain = AF_INET; static PRInt32 protocol = 6; /* TCP */ static PRFileDesc *debug_out = NULL; static PRBool debug_mode = PR_FALSE; static PRBool pthread_stats = PR_FALSE; static Verbosity verbosity = TEST_LOG_ALWAYS; static PRThreadScope thread_scope = PR_LOCAL_THREAD; struct CSWorker_s { PRCList element; /* list of the server's workers */ PRThread *thread; /* this worker objects thread */ CSServer_t *server; /* back pointer to server structure */ }; struct CSPool_s { PRCondVar *exiting; PRCondVar *acceptComplete; PRUint32 accepting, active, workers; }; struct CSServer_s { PRCList list; /* head of worker list */ PRLock *ml; PRThread *thread; /* the main server thread */ PRCondVar *stateChange; PRUint16 port; /* port we're listening on */ PRUint32 backlog; /* size of our listener backlog */ PRFileDesc *listener; /* the fd accepting connections */ CSPool_t pool; /* statistics on worker threads */ CSState_t state; /* the server's state */ struct /* controlling worker counts */ { PRUint32 minimum, maximum, accepting; } workers; /* statistics */ PRIntervalTime started, stopped; PRUint32 operations, bytesTransferred; }; typedef struct CSDescriptor_s { PRInt32 size; /* size of transfer */ char filename[60]; /* filename, null padded */ } CSDescriptor_t; typedef struct CSClient_s { PRLock *ml; PRThread *thread; PRCondVar *stateChange; PRNetAddr serverAddress; CSState_t state; /* statistics */ PRIntervalTime started, stopped; PRUint32 operations, bytesTransferred; } CSClient_t; #define TEST_LOG(l, p, a) \ do { \ if (debug_mode || (p <= verbosity)) printf a; \ } while (0) PRLogModuleInfo *cltsrv_log_file = NULL; #define MY_ASSERT(_expr) \ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__)) #define TEST_ASSERT(_expr) \ ((_expr)?((void)0):_MY_Assert(# _expr,__FILE__,__LINE__)) static void _MY_Assert(const char *s, const char *file, PRIntn ln) { PL_PrintError(NULL); PR_Assert(s, file, ln); } /* _MY_Assert */ static PRBool Aborted(PRStatus rv) { return ((PR_FAILURE == rv) && (PR_PENDING_INTERRUPT_ERROR == PR_GetError())) ? PR_TRUE : PR_FALSE; } static void TimeOfDayMessage(const char *msg, PRThread* me) { char buffer[100]; PRExplodedTime tod; PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &tod); (void)PR_FormatTime(buffer, sizeof(buffer), "%H:%M:%S", &tod); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("%s(0x%p): %s\n", msg, me, buffer)); } /* TimeOfDayMessage */ static void PR_CALLBACK Client(void *arg) { PRStatus rv; PRIntn index; char buffer[1024]; PRFileDesc *fd = NULL; PRUintn clipping = DEFAULT_CLIPPING; CSClient_t *client = (CSClient_t*)arg; PRThread *me = client->thread = PR_GetCurrentThread(); CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t); PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_CLIENT_TIMEOUT); for (index = 0; index < sizeof(buffer); ++index) buffer[index] = (char)index; client->started = PR_IntervalNow(); PR_Lock(client->ml); client->state = cs_run; PR_NotifyCondVar(client->stateChange); PR_Unlock(client->ml); TimeOfDayMessage("Client started at", me); while (cs_run == client->state) { PRInt32 bytes, descbytes, filebytes, netbytes; (void)PR_NetAddrToString(&client->serverAddress, buffer, sizeof(buffer)); TEST_LOG(cltsrv_log_file, TEST_LOG_INFO, ("\tClient(0x%p): connecting to server at %s\n", me, buffer)); fd = PR_Socket(domain, SOCK_STREAM, protocol); TEST_ASSERT(NULL != fd); rv = PR_Connect(fd, &client->serverAddress, timeout); if (PR_FAILURE == rv) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): conection failed\n", me)); goto aborted; } memset(descriptor, 0, sizeof(*descriptor)); descriptor->size = PR_htonl(descbytes = rand() % clipping); PR_snprintf( descriptor->filename, sizeof(descriptor->filename), "CS%p%p-%p.dat", client->started, me, client->operations); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): sending descriptor for %u bytes\n", me, descbytes)); bytes = PR_Send( fd, descriptor, sizeof(*descriptor), SEND_FLAGS, timeout); if (sizeof(CSDescriptor_t) != bytes) { if (Aborted(PR_FAILURE)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): send descriptor timeout\n", me)); goto retry; } } TEST_ASSERT(sizeof(*descriptor) == bytes); netbytes = 0; while (netbytes < descbytes) { filebytes = sizeof(buffer); if ((descbytes - netbytes) < filebytes) filebytes = descbytes - netbytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): sending %d bytes\n", me, filebytes)); bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout); if (filebytes != bytes) { if (Aborted(PR_FAILURE)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): send data timeout\n", me)); goto retry; } } TEST_ASSERT(bytes == filebytes); netbytes += bytes; } filebytes = 0; while (filebytes < descbytes) { netbytes = sizeof(buffer); if ((descbytes - filebytes) < netbytes) netbytes = descbytes - filebytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tClient(0x%p): receiving %d bytes\n", me, netbytes)); bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout); if (-1 == bytes) { if (Aborted(PR_FAILURE)) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive data aborted\n", me)); goto aborted; } else if (PR_IO_TIMEOUT_ERROR == PR_GetError()) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive data timeout\n", me)); else TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tClient(0x%p): receive error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto retry; } if (0 == bytes) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tClient(0x%p): unexpected end of stream\n", PR_GetCurrentThread())); break; } filebytes += bytes; } rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH); if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); retry: (void)PR_Close(fd); fd = NULL; TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("\tClient(0x%p): disconnected from server\n", me)); PR_Lock(client->ml); client->operations += 1; client->bytesTransferred += 2 * descbytes; rv = PR_WaitCondVar(client->stateChange, rand() % clipping); PR_Unlock(client->ml); if (Aborted(rv)) break; } aborted: client->stopped = PR_IntervalNow(); PR_ClearInterrupt(); if (NULL != fd) rv = PR_Close(fd); PR_Lock(client->ml); client->state = cs_exit; PR_NotifyCondVar(client->stateChange); PR_Unlock(client->ml); PR_DELETE(descriptor); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("\tClient(0x%p): stopped after %u operations and %u bytes\n", PR_GetCurrentThread(), client->operations, client->bytesTransferred)); } /* Client */ static PRStatus ProcessRequest(PRFileDesc *fd, CSServer_t *server) { PRStatus drv, rv; char buffer[1024]; PRFileDesc *file = NULL; PRThread * me = PR_GetCurrentThread(); PRInt32 bytes, descbytes, netbytes, filebytes = 0; CSDescriptor_t *descriptor = PR_NEW(CSDescriptor_t); PRIntervalTime timeout = PR_MillisecondsToInterval(DEFAULT_SERVER_TIMEOUT); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): receiving desciptor\n", me)); bytes = PR_Recv( fd, descriptor, sizeof(*descriptor), RECV_FLAGS, timeout); if (-1 == bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto exit; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): receive timeout\n", me)); } goto exit; } if (0 == bytes) { rv = PR_FAILURE; TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): unexpected end of file\n", me)); goto exit; } descbytes = PR_ntohl(descriptor->size); TEST_ASSERT(sizeof(*descriptor) == bytes); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): read descriptor {%d, %s}\n", me, descbytes, descriptor->filename)); file = PR_Open( descriptor->filename, (PR_CREATE_FILE | PR_WRONLY), 0666); if (NULL == file) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\tProcessRequest(0x%p): open file timeout\n", me)); goto aborted; } } TEST_ASSERT(NULL != file); filebytes = 0; while (filebytes < descbytes) { netbytes = sizeof(buffer); if ((descbytes - filebytes) < netbytes) netbytes = descbytes - filebytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): receive %d bytes\n", me, netbytes)); bytes = PR_Recv(fd, buffer, netbytes, RECV_FLAGS, timeout); if (-1 == bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): receive data timeout\n", me)); goto aborted; } /* * XXX: I got (PR_CONNECT_RESET_ERROR, ERROR_NETNAME_DELETED) * on NT here. This is equivalent to ECONNRESET on Unix. * -wtc */ TEST_LOG( cltsrv_log_file, TEST_LOG_WARNING, ("\t\tProcessRequest(0x%p): unexpected error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } if(0 == bytes) { TEST_LOG( cltsrv_log_file, TEST_LOG_WARNING, ("\t\tProcessRequest(0x%p): unexpected end of stream\n", me)); rv = PR_FAILURE; goto aborted; } filebytes += bytes; netbytes = bytes; /* The byte count for PR_Write should be positive */ MY_ASSERT(netbytes > 0); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): write %d bytes to file\n", me, netbytes)); bytes = PR_Write(file, buffer, netbytes); if (netbytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): write file timeout\n", me)); goto aborted; } } TEST_ASSERT(bytes > 0); } PR_Lock(server->ml); server->operations += 1; server->bytesTransferred += filebytes; PR_Unlock(server->ml); rv = PR_Close(file); file = NULL; if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): opening %s\n", me, descriptor->filename)); file = PR_Open(descriptor->filename, PR_RDONLY, 0); if (NULL == file) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): open file timeout\n", PR_GetCurrentThread())); goto aborted; } TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): other file open error (%u, %u)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } TEST_ASSERT(NULL != file); netbytes = 0; while (netbytes < descbytes) { filebytes = sizeof(buffer); if ((descbytes - netbytes) < filebytes) filebytes = descbytes - netbytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tProcessRequest(0x%p): read %d bytes from file\n", me, filebytes)); bytes = PR_Read(file, buffer, filebytes); if (filebytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): read file timeout\n", me)); else TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): other file error (%d, %d)\n", me, PR_GetError(), PR_GetOSError())); goto aborted; } TEST_ASSERT(bytes > 0); netbytes += bytes; filebytes = bytes; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): sending %d bytes\n", me, filebytes)); bytes = PR_Send(fd, buffer, filebytes, SEND_FLAGS, timeout); if (filebytes != bytes) { rv = PR_FAILURE; if (Aborted(rv)) goto aborted; if (PR_IO_TIMEOUT_ERROR == PR_GetError()) { TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tProcessRequest(0x%p): send data timeout\n", me)); goto aborted; } break; } TEST_ASSERT(bytes > 0); } PR_Lock(server->ml); server->bytesTransferred += filebytes; PR_Unlock(server->ml); rv = PR_Shutdown(fd, PR_SHUTDOWN_BOTH); if (Aborted(rv)) goto aborted; rv = PR_Close(file); file = NULL; if (Aborted(rv)) goto aborted; TEST_ASSERT(PR_SUCCESS == rv); aborted: PR_ClearInterrupt(); if (NULL != file) PR_Close(file); drv = PR_Delete(descriptor->filename); TEST_ASSERT(PR_SUCCESS == drv); exit: TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tProcessRequest(0x%p): Finished\n", me)); PR_DELETE(descriptor); #if defined(WIN95) PR_Sleep(PR_MillisecondsToInterval(200)); /* lth. see note [1] */ #endif return rv; } /* ProcessRequest */ typedef void (*StartFn)(void*); typedef struct StartObject { StartFn start; void *arg; } StartObject; #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include "md/_pth.h" #include static void *pthread_start(void *arg) { StartObject *so = (StartObject*)arg; StartFn start = so->start; void *data = so->arg; PR_Free(so); start(data); return NULL; } /* pthread_start */ #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ #if defined(IRIX) && !defined(_PR_PTHREADS) #include #include static void sproc_start(void *arg, PRSize size) { StartObject *so = (StartObject*)arg; StartFn start = so->start; void *data = so->arg; PR_Free(so); start(data); } /* sproc_start */ #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */ #if defined(WIN32) #include /* for _beginthreadex() */ static PRUintn __stdcall windows_start(void *arg) { StartObject *so = (StartObject*)arg; StartFn start = so->start; void *data = so->arg; PR_Free(so); start(data); return 0; } /* windows_start */ #endif /* defined(WIN32) */ static PRStatus JoinThread(PRThread *thread) { PRStatus rv; switch (thread_provider) { case thread_nspr: rv = PR_JoinThread(thread); break; case thread_pthread: #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) rv = PR_SUCCESS; break; #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ case thread_win32: #if defined(WIN32) rv = PR_SUCCESS; break; #endif default: rv = PR_FAILURE; break; } return rv; } /* JoinThread */ static PRStatus NewThread( StartFn start, void *arg, PRThreadPriority prio, PRThreadState state) { PRStatus rv; switch (thread_provider) { case thread_nspr: { PRThread *thread = PR_CreateThread( PR_USER_THREAD, start, arg, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); rv = (NULL == thread) ? PR_FAILURE : PR_SUCCESS; } break; case thread_pthread: #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) { int rv; pthread_t id; pthread_attr_t tattr; StartObject *start_object; start_object = PR_NEW(StartObject); PR_ASSERT(NULL != start_object); start_object->start = start; start_object->arg = arg; rv = _PT_PTHREAD_ATTR_INIT(&tattr); PR_ASSERT(0 == rv); rv = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); PR_ASSERT(0 == rv); rv = pthread_attr_setstacksize(&tattr, 64 * 1024); PR_ASSERT(0 == rv); rv = _PT_PTHREAD_CREATE(&id, tattr, pthread_start, start_object); (void)_PT_PTHREAD_ATTR_DESTROY(&tattr); return (0 == rv) ? PR_SUCCESS : PR_FAILURE; } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; #endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */ break; case thread_sproc: #if defined(IRIX) && !defined(_PR_PTHREADS) { PRInt32 pid; StartObject *start_object; start_object = PR_NEW(StartObject); PR_ASSERT(NULL != start_object); start_object->start = start; start_object->arg = arg; pid = sprocsp( sproc_start, PR_SALL, start_object, NULL, 64 * 1024); rv = (0 < pid) ? PR_SUCCESS : PR_FAILURE; } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; #endif /* defined(IRIX) && !defined(_PR_PTHREADS) */ break; case thread_win32: #if defined(WIN32) { void *th; PRUintn id; StartObject *start_object; start_object = PR_NEW(StartObject); PR_ASSERT(NULL != start_object); start_object->start = start; start_object->arg = arg; th = (void*)_beginthreadex( NULL, /* LPSECURITY_ATTRIBUTES - pointer to thread security attributes */ 0U, /* DWORD - initial thread stack size, in bytes */ windows_start, /* LPTHREAD_START_ROUTINE - pointer to thread function */ start_object, /* LPVOID - argument for new thread */ STACK_SIZE_PARAM_IS_A_RESERVATION, /*DWORD dwCreationFlags - creation flags */ &id /* LPDWORD - pointer to returned thread identifier */ ); rv = (NULL == th) ? PR_FAILURE : PR_SUCCESS; } #else PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; #endif break; default: PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); rv = PR_FAILURE; } return rv; } /* NewThread */ static PRStatus CreateWorker(CSServer_t *server, CSPool_t *pool) { PRStatus rv; CSWorker_t *worker = PR_NEWZAP(CSWorker_t); worker->server = server; PR_INIT_CLIST(&worker->element); rv = NewThread( Worker, worker, DEFAULT_SERVER_PRIORITY, PR_UNJOINABLE_THREAD); if (PR_FAILURE == rv) PR_DELETE(worker); TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS, ("\tCreateWorker(0x%p): create new worker (0x%p)\n", PR_GetCurrentThread(), worker->thread)); return rv; } /* CreateWorker */ static void PR_CALLBACK Worker(void *arg) { PRStatus rv; PRNetAddr from; PRFileDesc *fd = NULL; CSWorker_t *worker = (CSWorker_t*)arg; CSServer_t *server = worker->server; CSPool_t *pool = &server->pool; PRThread *me = worker->thread = PR_GetCurrentThread(); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): started [%u]\n", me, pool->workers + 1)); PR_Lock(server->ml); PR_APPEND_LINK(&worker->element, &server->list); pool->workers += 1; /* define our existance */ while (cs_run == server->state) { while (pool->accepting >= server->workers.accepting) { TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): waiting for accept slot[%d]\n", me, pool->accepting)); rv = PR_WaitCondVar(pool->acceptComplete, PR_INTERVAL_NO_TIMEOUT); if (Aborted(rv) || (cs_run != server->state)) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tWorker(0x%p): has been %s\n", me, (Aborted(rv) ? "interrupted" : "stopped"))); goto exit; } } pool->accepting += 1; /* how many are really in accept */ PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\t\tWorker(0x%p): calling accept\n", me)); fd = PR_Accept(server->listener, &from, PR_INTERVAL_NO_TIMEOUT); PR_Lock(server->ml); pool->accepting -= 1; PR_NotifyCondVar(pool->acceptComplete); if ((NULL == fd) && Aborted(PR_FAILURE)) { if (NULL != server->listener) { PR_Close(server->listener); server->listener = NULL; } goto exit; } if (NULL != fd) { /* ** Create another worker of the total number of workers is ** less than the minimum specified or we have none left in ** accept() AND we're not over the maximum. ** This sort of presumes that the number allowed in accept ** is at least as many as the minimum. Otherwise we'll keep ** creating new threads and deleting them soon after. */ PRBool another = ((pool->workers < server->workers.minimum) || ((0 == pool->accepting) && (pool->workers < server->workers.maximum))) ? PR_TRUE : PR_FALSE; pool->active += 1; PR_Unlock(server->ml); if (another) (void)CreateWorker(server, pool); rv = ProcessRequest(fd, server); if (PR_SUCCESS != rv) TEST_LOG( cltsrv_log_file, TEST_LOG_ERROR, ("\t\tWorker(0x%p): server process ended abnormally\n", me)); (void)PR_Close(fd); fd = NULL; PR_Lock(server->ml); pool->active -= 1; } } exit: PR_ClearInterrupt(); PR_Unlock(server->ml); if (NULL != fd) { (void)PR_Shutdown(fd, PR_SHUTDOWN_BOTH); (void)PR_Close(fd); } TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\t\tWorker(0x%p): exiting [%u]\n", PR_GetCurrentThread(), pool->workers)); PR_Lock(server->ml); pool->workers -= 1; /* undefine our existance */ PR_REMOVE_AND_INIT_LINK(&worker->element); PR_NotifyCondVar(pool->exiting); PR_Unlock(server->ml); PR_DELETE(worker); /* destruction of the "worker" object */ } /* Worker */ static void PR_CALLBACK Server(void *arg) { PRStatus rv; PRNetAddr serverAddress; CSServer_t *server = (CSServer_t*)arg; PRThread *me = server->thread = PR_GetCurrentThread(); PRSocketOptionData sockOpt; server->listener = PR_Socket(domain, SOCK_STREAM, protocol); sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(server->listener, &sockOpt); TEST_ASSERT(PR_SUCCESS == rv); memset(&serverAddress, 0, sizeof(serverAddress)); rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress); rv = PR_Bind(server->listener, &serverAddress); TEST_ASSERT(PR_SUCCESS == rv); rv = PR_Listen(server->listener, server->backlog); TEST_ASSERT(PR_SUCCESS == rv); server->started = PR_IntervalNow(); TimeOfDayMessage("Server started at", me); PR_Lock(server->ml); server->state = cs_run; PR_NotifyCondVar(server->stateChange); PR_Unlock(server->ml); /* ** Create the first worker (actually, a thread that accepts ** connections and then processes the work load as needed). ** From this point on, additional worker threads are created ** as they are needed by existing worker threads. */ rv = CreateWorker(server, &server->pool); TEST_ASSERT(PR_SUCCESS == rv); /* ** From here on this thread is merely hanging around as the contact ** point for the main test driver. It's just waiting for the driver ** to declare the test complete. */ TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tServer(0x%p): waiting for state change\n", me)); PR_Lock(server->ml); while ((cs_run == server->state) && !Aborted(rv)) { rv = PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(server->ml); PR_ClearInterrupt(); TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("\tServer(0x%p): shutting down workers\n", me)); /* ** Get all the worker threads to exit. They know how to ** clean up after themselves, so this is just a matter of ** waiting for clorine in the pool to take effect. During ** this stage we're ignoring interrupts. */ server->workers.minimum = server->workers.maximum = 0; PR_Lock(server->ml); while (!PR_CLIST_IS_EMPTY(&server->list)) { PRCList *head = PR_LIST_HEAD(&server->list); CSWorker_t *worker = (CSWorker_t*)head; TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("\tServer(0x%p): interrupting worker(0x%p)\n", me, worker)); rv = PR_Interrupt(worker->thread); TEST_ASSERT(PR_SUCCESS == rv); PR_REMOVE_AND_INIT_LINK(head); } while (server->pool.workers > 0) { TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("\tServer(0x%p): waiting for %u workers to exit\n", me, server->pool.workers)); (void)PR_WaitCondVar(server->pool.exiting, PR_INTERVAL_NO_TIMEOUT); } server->state = cs_exit; PR_NotifyCondVar(server->stateChange); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("\tServer(0x%p): stopped after %u operations and %u bytes\n", me, server->operations, server->bytesTransferred)); if (NULL != server->listener) PR_Close(server->listener); server->stopped = PR_IntervalNow(); } /* Server */ static void WaitForCompletion(PRIntn execution) { while (execution > 0) { PRIntn dally = (execution > 30) ? 30 : execution; PR_Sleep(PR_SecondsToInterval(dally)); if (pthread_stats) PT_FPrintStats(debug_out, "\nPThread Statistics\n"); execution -= dally; } } /* WaitForCompletion */ static void Help(void) { PR_fprintf(debug_out, "cltsrv test program usage:\n"); PR_fprintf(debug_out, "\t-a threads allowed in accept (5)\n"); PR_fprintf(debug_out, "\t-b backlock for listen (5)\n"); PR_fprintf(debug_out, "\t-c number of clients to create (1)\n"); PR_fprintf(debug_out, "\t-w minimal number of server threads (1)\n"); PR_fprintf(debug_out, "\t-W maximum number of server threads (1)\n"); PR_fprintf(debug_out, "\t-e duration of the test in seconds (10)\n"); PR_fprintf(debug_out, "\t-s dsn name of server (localhost)\n"); PR_fprintf(debug_out, "\t-G use GLOBAL threads (LOCAL)\n"); PR_fprintf(debug_out, "\t-T thread provider ('n' | 'p' | 'w')(n)\n"); PR_fprintf(debug_out, "\t-X use XTP as transport (TCP)\n"); PR_fprintf(debug_out, "\t-6 Use IPv6 (IPv4)\n"); PR_fprintf(debug_out, "\t-v verbosity (accumulative) (0)\n"); PR_fprintf(debug_out, "\t-p pthread statistics (FALSE)\n"); PR_fprintf(debug_out, "\t-d debug mode (FALSE)\n"); PR_fprintf(debug_out, "\t-h this message\n"); } /* Help */ static Verbosity IncrementVerbosity(void) { PRIntn verboge = (PRIntn)verbosity + 1; return (Verbosity)verboge; } /* IncrementVerbosity */ int main(int argc, char **argv) { PRUintn index; PRBool boolean; CSClient_t *client; PRStatus rv, joinStatus; CSServer_t *server = NULL; char *thread_type; PRUintn backlog = DEFAULT_BACKLOG; PRUintn clients = DEFAULT_CLIENTS; const char *serverName = DEFAULT_SERVER; PRBool serverIsLocal = PR_TRUE; PRUintn accepting = ALLOWED_IN_ACCEPT; PRUintn workersMin = DEFAULT_WORKERS_MIN; PRUintn workersMax = DEFAULT_WORKERS_MAX; PRIntn execution = DEFAULT_EXECUTION_TIME; /* * -G use global threads * -a threads allowed in accept * -b backlock for listen * -c number of clients to create * -w minimal number of server threads * -W maximum number of server threads * -e duration of the test in seconds * -s dsn name of server (implies no server here) * -v verbosity */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "GX6b:a:c:w:W:e:s:T:vdhp"); #if defined(WIN32) thread_provider = thread_win32; #elif defined(_PR_PTHREADS) thread_provider = thread_pthread; #elif defined(IRIX) thread_provider = thread_sproc; #else thread_provider = thread_nspr; #endif debug_out = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'X': /* use XTP as transport */ protocol = 36; break; case '6': /* Use IPv6 */ domain = PR_AF_INET6; break; case 'a': /* the value for accepting */ accepting = atoi(opt->value); break; case 'b': /* the value for backlock */ backlog = atoi(opt->value); break; case 'T': /* the thread provider */ if ('n' == *opt->value) thread_provider = thread_nspr; else if ('p' == *opt->value) thread_provider = thread_pthread; else if ('w' == *opt->value) thread_provider = thread_win32; else {Help(); return 2; } break; case 'c': /* number of client threads */ clients = atoi(opt->value); break; case 'w': /* minimum server worker threads */ workersMin = atoi(opt->value); break; case 'W': /* maximum server worker threads */ workersMax = atoi(opt->value); break; case 'e': /* program execution time in seconds */ execution = atoi(opt->value); break; case 's': /* server's address */ serverName = opt->value; break; case 'v': /* verbosity */ verbosity = IncrementVerbosity(); break; case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'p': /* pthread mode */ pthread_stats = PR_TRUE; break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); if (0 != PL_strcmp(serverName, DEFAULT_SERVER)) serverIsLocal = PR_FALSE; if (0 == execution) execution = DEFAULT_EXECUTION_TIME; if (0 == workersMax) workersMax = DEFAULT_WORKERS_MAX; if (0 == workersMin) workersMin = DEFAULT_WORKERS_MIN; if (0 == accepting) accepting = ALLOWED_IN_ACCEPT; if (0 == backlog) backlog = DEFAULT_BACKLOG; if (workersMin > accepting) accepting = workersMin; PR_STDIO_INIT(); TimeOfDayMessage("Client/Server started at", PR_GetCurrentThread()); cltsrv_log_file = PR_NewLogModule("cltsrv_log"); MY_ASSERT(NULL != cltsrv_log_file); boolean = PR_SetLogFile("cltsrv.log"); MY_ASSERT(boolean); if (serverIsLocal) { /* Establish the server */ TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("main(0x%p): starting server\n", PR_GetCurrentThread())); server = PR_NEWZAP(CSServer_t); PR_INIT_CLIST(&server->list); server->state = cs_init; server->ml = PR_NewLock(); server->backlog = backlog; server->port = DEFAULT_PORT; server->workers.minimum = workersMin; server->workers.maximum = workersMax; server->workers.accepting = accepting; server->stateChange = PR_NewCondVar(server->ml); server->pool.exiting = PR_NewCondVar(server->ml); server->pool.acceptComplete = PR_NewCondVar(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): creating server thread\n", PR_GetCurrentThread())); rv = NewThread( Server, server, PR_PRIORITY_HIGH, PR_JOINABLE_THREAD); TEST_ASSERT(PR_SUCCESS == rv); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): waiting for server init\n", PR_GetCurrentThread())); PR_Lock(server->ml); while (server->state == cs_init) PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): server init complete (port #%d)\n", PR_GetCurrentThread(), server->port)); } if (clients != 0) { /* Create all of the clients */ PRHostEnt host; char buffer[BUFFER_SIZE]; client = (CSClient_t*)PR_CALLOC(clients * sizeof(CSClient_t)); TEST_LOG( cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): creating %d client threads\n", PR_GetCurrentThread(), clients)); if (!serverIsLocal) { rv = PR_GetHostByName(serverName, buffer, BUFFER_SIZE, &host); if (PR_SUCCESS != rv) { PL_FPrintError(PR_STDERR, "PR_GetHostByName"); return 2; } } for (index = 0; index < clients; ++index) { client[index].state = cs_init; client[index].ml = PR_NewLock(); if (serverIsLocal) { (void)PR_InitializeNetAddr( PR_IpAddrLoopback, DEFAULT_PORT, &client[index].serverAddress); } else { (void)PR_EnumerateHostEnt( 0, &host, DEFAULT_PORT, &client[index].serverAddress); } client[index].stateChange = PR_NewCondVar(client[index].ml); TEST_LOG( cltsrv_log_file, TEST_LOG_INFO, ("main(0x%p): creating client threads\n", PR_GetCurrentThread())); rv = NewThread( Client, &client[index], PR_PRIORITY_NORMAL, PR_JOINABLE_THREAD); TEST_ASSERT(PR_SUCCESS == rv); PR_Lock(client[index].ml); while (cs_init == client[index].state) PR_WaitCondVar(client[index].stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(client[index].ml); } } /* Then just let them go at it for a bit */ TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("main(0x%p): waiting for execution interval (%d seconds)\n", PR_GetCurrentThread(), execution)); WaitForCompletion(execution); TimeOfDayMessage("Shutting down", PR_GetCurrentThread()); if (clients != 0) { for (index = 0; index < clients; ++index) { TEST_LOG(cltsrv_log_file, TEST_LOG_STATUS, ("main(0x%p): notifying client(0x%p) to stop\n", PR_GetCurrentThread(), client[index].thread)); PR_Lock(client[index].ml); if (cs_run == client[index].state) { client[index].state = cs_stop; PR_Interrupt(client[index].thread); while (cs_stop == client[index].state) PR_WaitCondVar( client[index].stateChange, PR_INTERVAL_NO_TIMEOUT); } PR_Unlock(client[index].ml); TEST_LOG(cltsrv_log_file, TEST_LOG_VERBOSE, ("main(0x%p): joining client(0x%p)\n", PR_GetCurrentThread(), client[index].thread)); joinStatus = JoinThread(client[index].thread); TEST_ASSERT(PR_SUCCESS == joinStatus); PR_DestroyCondVar(client[index].stateChange); PR_DestroyLock(client[index].ml); } PR_DELETE(client); } if (NULL != server) { /* All clients joined - retrieve the server */ TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): notifying server(0x%p) to stop\n", PR_GetCurrentThread(), server->thread)); PR_Lock(server->ml); server->state = cs_stop; PR_Interrupt(server->thread); while (cs_exit != server->state) PR_WaitCondVar(server->stateChange, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(server->ml); TEST_LOG( cltsrv_log_file, TEST_LOG_NOTICE, ("main(0x%p): joining server(0x%p)\n", PR_GetCurrentThread(), server->thread)); joinStatus = JoinThread(server->thread); TEST_ASSERT(PR_SUCCESS == joinStatus); PR_DestroyCondVar(server->stateChange); PR_DestroyCondVar(server->pool.exiting); PR_DestroyCondVar(server->pool.acceptComplete); PR_DestroyLock(server->ml); PR_DELETE(server); } TEST_LOG( cltsrv_log_file, TEST_LOG_ALWAYS, ("main(0x%p): test complete\n", PR_GetCurrentThread())); if (thread_provider == thread_win32) thread_type = "\nWin32 Thread Statistics\n"; else if (thread_provider == thread_pthread) thread_type = "\npthread Statistics\n"; else if (thread_provider == thread_sproc) thread_type = "\nsproc Statistics\n"; else { PR_ASSERT(thread_provider == thread_nspr); thread_type = "\nPRThread Statistics\nn"; } PT_FPrintStats(debug_out, thread_type); TimeOfDayMessage("Test exiting at", PR_GetCurrentThread()); PR_Cleanup(); return 0; } /* main */ /* cltsrv.c */ nspr-4.11/nspr/pr/tests/prpoll.c0000644000000000000000000002300312623070344014767 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef WIN32 #include #endif #ifdef XP_UNIX #include /* for close() */ #endif #include "prinit.h" #include "prio.h" #include "prlog.h" #include "prprf.h" #include "prnetdb.h" #include "private/pprio.h" #define CLIENT_LOOPS 5 #define BUF_SIZE 128 #include #include #include #ifdef WINCE int main(int argc, char **argv) { fprintf(stderr, "Invalid/Broken Test for WinCE/WinMobile\n"); exit(1); } #else static void clientThreadFunc(void *arg) { PRUint16 port = (PRUint16) arg; PRFileDesc *sock; PRNetAddr addr; char buf[BUF_SIZE]; int i; addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons(port); addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); PR_snprintf(buf, sizeof(buf), "%hu", port); for (i = 0; i < 5; i++) { sock = PR_NewTCPSocket(); PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); PR_Write(sock, buf, sizeof(buf)); PR_Close(sock); } } int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; char buf[BUF_SIZE]; PRThread *clientThread; PRPollDesc pds0[10], pds1[10], *pds, *other_pds; PRIntn npds; PRInt32 retVal; PRInt32 rv; PROsfd sd; struct sockaddr_in saddr; PRIntn saddr_len; PRUint16 listenPort3; PRFileDesc *socket_poll_fd; PRIntn i, j; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); printf("This program tests PR_Poll with sockets.\n"); printf("Timeout, error reporting, and normal operation are tested.\n\n"); /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); exit(1); } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); exit(1); } /* Set up the poll descriptor array */ pds = pds0; other_pds = pds1; memset(pds, 0, sizeof(pds)); npds = 0; pds[npds].fd = listenSock1; pds[npds].in_flags = PR_POLL_READ; npds++; pds[npds].fd = listenSock2; pds[npds].in_flags = PR_POLL_READ; npds++; sd = socket(AF_INET, SOCK_STREAM, 0); PR_ASSERT(sd >= 0); memset((char *) &saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(0); rv = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); PR_ASSERT(rv == 0); saddr_len = sizeof(saddr); rv = getsockname(sd, (struct sockaddr *) &saddr, &saddr_len); PR_ASSERT(rv == 0); listenPort3 = ntohs(saddr.sin_port); rv = listen(sd, 5); PR_ASSERT(rv == 0); pds[npds].fd = socket_poll_fd = PR_CreateSocketPollFd(sd); PR_ASSERT(pds[npds].fd); pds[npds].in_flags = PR_POLL_READ; npds++; PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu, %hu and %hu\n\n", listenPort1, listenPort2, listenPort3); printf("%s", buf); /* Testing timeout */ printf("PR_Poll should time out in 5 seconds\n"); retVal = PR_Poll(pds, npds, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Poll should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); exit(1); } printf("PR_Poll timed out. Test passed.\n\n"); /* Testing bad fd */ printf("PR_Poll should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); exit(1); } pds[npds].fd = badFD; pds[npds].in_flags = PR_POLL_READ; npds++; PR_Close(badFD); /* make the fd bad */ #if 0 retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); if (retVal != 1 || (unsigned short) pds[2].out_flags != PR_POLL_NVAL) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Poll returns %d, out_flags is 0x%hx\n", retVal, pds[npds - 1].out_flags); exit(1); } printf("PR_Poll detected the bad fd. Test passed.\n\n"); #endif npds--; clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort3, PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("Three client threads are created. Each of them will\n"); printf("send data to one of the three ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); /* 30 events total */ i = 0; while (i < 30) { PRPollDesc *tmp; int nextIndex; int nEvents = 0; retVal = PR_Poll(pds, npds, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Poll failed\n"); exit(1); } nextIndex = 3; /* the three listening sockets */ for (j = 0; j < 3; j++) { other_pds[j] = pds[j]; PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRFileDesc *sock; nEvents++; if (j == 2) { PROsfd newsd; newsd = accept(PR_FileDesc2NativeHandle(pds[j].fd), NULL, 0); if (newsd == -1) { fprintf(stderr, "accept() failed\n"); exit(1); } other_pds[nextIndex].fd = PR_CreateSocketPollFd(newsd); PR_ASSERT(other_pds[nextIndex].fd); other_pds[nextIndex].in_flags = PR_POLL_READ; } else { sock = PR_Accept(pds[j].fd, NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); exit(1); } other_pds[nextIndex].fd = sock; other_pds[nextIndex].in_flags = PR_POLL_READ; } nextIndex++; } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); exit(1); } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that fd %d is invalid\n", PR_FileDesc2NativeHandle(pds[j].fd)); exit(1); } } for (j = 3; j < npds; j++) { PR_ASSERT((pds[j].out_flags & PR_POLL_WRITE) == 0 && (pds[j].out_flags & PR_POLL_EXCEPT) == 0); if (pds[j].out_flags & PR_POLL_READ) { PRInt32 nBytes; nEvents++; /* XXX: This call is a hack and should be fixed */ if (PR_GetDescType(pds[j].fd) == (PRDescType) 0) { nBytes = recv(PR_FileDesc2NativeHandle(pds[j].fd), buf, sizeof(buf), 0); if (nBytes == -1) { fprintf(stderr, "recv() failed\n"); exit(1); } printf("Server read %d bytes from native fd %d\n",nBytes, PR_FileDesc2NativeHandle(pds[j].fd)); #ifdef WIN32 closesocket((SOCKET)PR_FileDesc2NativeHandle(pds[j].fd)); #else close(PR_FileDesc2NativeHandle(pds[j].fd)); #endif PR_DestroySocketPollFd(pds[j].fd); } else { nBytes = PR_Read(pds[j].fd, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read() failed\n"); exit(1); } PR_Close(pds[j].fd); } /* Just to be safe */ buf[BUF_SIZE - 1] = '\0'; printf("The server received \"%s\" from a client\n", buf); } else if (pds[j].out_flags & PR_POLL_ERR) { fprintf(stderr, "PR_Poll() indicates that an fd has error\n"); exit(1); } else if (pds[j].out_flags & PR_POLL_NVAL) { fprintf(stderr, "PR_Poll() indicates that an fd is invalid\n"); exit(1); } else { other_pds[nextIndex] = pds[j]; nextIndex++; } } PR_ASSERT(retVal == nEvents); /* swap */ tmp = pds; pds = other_pds; other_pds = tmp; npds = nextIndex; i += nEvents; } PR_DestroySocketPollFd(socket_poll_fd); printf("All tests finished\n"); PR_Cleanup(); return 0; } #endif /* ifdef WINCE */ nspr-4.11/nspr/pr/tests/prpollml.c0000644000000000000000000001043712623070344015327 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This test exercises the code that allocates and frees the syspoll_list * array of PRThread in the pthreads version. This test is intended to be * run under Purify to verify that there is no memory leak. */ #include "nspr.h" #include #include #include #ifdef SYMBIAN #define POLL_DESC_COUNT 128 #else #define POLL_DESC_COUNT 256 /* This should be greater than the * STACK_POLL_DESC_COUNT macro in * ptio.c to cause syspoll_list to * be created. */ #endif static PRPollDesc pd[POLL_DESC_COUNT]; static void Test(void) { int i; PRInt32 rv; PRIntervalTime timeout; timeout = PR_MillisecondsToInterval(10); /* cause syspoll_list to grow */ for (i = 1; i <= POLL_DESC_COUNT; i++) { rv = PR_Poll(pd, i, timeout); if (rv != 0) { fprintf(stderr, "PR_Poll should time out but returns %d (%d, %d)\n", (int) rv, (int) PR_GetError(), (int) PR_GetOSError()); exit(1); } } /* syspoll_list should be large enough for all these */ for (i = POLL_DESC_COUNT; i >= 1; i--) { rv = PR_Poll(pd, i, timeout); if (rv != 0) { fprintf(stderr, "PR_Poll should time out but returns %d\n", (int) rv); exit(1); } } } static void ThreadFunc(void *arg) { Test(); } int main(int argc, char **argv) { int i; PRThread *thread; PRFileDesc *sock; PRNetAddr addr; memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons(0); addr.inet.ip = PR_htonl(PR_INADDR_ANY); for (i = 0; i < POLL_DESC_COUNT; i++) { sock = PR_NewTCPSocket(); if (sock == NULL) { fprintf(stderr, "PR_NewTCPSocket failed (%d, %d)\n", (int) PR_GetError(), (int) PR_GetOSError()); fprintf(stderr, "Ensure the per process file descriptor limit " "is greater than %d.", POLL_DESC_COUNT); exit(1); } if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed (%d, %d)\n", (int) PR_GetError(), (int) PR_GetOSError()); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed (%d, %d)\n", (int) PR_GetError(), (int) PR_GetOSError()); exit(1); } pd[i].fd = sock; pd[i].in_flags = PR_POLL_READ; } /* first run the test on the primordial thread */ Test(); /* then run the test on all three kinds of threads */ thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == thread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } if (PR_JoinThread(thread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == thread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } if (PR_JoinThread(thread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } thread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_BOUND_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == thread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } if (PR_JoinThread(thread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } for (i = 0; i < POLL_DESC_COUNT; i++) { if (PR_Close(pd[i].fd) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } PR_Cleanup(); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/prselect.c0000644000000000000000000002271112623070344015305 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1997 - Netscape Communications Corporation ** ** Name: prselect_err.c ** ** Description: tests PR_Select with sockets Error condition functions. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prttools.h" #include "prinit.h" #include "prio.h" #include "prlog.h" #include "prprf.h" #include "prerror.h" #include "prnetdb.h" #include #include #include /*********************************************************************** ** PRIVATE FUNCTION: Test_Result ** DESCRIPTION: Used in conjunction with the regress tool, prints out the ** status of the test case. ** INPUTS: PASS/FAIL ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: Determine what the status is and print accordingly. ** ***********************************************************************/ static Test_Result (int result) { if (result == PASS) printf ("PASS\n"); else printf ("FAIL\n"); } static void clientThreadFunc(void *arg) { PRUint16 port = (PRUint16) arg; PRFileDesc *sock; PRNetAddr addr; char buf[128]; int i; addr.inet.family = AF_INET; addr.inet.port = PR_htons(port); addr.inet.ip = PR_htonl(INADDR_LOOPBACK); PR_snprintf(buf, sizeof(buf), "%hu", port); for (i = 0; i < 5; i++) { sock = PR_NewTCPSocket(); PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); PR_Write(sock, buf, sizeof(buf)); PR_Close(sock); } } int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds; PRIntn nfds; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRThread *clientThread; PRInt32 retVal; PRIntn i, j; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. Timeout, error\n"); printf("reporting, and normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); if (!debug_mode) Test_Result(FAIL); exit(1); } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); printf("%s", buf); /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* Testing timeout */ if (debug_mode) printf("PR_Select should time out in 5 seconds\n"); retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Select should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); if (!debug_mode) Test_Result(FAIL); } exit(1); } if (debug_mode) printf("PR_Select timed out. Test passed.\n\n"); else Test_Result(PASS); /* Testing bad fd */ printf("PR_Select should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); exit(1); } PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); PR_FD_SET(badFD, &readFdSet); PR_Close(badFD); /* make the fd bad */ retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Select returns %d\n", retVal); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); } exit(1); } printf("PR_Select detected a bad fd. Test passed.\n\n"); PR_FD_CLR(badFD, &readFdSet); clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); exit(1); } printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); /* set up the fd array */ fds = fds0; other_fds = fds1; fds[0] = listenSock1; fds[1] = listenSock2; nfds = 2; PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* 20 events total */ i = 0; while (i < 20) { PRFileDesc **tmp; int nextIndex; int nEvents = 0; retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_fds[j] = fds[j]; if (PR_FD_ISSET(fds[j], &readFdSet)) { PRFileDesc *sock; nEvents++; sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); exit(1); } other_fds[nextIndex] = sock; PR_FD_SET(sock, &readFdSet); nextIndex++; } PR_FD_SET(fds[j], &readFdSet); } for (j = 2; j < nfds; j++) { if (PR_FD_ISSET(fds[j], &readFdSet)) { PRInt32 nBytes; PR_FD_CLR(fds[j], &readFdSet); nEvents++; nBytes = PR_Read(fds[j], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read() failed\n"); exit(1); } /* Just to be safe */ buf[127] = '\0'; PR_Close(fds[j]); printf("The server received \"%s\" from a client\n", buf); } else { PR_FD_SET(fds[j], &readFdSet); other_fds[nextIndex] = fds[j]; nextIndex++; } } PR_ASSERT(retVal == nEvents); /* swap */ tmp = fds; fds = other_fds; other_fds = tmp; nfds = nextIndex; i += nEvents; } printf("All tests finished\n"); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/prttools.h0000644000000000000000000000060012623070344015350 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Used in Regress Tool */ #define NOSTATUS 2 #define PASS 1 #define FAIL 0 PRIntn debug_mode=0; nspr-4.11/nspr/pr/tests/pushtop.c0000644000000000000000000000367512623070344015176 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* A regression test for bug 794316 */ #include #include #include "prio.h" static PRIOMethods dummyMethods; int main() { PRDescIdentity topId, middleId, bottomId; PRFileDesc *top, *middle, *bottom; PRFileDesc *fd; topId = PR_GetUniqueIdentity("top"); middleId = PR_GetUniqueIdentity("middle"); bottomId = PR_GetUniqueIdentity("bottom"); top = PR_CreateIOLayerStub(topId, &dummyMethods); middle = PR_CreateIOLayerStub(middleId, &dummyMethods); bottom = PR_CreateIOLayerStub(bottomId, &dummyMethods); fd = bottom; PR_PushIOLayer(fd, PR_TOP_IO_LAYER, middle); PR_PushIOLayer(fd, PR_TOP_IO_LAYER, top); top = fd; middle = top->lower; bottom = middle->lower; /* Verify that the higher pointers are correct. */ if (middle->higher != top) { fprintf(stderr, "middle->higher is wrong\n"); fprintf(stderr, "FAILED\n"); exit(1); } if (bottom->higher != middle) { fprintf(stderr, "bottom->higher is wrong\n"); fprintf(stderr, "FAILED\n"); exit(1); } top = PR_PopIOLayer(fd, topId); top->dtor(top); middle = fd; bottom = middle->lower; /* Verify that the higher pointer is correct. */ if (bottom->higher != middle) { fprintf(stderr, "bottom->higher is wrong\n"); fprintf(stderr, "FAILED\n"); exit(1); } middle = PR_PopIOLayer(fd, middleId); middle->dtor(middle); if (fd->identity != bottomId) { fprintf(stderr, "The bottom layer has the wrong identity\n"); fprintf(stderr, "FAILED\n"); exit(1); } fd->dtor(fd); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/randseed.c0000644000000000000000000000645512623070344015260 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: rngseed.c ** Description: ** Test NSPR's Random Number Seed generator ** ** Initial test: Just make sure it outputs some data. ** ** ... more? ... check some iterations to ensure it is random (no dupes) ** ... more? ... histogram distribution of random numbers */ #include "plgetopt.h" #include "nspr.h" #include "prrng.h" #include #include #include /* ** Test harness infrastructure */ PRLogModuleInfo *lm; PRLogModuleLevel msgLevel = PR_LOG_NONE; PRIntn debug = 0; PRUint32 failed_already = 0; /* end Test harness infrastructure */ PRIntn optRandCount = 30; char buf[40]; PRSize bufSize = sizeof(buf); PRSize rSize; PRIntn i; /* ** Emit help text for this test */ static void Help( void ) { printf("Template: Help(): display your help message(s) here"); exit(1); } /* end Help() */ static void PrintRand( void *buf, PRIntn size ) { PRUint32 *rp = buf; PRIntn i; printf("%4.4d--\n", size ); while (size > 0 ) { switch( size ) { case 1 : printf("%2.2X\n", *(rp++) ); size -= 4; break; case 2 : printf("%4.4X\n", *(rp++) ); size -= 4; break; case 3 : printf("%6.6X\n", *(rp++) ); size -= 4; break; default: while ( size >= 4) { PRIntn i = 3; do { printf("%8.8X ", *(rp++) ); size -= 4; } while( i-- ); i = 3; printf("\n"); } break; } /* end switch() */ } /* end while() */ } /* end PrintRand() */ int main(int argc, char **argv) { { /* ** Get command line options */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "hdv"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug */ debug = 1; msgLevel = PR_LOG_ERROR; break; case 'v': /* verbose mode */ msgLevel = PR_LOG_DEBUG; break; case 'h': /* help message */ Help(); break; default: break; } } PL_DestroyOptState(opt); } lm = PR_NewLogModule("Test"); /* Initialize logging */ for ( i = 0; i < optRandCount ; i++ ) { memset( buf, 0, bufSize ); rSize = PR_GetRandomNoise( buf, bufSize ); if (!rSize) { fprintf(stderr, "Not implemented\n" ); failed_already = PR_TRUE; break; } if (debug) PrintRand( buf, rSize ); } if (debug) printf("%s\n", (failed_already)? "FAIL" : "PASS"); return( (failed_already == PR_TRUE )? 1 : 0 ); } /* main() */ /* end template.c */ nspr-4.11/nspr/pr/tests/ranfile.c0000644000000000000000000003170612623070344015110 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Contact: AOF ** ** Name: ranfile.c ** ** Description: Test to hammer on various components of NSPR ** Modification History: ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prthread.h" #include "prlock.h" #include "prcvar.h" #include "prmem.h" #include "prinrval.h" #include "prio.h" #include #include static PRIntn debug_mode = 0; static PRIntn failed_already=0; static PRThreadScope thread_scope = PR_LOCAL_THREAD; typedef enum {sg_go, sg_stop, sg_done} Action; typedef enum {sg_okay, sg_open, sg_close, sg_delete, sg_write, sg_seek} Problem; typedef struct Hammer_s { PRLock *ml; PRCondVar *cv; PRUint32 id; PRUint32 limit; PRUint32 writes; PRThread *thread; PRIntervalTime timein; Action action; Problem problem; } Hammer_t; #define DEFAULT_LIMIT 10 #define DEFAULT_THREADS 2 #define DEFAULT_LOOPS 1 static PRInt32 pageSize = 1024; static const char* baseName = "./"; static const char *programName = "Random File"; /*********************************************************************** ** PRIVATE FUNCTION: RandomNum ** DESCRIPTION: ** Generate a pseudo-random number ** INPUTS: None ** OUTPUTS: None ** RETURN: A pseudo-random unsigned number, 32-bits wide ** SIDE EFFECTS: ** Updates random seed (a static) ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: ** Uses the current interval timer value, promoted to a 64 bit ** float as a multiplier for a static residue (which begins ** as an uninitialized variable). The result is bits [16..48) ** of the product. Seed is then updated with the return value ** promoted to a float-64. ***********************************************************************/ static PRUint32 RandomNum(void) { PRUint32 rv; PRUint64 shift; static PRFloat64 seed = 0x58a9382; /* Just make sure it isn't 0! */ PRFloat64 random = seed * (PRFloat64)PR_IntervalNow(); LL_USHR(shift, *((PRUint64*)&random), 16); LL_L2UI(rv, shift); seed = (PRFloat64)rv; return rv; } /* RandomNum */ /*********************************************************************** ** PRIVATE FUNCTION: Thread ** DESCRIPTION: ** Hammer on the file I/O system ** INPUTS: A pointer to the thread's private data ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** Creates, accesses and deletes a file ** RESTRICTIONS: ** (Currently) must have file create permission in "/usr/tmp". ** MEMORY: NA ** ALGORITHM: ** This function is a root of a thread ** 1) Creates a (hopefully) unique file in /usr/tmp/ ** 2) Writes a zero to a random number of sequential pages ** 3) Closes the file ** 4) Reopens the file ** 5) Seeks to a random page within the file ** 6) Writes a one byte on that page ** 7) Repeat steps [5..6] for each page in the file ** 8) Close and delete the file ** 9) Repeat steps [1..8] until told to stop ** 10) Notify complete and return ***********************************************************************/ static void PR_CALLBACK Thread(void *arg) { PRUint32 index; char filename[30]; const char zero = 0; PRFileDesc *file = NULL; PRStatus rv = PR_SUCCESS; Hammer_t *cd = (Hammer_t*)arg; (void)sprintf(filename, "%ssg%04ld.dat", baseName, cd->id); if (debug_mode) printf("Starting work on %s\n", filename); while (PR_TRUE) { PRUint32 bytes; PRUint32 minor = (RandomNum() % cd->limit) + 1; PRUint32 random = (RandomNum() % cd->limit) + 1; PRUint32 pages = (RandomNum() % cd->limit) + 10; while (minor-- > 0) { cd->problem = sg_okay; if (cd->action != sg_go) goto finished; cd->problem = sg_open; file = PR_Open(filename, PR_RDWR|PR_CREATE_FILE, 0666); if (file == NULL) goto finished; for (index = 0; index < pages; index++) { cd->problem = sg_okay; if (cd->action != sg_go) goto close; cd->problem = sg_seek; bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET); if (bytes != pageSize * index) goto close; cd->problem = sg_write; bytes = PR_Write(file, &zero, sizeof(zero)); if (bytes <= 0) goto close; cd->writes += 1; } cd->problem = sg_close; rv = PR_Close(file); if (rv != PR_SUCCESS) goto purge; cd->problem = sg_okay; if (cd->action != sg_go) goto purge; cd->problem = sg_open; file = PR_Open(filename, PR_RDWR, 0666); for (index = 0; index < pages; index++) { cd->problem = sg_okay; if (cd->action != sg_go) goto close; cd->problem = sg_seek; bytes = PR_Seek(file, pageSize * index, PR_SEEK_SET); if (bytes != pageSize * index) goto close; cd->problem = sg_write; bytes = PR_Write(file, &zero, sizeof(zero)); if (bytes <= 0) goto close; cd->writes += 1; random = (random + 511) % pages; } cd->problem = sg_close; rv = PR_Close(file); if (rv != PR_SUCCESS) goto purge; cd->problem = sg_delete; rv = PR_Delete(filename); if (rv != PR_SUCCESS) goto finished; } } close: (void)PR_Close(file); purge: (void)PR_Delete(filename); finished: PR_Lock(cd->ml); cd->action = sg_done; PR_NotifyCondVar(cd->cv); PR_Unlock(cd->ml); if (debug_mode) printf("Ending work on %s\n", filename); return; } /* Thread */ static Hammer_t hammer[100]; static PRCondVar *cv; /*********************************************************************** ** PRIVATE FUNCTION: main ** DESCRIPTION: ** Hammer on the file I/O system ** INPUTS: The usual argc and argv ** argv[0] - program name (not used) ** argv[1] - the number of times to execute the major loop ** argv[2] - the number of threads to toss into the batch ** argv[3] - the clipping number applied to randoms ** default values: loops = 2, threads = 10, limit = 57 ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** Creates, accesses and deletes lots of files ** RESTRICTIONS: ** (Currently) must have file create permission in "/usr/tmp". ** MEMORY: NA ** ALGORITHM: ** 1) Fork a "Thread()" ** 2) Wait for 'interleave' seconds ** 3) For [0..'threads') repeat [1..2] ** 4) Mark all objects to stop ** 5) Collect the threads, accumulating the results ** 6) For [0..'loops') repeat [1..5] ** 7) Print accumulated results and exit ** ** Characteristic output (from IRIX) ** Random File: Using loops = 2, threads = 10, limit = 57 ** Random File: [min [avg] max] writes/sec average ***********************************************************************/ int main(int argc, char **argv) { PRLock *ml; PRUint32 id = 0; int active, poll; PRIntervalTime interleave; PRIntervalTime duration = 0; int limit = 0, loops = 0, threads = 0, times; PRUint32 writes, writesMin = 0x7fffffff, writesTot = 0, durationTot = 0, writesMax = 0; const char *where[] = {"okay", "open", "close", "delete", "write", "seek"}; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "Gdl:t:i:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'G': /* global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'd': /* debug mode */ debug_mode = 1; break; case 'l': /* limiting number */ limit = atoi(opt->value); break; case 't': /* number of threads */ threads = atoi(opt->value); break; case 'i': /* iteration counter */ loops = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); interleave = PR_SecondsToInterval(10); ml = PR_NewLock(); cv = PR_NewCondVar(ml); if (loops == 0) loops = DEFAULT_LOOPS; if (limit == 0) limit = DEFAULT_LIMIT; if (threads == 0) threads = DEFAULT_THREADS; if (debug_mode) printf( "%s: Using loops = %d, threads = %d, limit = %d and %s threads\n", programName, loops, threads, limit, (thread_scope == PR_LOCAL_THREAD) ? "LOCAL" : "GLOBAL"); for (times = 0; times < loops; ++times) { if (debug_mode) printf("%s: Setting concurrency level to %d\n", programName, times + 1); PR_SetConcurrency(times + 1); for (active = 0; active < threads; active++) { hammer[active].ml = ml; hammer[active].cv = cv; hammer[active].id = id++; hammer[active].writes = 0; hammer[active].action = sg_go; hammer[active].problem = sg_okay; hammer[active].limit = (RandomNum() % limit) + 1; hammer[active].timein = PR_IntervalNow(); hammer[active].thread = PR_CreateThread( PR_USER_THREAD, Thread, &hammer[active], PR_GetThreadPriority(PR_GetCurrentThread()), thread_scope, PR_JOINABLE_THREAD, 0); PR_Lock(ml); PR_WaitCondVar(cv, interleave); /* start new ones slowly */ PR_Unlock(ml); } /* * The last thread started has had the opportunity to run for * 'interleave' seconds. Now gather them all back in. */ PR_Lock(ml); for (poll = 0; poll < threads; poll++) { if (hammer[poll].action == sg_go) /* don't overwrite done */ hammer[poll].action = sg_stop; /* ask him to stop */ } PR_Unlock(ml); while (active > 0) { for (poll = 0; poll < threads; poll++) { PR_Lock(ml); while (hammer[poll].action < sg_done) PR_WaitCondVar(cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(ml); active -= 1; /* this is another one down */ (void)PR_JoinThread(hammer[poll].thread); hammer[poll].thread = NULL; if (hammer[poll].problem == sg_okay) { duration = PR_IntervalToMilliseconds( PR_IntervalNow() - hammer[poll].timein); writes = hammer[poll].writes * 1000 / duration; if (writes < writesMin) writesMin = writes; if (writes > writesMax) writesMax = writes; writesTot += hammer[poll].writes; durationTot += duration; } else if (debug_mode) printf( "%s: test failed %s after %ld seconds\n", programName, where[hammer[poll].problem], duration); else failed_already=1; } } } if (debug_mode) printf( "%s: [%ld [%ld] %ld] writes/sec average\n", programName, writesMin, writesTot * 1000 / durationTot, writesMax); PR_DestroyCondVar(cv); PR_DestroyLock(ml); if (failed_already) { printf("FAIL\n"); return 1; } else { printf("PASS\n"); return 0; } } /* main */ nspr-4.11/nspr/pr/tests/reinit.c0000644000000000000000000000165312623070344014760 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* This test verifies that NSPR can be cleaned up and reinitialized. */ #include "nspr.h" #include int main() { PRStatus rv; fprintf(stderr, "Init 1\n"); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); fprintf(stderr, "Cleanup 1\n"); rv = PR_Cleanup(); if (rv != PR_SUCCESS) { fprintf(stderr, "FAIL\n"); return 1; } fprintf(stderr, "Init 2\n"); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); fprintf(stderr, "Cleanup 2\n"); rv = PR_Cleanup(); if (rv != PR_SUCCESS) { fprintf(stderr, "FAIL\n"); return 1; } fprintf(stderr, "PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/rmdir.c0000644000000000000000000000463512623070344014606 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: rmdir.c ** Description: Demonstrate bugzilla 80884. ** ** after fix to unix_errors.c, message should report correct ** failure of PR_Rmdir(). ** ** ** */ #include #include #include #include #include "plgetopt.h" #define DIRNAME "xxxBug80884/" #define FILENAME "file80883" PRBool failed_already = PR_FALSE; PRBool debug_mode = PR_FALSE; PRLogModuleInfo *lm; /* ** Help() -- print Usage information */ static void Help( void ) { fprintf(stderr, "template usage:\n" "\t-d debug mode\n" ); } /* --- end Help() */ int main(int argc, char **argv) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dh"); PRFileDesc* fd; PRErrorCode err; /* parse command line options */ while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); lm = PR_NewLogModule( "testcase" ); (void) PR_MkDir( DIRNAME, 0777); fd = PR_Open( DIRNAME FILENAME, PR_CREATE_FILE|PR_RDWR, 0666); if (fd == 0) { PRErrorCode err = PR_GetError(); fprintf(stderr, "create file fails: %d: %s\n", err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); failed_already = PR_TRUE; goto Finished; } PR_Close(fd); if (PR_RmDir( DIRNAME ) == PR_SUCCESS) { fprintf(stderr, "remove directory succeeds\n"); failed_already = PR_TRUE; goto Finished; } err = PR_GetError(); fprintf(stderr, "remove directory fails with: %d: %s\n", err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT)); (void) PR_Delete( DIRNAME FILENAME); (void) PR_RmDir( DIRNAME ); return 0; Finished: if ( debug_mode ) printf("%s\n", ( failed_already ) ? "FAILED" : "PASS" ); return( (failed_already)? 1 : 0 ); } /* --- end main() */ /* --- end template.c */ nspr-4.11/nspr/pr/tests/runtests.pl0000755000000000000000000001723312623070344015552 0ustar 00000000000000#!/usr/bin/perl # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. use POSIX qw(:sys_wait_h); use POSIX qw(setsid); use FileHandle; # Constants $WINOS = "MSWin32"; $osname = $^O; use Cwd; if ($osname =~ $WINOS) { # Windows require Win32::Process; require Win32; } # Get environment variables. $output_file = $ENV{NSPR_TEST_LOGFILE}; $timeout = $ENV{TEST_TIMEOUT}; $timeout = 0 if (!defined($timeout)); sub getTime { ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); $year = 1900 + $yearOffset; $theTime = sprintf("%04d-%02d-%02d %02d:%02d:%02d",$year,$month,$dayOfMonth,$hour,$minute,$second); return $theTime; } sub open_log { if (!defined($output_file)) { print "No output file.\n"; # null device if ($osname =~ $WINOS) { $output_file = "nul"; } else { $output_file = "/dev/null"; } } # use STDOUT for OF (to print summary of test results) open(OF, ">&STDOUT") or die "Can't reuse STDOUT for OF\n"; OF->autoflush; # reassign STDOUT to $output_file (to print details of test results) open(STDOUT, ">$output_file") or die "Can't open file $output_file for STDOUT\n"; STDOUT->autoflush; # redirect STDERR to STDOUT open(STDERR, ">&STDOUT") or die "Can't redirect STDERR to STDOUT\n"; STDERR->autoflush; # Print header test in summary $now = getTime; print OF "\nNSPR Test Results - tests\n"; print OF "\nBEGIN\t\t\t$now\n"; print OF "NSPR_TEST_LOGFILE\t$output_file\n"; print OF "TEST_TIMEOUT\t$timeout\n\n"; print OF "\nTest\t\t\tResult\n\n"; } sub close_log { # end of test marker in summary $now = getTime; print OF "END\t\t\t$now\n"; close(OF) or die "Can't close file OF\n"; close(STDERR) or die "Can't close STDERR\n"; close(STDOUT) or die "Can't close STDOUT\n"; } sub print_begin { $lprog = shift; # Summary output print OF "$prog"; # Full output $now = getTime; print "BEGIN TEST: $lprog ($now)\n\n"; } sub print_end { ($lprog, $exit_status, $exit_signal, $exit_core) = @_; if (($exit_status == 0) && ($exit_signal == 0) && ($exit_core == 0)) { $str_status = "Passed"; } else { $str_status = "FAILED"; } if ($exit_signal != 0) { $str_signal = " - signal $exit_signal"; } else { $str_signal = ""; } if ($exit_core != 0) { $str_core = " - core dumped"; } else { $str_core = ""; } $now = getTime; # Full output print "\nEND TEST: $lprog ($now)\n"; print "TEST STATUS: $lprog = $str_status (exit status " . $exit_status . $str_signal . $str_core . ")\n"; print "--------------------------------------------------\n\n"; # Summary output print OF "\t\t\t$str_status\n"; } sub ux_start_prog { # parameters: $lprog = shift; # command to run # Create a process group for the child # so we can kill all of it if needed setsid or die "setsid failed: $!"; # Start test program exec("./$lprog"); # We should not be here unless exec failed. print "Faild to exec $lprog"; exit 1 << 8; } sub ux_wait_timeout { # parameters: $lpid = shift; # child process id $ltimeout = shift; # timeout if ($ltimeout == 0) { # No timeout: use blocking wait $ret = waitpid($lpid,0); # Exit and don't kill $lstatus = $?; $ltimeout = -1; } else { while ($ltimeout > 0) { # Check status of child using non blocking wait $ret = waitpid($lpid, WNOHANG); if ($ret == 0) { # Child still running # print "Time left=$ltimeout\n"; sleep 1; $ltimeout--; } else { # Child has ended $lstatus = $?; # Exit the wait loop and don't kill $ltimeout = -1; } } } if ($ltimeout == 0) { # we ran all the timeout: it's time to kill the child print "Timeout ! Kill child process $lpid\n"; # Kill the child process and group kill(-9,$lpid); $lstatus = 9; } return $lstatus; } sub ux_test_prog { # parameters: $prog = shift; # Program to test $child_pid = fork; if ($child_pid == 0) { # we are in the child process print_begin($prog); ux_start_prog($prog); } else { # we are in the parent process $status = ux_wait_timeout($child_pid,$timeout); # See Perlvar for documentation of $? # exit status = $status >> 8 # exit signal = $status & 127 (no signal = 0) # core dump = $status & 128 (no core = 0) print_end($prog, $status >> 8, $status & 127, $status & 128); } return $status; } sub win_path { $lpath = shift; # MSYS drive letter = /c/ -> c:/ $lpath =~ s/^\/(\w)\//$1:\//; # Cygwin drive letter = /cygdrive/c/ -> c:/ $lpath =~ s/^\/cygdrive\/(\w)\//$1:\//; # replace / with \\ $lpath =~ s/\//\\\\/g; return $lpath; } sub win_ErrorReport{ print Win32::FormatMessage( Win32::GetLastError() ); } sub win_test_prog { # parameters: $prog = shift; # Program to test $status = 1; $curdir = getcwd; $curdir = win_path($curdir); $prog_path = "$curdir\\$prog.exe"; print_begin($prog); Win32::Process::Create($ProcessObj, "$prog_path", "$prog", 0, NORMAL_PRIORITY_CLASS, ".")|| die win_ErrorReport(); $retwait = $ProcessObj->Wait($timeout * 1000); if ( $retwait == 0) { # the prog didn't finish after the timeout: kill $ProcessObj->Kill($status); print "Timeout ! Process killed with exit status $status\n"; } else { # the prog finished before the timeout: get exit status $ProcessObj->GetExitCode($status); } # There is no signal, no core on Windows print_end($prog, $status, 0, 0); return $status } # MAIN --------------- @progs = ( "accept", "acceptread", "acceptreademu", "affinity", "alarm", "anonfm", "atomic", "attach", "bigfile", "cleanup", "cltsrv", "concur", "cvar", "cvar2", "dlltest", "dtoa", "errcodes", "exit", "fdcach", "fileio", "foreign", "formattm", "fsync", "gethost", "getproto", "i2l", "initclk", "inrval", "instrumt", "intrio", "intrupt", "io_timeout", "ioconthr", "join", "joinkk", "joinku", "joinuk", "joinuu", "layer", "lazyinit", "libfilename", "lltest", "lock", "lockfile", "logfile", "logger", "many_cv", "multiwait", "nameshm1", "nblayer", "nonblock", "ntioto", "ntoh", "op_2long", "op_excl", "op_filnf", "op_filok", "op_nofil", "parent", "parsetm", "peek", "perf", "pipeping", "pipeping2", "pipeself", "poll_nm", "poll_to", "pollable", "prftest", "prfz", "primblok", "provider", "prpollml", "pushtop", "ranfile", "randseed", "reinit", "rwlocktest", "sel_spd", "selct_er", "selct_nm", "selct_to", "selintr", "sema", "semaerr", "semaping", "sendzlf", "server_test", "servr_kk", "servr_uk", "servr_ku", "servr_uu", "short_thread", "sigpipe", "socket", "sockopt", "sockping", "sprintf", "stack", "stdio", "str2addr", "strod", "switch", "system", "testbit", "testfile", "threads", "timemac", "timetest", "tpd", "udpsrv", "vercheck", "version", "writev", "xnotify", "zerolen"); open_log; foreach $current_prog (@progs) { if ($osname =~ $WINOS) { win_test_prog($current_prog); } else { ux_test_prog($current_prog); } } close_log; nspr-4.11/nspr/pr/tests/runtests.sh0000755000000000000000000001122012623070344015537 0ustar 00000000000000#!/bin/sh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # runtests.sh # Bourne shell script for nspr tests # SYSTEM_INFO=`uname -a` OS_ARCH=`uname -s` if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "OS/2" ] then NULL_DEVICE=nul else NULL_DEVICE=/dev/null FILE_D=`ulimit -n` if [ $FILE_D -lt 512 ] then ulimit -n 512 fi fi # # Irrevelant tests # #bug1test - used to demonstrate a bug on NT #bigfile2 - requires 4Gig file creation. See BugZilla #5451 #bigfile3 - requires 4Gig file creation. See BugZilla #5451 #dbmalloc - obsolete; originally for testing debug version of nspr's malloc #dbmalloc1 - obsolete; originally for testing debug version of nspr's malloc #depend - obsolete; used to test a initial spec for library dependencies #dceemu - used to tests special functions in NSPR for DCE emulation #ipv6 - IPV6 not in use by NSPR clients #mbcs - tests use of multi-byte charset for filenames. See BugZilla #25140 #sproc_ch - obsolete; sproc-based tests for Irix #sproc_p - obsolete; sproc-based tests for Irix #io_timeoutk - obsolete; subsumed in io_timeout #io_timeoutu - obsolete; subsumed in io_timeout #prftest1 - obsolete; subsumed by prftest #prftest2 - obsolete; subsumed by prftest #prselect - obsolete; PR_Select is obsolete #select2 - obsolete; PR_Select is obsolete #sem - obsolete; PRSemaphore is obsolete #stat - for OS2? #suspend - private interfaces PR_SuspendAll, PR_ResumeAll, etc.. #thruput - needs to be run manually as client/server #time - used to measure time with native calls and nspr calls #tmoacc - should be run with tmocon #tmocon - should be run with tmoacc #op_noacc - limited use #yield - limited use for PR_Yield # # Tests not run (but should) # #forktest (failed on IRIX) #nbconn - fails on some platforms #poll_er - fails on some platforms? limited use? #prpoll - the bad-FD test needs to be moved to a different test #sleep - specific to OS/2 LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE} # # Tests run on all platforms # TESTS=" accept acceptread acceptreademu affinity alarm anonfm atomic attach bigfile cleanup cltsrv concur cvar cvar2 dlltest dtoa errcodes exit fdcach fileio foreign formattm fsync gethost getproto i2l initclk inrval instrumt intrio intrupt io_timeout ioconthr join joinkk joinku joinuk joinuu layer lazyinit libfilename lltest lock lockfile logfile logger many_cv multiwait nameshm1 nblayer nonblock ntioto ntoh op_2long op_excl op_filnf op_filok op_nofil parent parsetm peek perf pipeping pipeping2 pipeself poll_nm poll_to pollable prftest prfz primblok provider prpollml pushtop ranfile randseed reinit rwlocktest sel_spd selct_er selct_nm selct_to selintr sema semaerr semaping sendzlf server_test servr_kk servr_uk servr_ku servr_uu short_thread sigpipe socket sockopt sockping sprintf stack stdio str2addr strod switch system testbit testfile threads timemac timetest tpd udpsrv vercheck version writev xnotify zerolen" rval=0 # # When set, value of the environment variable TEST_TIMEOUT is the maximum # time (secs) allowed for a test program beyond which it is terminated. # If TEST_TIMEOUT is not set or if it's value is 0, then test programs # don't timeout. # # Running runtests.ksh under MKS toolkit on NT, 95, 98 does not cause # timeout detection correctly. For these platforms, do not attempt timeout # test. (lth). # # OS_PLATFORM=`uname` OBJDIR=`basename $PWD` printf "\nNSPR Test Results - $OBJDIR\n\n" printf "BEGIN\t\t\t`date`\n" printf "NSPR_TEST_LOGFILE\t${LOGFILE}\n\n" printf "Test\t\t\tResult\n\n" if [ $OS_PLATFORM = "Windows_95" ] || [ $OS_PLATFORM = "Windows_98" ] || [ $OS_PLATFORM = "Windows_NT" ] || [ $OS_PLATFORM = "OS/2" ] ; then for prog in $TESTS do printf "$prog" printf "\nBEGIN TEST: $prog\n\n" >> ${LOGFILE} 2>&1 ./$prog >> ${LOGFILE} 2>&1 if [ 0 = $? ] ; then printf "\t\t\tPassed\n"; else printf "\t\t\tFAILED\n"; rval=1 fi; printf "\nEND TEST: $prog\n\n" >> ${LOGFILE} 2>&1 done else for prog in $TESTS do printf "$prog" printf "\nBEGIN TEST: $prog\n\n" >> ${LOGFILE} 2>&1 export test_rval ./$prog >> ${LOGFILE} 2>&1 & test_pid=$! sleep_pid=0 if test -n "$TEST_TIMEOUT" && test "$TEST_TIMEOUT" -gt 0 then (sleep $TEST_TIMEOUT; kill $test_pid >/dev/null 2>&1 ) & sleep_pid=$! fi wait $test_pid test_rval=$? [ $sleep_pid -eq 0 ] || kill $sleep_pid >/dev/null 2>&1 if [ 0 = $test_rval ] ; then printf "\t\t\tPassed\n"; else printf "\t\t\tFAILED\n"; rval=1 fi; printf "\nEND TEST: $prog\n\n" >> ${LOGFILE} 2>&1 done fi; printf "END\t\t\t`date`\n" exit $rval nspr-4.11/nspr/pr/tests/runy2ktests.ksh0000644000000000000000000000702412623070344016344 0ustar 00000000000000#!/bin/ksh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # runy2ktests.ksh # Set system clock to Y2K dates of interest and run the Y2K tests. # Needs root/administrator privilege # # WARNING: Because this script needs to be run with root/administrator # privilege, thorough understanding of the script and extreme # caution are urged. # # # SECTION I # Define variables # SYSTEM_INFO=`uname -a` OS_ARCH=`uname -s` if [ $OS_ARCH = "Windows_NT" ] || [ $OS_ARCH = "Windows_95" ] then NULL_DEVICE=nul else NULL_DEVICE=/dev/null fi # # Test dates for NSPR Y2K tests # Y2KDATES=" 123123591998.55 090923591999.55 123123591999.55 022823592000.55 022923592000.55 123123592000.55" Y2KDATES_AIX=" 12312359.5598 09092359.5599 12312359.5599 02282359.5500 02292359.5500 12312359.5500" Y2KDATES_HPUX=" 123123591998 090923591999 123123591999 022823592000 022923592000 123123592000" Y2KDATES_MKS=" 1231235998.55 0909235999.55 1231235999.55 0228235900.55 0229235900.55 1231235900.55" # # NSPR Y2K tests # Y2KTESTS=" y2k \n y2ktmo \n y2k \n ../runtests.ksh" Y2KTESTS_HPUX=" y2k \n y2ktmo -l 60\n y2k \n ../runtests.ksh" # # SECTION II # Define functions # save_date() { case $OS_ARCH in AIX) SAVED_DATE=`date "+%m%d%H%M.%S%y"` ;; HP-UX) SAVED_DATE=`date "+%m%d%H%M%Y"` ;; Windows_NT) SAVED_DATE=`date "+%m%d%H%M%y.%S"` ;; Windows_95) SAVED_DATE=`date "+%m%d%H%M%y.%S"` ;; *) SAVED_DATE=`date "+%m%d%H%M%Y.%S"` ;; esac } set_date() { case $OS_ARCH in Windows_NT) # # The date command in MKS Toolkit releases 5.1 and 5.2 # uses the current DST status for the date we want to # set the system clock to. However, the DST status for # that date may be different from the current DST status. # We can work around this problem by invoking the date # command with the same date twice. # date "$1" > $NULL_DEVICE date "$1" > $NULL_DEVICE ;; *) date "$1" > $NULL_DEVICE ;; esac } restore_date() { set_date "$SAVED_DATE" } savedate() { case $OS_ARCH in AIX) SAVED_DATE=`date "+%m%d%H%M.%S%y"` ;; HP-UX) SAVED_DATE=`date "+%m%d%H%M%Y"` ;; Windows_NT) SAVED_DATE=`date "+%m%d%H%M%y.%S"` ;; Windows_95) SAVED_DATE=`date "+%m%d%H%M%y.%S"` ;; *) SAVED_DATE=`date "+%m%d%H%M%Y.%S"` ;; esac } set_y2k_test_parameters() { # # set dates # case $OS_ARCH in AIX) DATES=$Y2KDATES_AIX ;; HP-UX) DATES=$Y2KDATES_HPUX ;; Windows_NT) DATES=$Y2KDATES_MKS ;; Windows_95) DATES=$Y2KDATES_MKS ;; *) DATES=$Y2KDATES ;; esac # # set tests # case $OS_ARCH in HP-UX) TESTS=$Y2KTESTS_HPUX ;; *) TESTS=$Y2KTESTS ;; esac } # # runtests: # - runs each test in $TESTS after setting the # system clock to each date in $DATES # runtests() { for newdate in ${DATES} do set_date $newdate echo $newdate echo "BEGIN\t\t\t`date`" echo "Date\t\t\t\t\tTest\t\t\tResult" echo $TESTS | while read prog do echo "`date`\t\t\c" echo "$prog\c" ./$prog >> ${LOGFILE} 2>&1 if [ 0 = $? ] ; then echo "\t\t\tPassed"; else echo "\t\t\tFAILED"; fi; done echo "END\t\t\t`date`\n" done } # # SECTION III # Run tests # LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE} OBJDIR=`basename $PWD` echo "\nNSPR Year 2000 Test Results - $OBJDIR\n" echo "SYSTEM:\t\t\t${SYSTEM_INFO}" echo "NSPR_TEST_LOGFILE:\t${LOGFILE}\n" save_date # # Run NSPR Y2k and standard tests # set_y2k_test_parameters runtests restore_date nspr-4.11/nspr/pr/tests/rwlockrank.c0000644000000000000000000000574112623070344015645 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * RWLock rank tests */ #include "nspr.h" #include "plgetopt.h" static int _debug_on; static PRRWLock *rwlock0; static PRRWLock *rwlock1; static PRRWLock *rwlock2; static void rwtest(void *args) { PR_RWLock_Rlock(rwlock1); PR_RWLock_Unlock(rwlock1); PR_RWLock_Rlock(rwlock1); PR_RWLock_Unlock(rwlock1); /* Test correct lock rank. */ PR_RWLock_Rlock(rwlock1); PR_RWLock_Rlock(rwlock2); PR_RWLock_Unlock(rwlock2); PR_RWLock_Unlock(rwlock1); PR_RWLock_Rlock(rwlock1); PR_RWLock_Rlock(rwlock2); PR_RWLock_Unlock(rwlock1); PR_RWLock_Unlock(rwlock2); PR_RWLock_Rlock(rwlock1); PR_RWLock_Rlock(rwlock0); PR_RWLock_Rlock(rwlock2); PR_RWLock_Unlock(rwlock2); PR_RWLock_Unlock(rwlock0); PR_RWLock_Unlock(rwlock1); #if 0 /* Test incorrect lock rank. */ PR_RWLock_Rlock(rwlock2); PR_RWLock_Rlock(rwlock1); PR_RWLock_Unlock(rwlock1); PR_RWLock_Unlock(rwlock2); PR_RWLock_Rlock(rwlock2); PR_RWLock_Rlock(rwlock0); PR_RWLock_Rlock(rwlock1); PR_RWLock_Unlock(rwlock1); PR_RWLock_Unlock(rwlock0); PR_RWLock_Unlock(rwlock2); #endif } int main(int argc, char **argv) { PRStatus rc; PRThread *thread; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); rwlock0 = PR_NewRWLock(PR_RWLOCK_RANK_NONE, "Lock 0"); if (rwlock0 == NULL) { fprintf(stderr, "PR_NewRWLock failed - error %d\n", (int)PR_GetError()); return 1; } rwlock1 = PR_NewRWLock(1, "Lock 1"); if (rwlock1 == NULL) { fprintf(stderr, "PR_NewRWLock failed - error %d\n", (int)PR_GetError()); return 1; } rwlock2 = PR_NewRWLock(2, "Lock 2"); if (rwlock2 == NULL) { fprintf(stderr, "PR_NewRWLock failed - error %d\n", (int)PR_GetError()); return 1; } thread = PR_CreateThread(PR_USER_THREAD, rwtest, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (thread == NULL) { fprintf(stderr, "PR_CreateThread failed - error %d\n", (int)PR_GetError()); PR_ProcessExit(2); } if (_debug_on) { printf("%s: created thread = %p\n", argv[0], thread); } rc = PR_JoinThread(thread); PR_ASSERT(rc == PR_SUCCESS); PR_DestroyRWLock(rwlock0); rwlock0 = NULL; PR_DestroyRWLock(rwlock1); rwlock1 = NULL; PR_DestroyRWLock(rwlock2); rwlock2 = NULL; printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/rwlocktest.c0000644000000000000000000001124112623070344015661 0ustar 00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * * RWLock tests * * Several threads are created to access and modify data arrays using * PRRWLocks for synchronization. Two data arrays, array_A and array_B, are * initialized with random data and a third array, array_C, is initialized * with the sum of the first 2 arrays. * * Each one of the threads acquires a read lock to verify that the sum of * the arrays A and B is equal to array C, and acquires a write lock to * consistently update arrays A and B so that their is equal to array C. * */ #include "nspr.h" #include "plgetopt.h" #include "prrwlock.h" static int _debug_on; static void rwtest(void *args); static PRInt32 *array_A,*array_B,*array_C; static void update_array(void); static void check_array(void); typedef struct thread_args { PRRWLock *rwlock; PRInt32 loop_cnt; } thread_args; PRFileDesc *output; PRFileDesc *errhandle; #define DEFAULT_THREAD_CNT 4 #define DEFAULT_LOOP_CNT 100 #define TEST_ARRAY_SIZE 100 int main(int argc, char **argv) { PRInt32 cnt; PRStatus rc; PRInt32 i; PRInt32 thread_cnt = DEFAULT_THREAD_CNT; PRInt32 loop_cnt = DEFAULT_LOOP_CNT; PRThread **threads; thread_args *params; PRRWLock *rwlock1; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; case 't': /* thread count */ thread_cnt = atoi(opt->value); break; case 'c': /* loop count */ loop_cnt = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_SetConcurrency(4); output = PR_GetSpecialFD(PR_StandardOutput); errhandle = PR_GetSpecialFD(PR_StandardError); rwlock1 = PR_NewRWLock(0,"Lock 1"); if (rwlock1 == NULL) { PR_fprintf(errhandle, "PR_NewRWLock failed - error %d\n", PR_GetError()); return 1; } threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt); params = (thread_args *) PR_CALLOC(sizeof(thread_args) * thread_cnt); /* * allocate and initialize data arrays */ array_A =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE); array_B =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE); array_C =(PRInt32 *) PR_MALLOC(sizeof(PRInt32) * TEST_ARRAY_SIZE); cnt = 0; for (i=0; i < TEST_ARRAY_SIZE;i++) { array_A[i] = cnt++; array_B[i] = cnt++; array_C[i] = array_A[i] + array_B[i]; } if (_debug_on) PR_fprintf(output,"%s: thread_cnt = %d loop_cnt = %d\n", argv[0], thread_cnt, loop_cnt); for(cnt = 0; cnt < thread_cnt; cnt++) { PRThreadScope scope; params[cnt].rwlock = rwlock1; params[cnt].loop_cnt = loop_cnt; /* * create LOCAL and GLOBAL threads alternately */ if (cnt & 1) scope = PR_LOCAL_THREAD; else scope = PR_GLOBAL_THREAD; threads[cnt] = PR_CreateThread(PR_USER_THREAD, rwtest, ¶ms[cnt], PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (threads[cnt] == NULL) { PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n", PR_GetError()); PR_ProcessExit(2); } if (_debug_on) PR_fprintf(output,"%s: created thread = %p\n", argv[0], threads[cnt]); } for(cnt = 0; cnt < thread_cnt; cnt++) { rc = PR_JoinThread(threads[cnt]); PR_ASSERT(rc == PR_SUCCESS); } PR_DELETE(threads); PR_DELETE(params); PR_DELETE(array_A); PR_DELETE(array_B); PR_DELETE(array_C); PR_DestroyRWLock(rwlock1); printf("PASS\n"); return 0; } static void rwtest(void *args) { PRInt32 index; thread_args *arg = (thread_args *) args; for (index = 0; index < arg->loop_cnt; index++) { /* * verify sum, update arrays and verify sum again */ PR_RWLock_Rlock(arg->rwlock); check_array(); PR_RWLock_Unlock(arg->rwlock); PR_RWLock_Wlock(arg->rwlock); update_array(); PR_RWLock_Unlock(arg->rwlock); PR_RWLock_Rlock(arg->rwlock); check_array(); PR_RWLock_Unlock(arg->rwlock); } if (_debug_on) PR_fprintf(output, "Thread[0x%x] lock = 0x%x exiting\n", PR_GetCurrentThread(), arg->rwlock); } static void check_array(void) { PRInt32 i; for (i=0; i < TEST_ARRAY_SIZE;i++) if (array_C[i] != (array_A[i] + array_B[i])) { PR_fprintf(output, "Error - data check failed\n"); PR_ProcessExit(1); } } static void update_array(void) { PRInt32 i; for (i=0; i < TEST_ARRAY_SIZE;i++) { array_A[i] += i; array_B[i] -= i; } } nspr-4.11/nspr/pr/tests/sel_spd.c0000644000000000000000000003304712623070344015121 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test the speed of select within NSPR * */ #include "nspr.h" #include "prpriv.h" #include #include #include #include #ifdef SYMBIAN #include #endif #define PORT_BASE 19000 typedef struct timer_slot_t { unsigned long d_connect; unsigned long d_cl_data; unsigned long d_sv_data; unsigned long d_close; unsigned long d_total; unsigned long requests; } timer_slot_t; static long _iterations = 5; static long _client_data = 8192; #ifdef SYMBIAN /* * Symbian OS does not scale well specially the requirement for thread stack * space and buffer allocation space. It is easy to get into a fragmented * memory and not be able to allocate thread stack or client/server data * buffer. */ static long _server_data = (8*1024); static long _threads_max = 10, _threads = 10; #else static long _server_data = (128*1024); static long _threads_max = 10, _threads = 10; #endif static int verbose=0; static PRMonitor *exit_cv; static long _thread_exit_count; static timer_slot_t *timer_data; static PRThreadScope scope1, scope2; void tally_results(int); /* return the diff in microseconds */ unsigned long _delta(PRIntervalTime *start, PRIntervalTime *stop) { /* * Will C do the right thing with unsigned arithemtic? */ return PR_IntervalToMicroseconds(*stop - *start); } int _readn(PRFileDesc *sock, char *buf, int len) { int rem; int bytes; for (rem=len; rem; rem -= bytes) { bytes = PR_Recv(sock, buf+len-rem, rem, 0, PR_INTERVAL_NO_TIMEOUT); if (bytes <= 0) return -1; } return len; } void _thread_exit(int id) { PR_EnterMonitor(exit_cv); #ifdef DEBUG fprintf(stdout, "Thread %d EXIT\n", id); #endif _thread_exit_count--; if (_thread_exit_count == 0) { #ifdef DEBUG fprintf(stdout, "Thread %d EXIT triggered notify\n", id); #endif PR_Notify(exit_cv); } PR_ExitMonitor(exit_cv); } void _server_thread(void *arg_id) { void _client_thread(void *); PRThread *thread; int *id = (int *)arg_id; PRFileDesc *sock; PRSocketOptionData sockopt; PRNetAddr sa; PRFileDesc * newsock; char *data_buffer = NULL; int data_buffer_size; int index; PRIntervalTime start, connect_done, read_done, write_done, close_done; #ifdef DEBUG fprintf(stdout, "server thread %d alive\n", *id); #endif data_buffer_size = (_client_data>_server_data?_client_data:_server_data); if ( (data_buffer = (char *)PR_Malloc(data_buffer_size * sizeof(char))) == NULL ) { fprintf(stderr, "Error creating buffer in server thread %d\n", *id); goto done; } if ( (sock = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Error creating socket in server thread %d\n", *id); goto done; } sockopt.option = PR_SockOpt_Reuseaddr; sockopt.value.reuse_addr = PR_TRUE; if ( PR_SetSocketOption(sock, &sockopt) == PR_FAILURE) { fprintf(stderr, "Error setting socket option in server thread %d\n", *id); goto done; } memset(&sa, 0 , sizeof(sa)); sa.inet.family = PR_AF_INET; sa.inet.port = PR_htons(PORT_BASE + *id); sa.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(sock, &sa) < 0) { fprintf(stderr, "Error binding socket in server thread %d errno = %d\n", *id, errno); goto done; } if ( PR_Listen(sock, 32) < 0 ) { fprintf(stderr, "Error listening to socket in server thread %d\n", *id); goto done; } /* Tell the client to start */ if ( (thread = PR_CreateThread(PR_USER_THREAD, _client_thread, id, PR_PRIORITY_NORMAL, scope2, PR_UNJOINABLE_THREAD, 0)) == NULL) fprintf(stderr, "Error creating client thread %d\n", *id); for (index = 0; index< _iterations; index++) { #ifdef DEBUG fprintf(stdout, "server thread %d loop %d\n", *id, index); #endif start = PR_IntervalNow(); if ( (newsock = PR_Accept(sock, &sa, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr, "Error accepting connection %d in server thread %d\n", index, *id); goto done; } #ifdef DEBUG fprintf(stdout, "server thread %d got connection %d\n", *id, newsock); #endif connect_done = PR_IntervalNow(); if ( _readn(newsock, data_buffer, _client_data) < _client_data) { fprintf(stderr, "Error reading client data for iteration %d in server thread %d\n", index, *id ); goto done; } #ifdef DEBUG fprintf(stdout, "server thread %d read %d bytes\n", *id, _client_data); #endif read_done = PR_IntervalNow(); if ( PR_Send(newsock, data_buffer, _server_data, 0, PR_INTERVAL_NO_TIMEOUT) < _server_data) { fprintf(stderr, "Error sending client data for iteration %d in server thread %d\n", index, *id ); goto done; } #ifdef DEBUG fprintf(stdout, "server thread %d write %d bytes\n", *id, _server_data); #endif write_done = PR_IntervalNow(); PR_Close(newsock); close_done = PR_IntervalNow(); timer_data[2*(*id)].d_connect += _delta(&start, &connect_done); timer_data[2*(*id)].d_cl_data += _delta(&connect_done, &read_done); timer_data[2*(*id)].d_sv_data += _delta(&read_done, &write_done); timer_data[2*(*id)].d_close += _delta(&write_done, &close_done); timer_data[2*(*id)].d_total += _delta(&start, &close_done); timer_data[2*(*id)].requests++; #ifdef DEBUG fprintf(stdout, "server: %d %d %d %d %d\n", _delta(&start, &connect_done), _delta(&connect_done, &read_done), _delta(&read_done, &write_done), _delta(&write_done, &close_done), _delta(&start, &close_done)); #endif } done: if (data_buffer != NULL) PR_Free (data_buffer); if (sock) PR_Close(sock); _thread_exit(*id); return; } void _client_thread(void *arg_id) { int *id = (int *)arg_id; int index; PRNetAddr sa; PRFileDesc *sock_h; char *data_buffer = NULL; int data_buffer_size; int bytes; PRIntervalTime start, connect_done, read_done, write_done, close_done; PRStatus rv; #ifdef DEBUG fprintf(stdout, "client thread %d alive\n", *id); #endif data_buffer_size = (_client_data>_server_data?_client_data:_server_data); if ( (data_buffer = (char *)PR_Malloc(data_buffer_size * sizeof(char))) == NULL) { fprintf(stderr, "Error creating buffer in server thread %d\n", *id); goto done; } memset(&sa, 0 , sizeof(sa)); rv = PR_InitializeNetAddr(PR_IpAddrLoopback, PORT_BASE + *id, &sa); PR_ASSERT(PR_SUCCESS == rv); for (index = 0; index< _iterations; index++) { #ifdef DEBUG fprintf(stdout, "client thread %d loop %d\n", *id, index); #endif start = PR_IntervalNow(); if ( (sock_h = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Error creating socket %d in client thread %d\n", index, *id); goto done; } #ifdef DEBUG fprintf(stdout, "client thread %d socket created %d\n", *id, sock_h); #endif if ( PR_Connect(sock_h, &sa, PR_INTERVAL_NO_TIMEOUT) < 0) { fprintf(stderr, "Error accepting connection %d in client thread %d\n", index, *id); goto done; } #ifdef DEBUG fprintf(stdout, "client thread %d socket connected %d\n", *id, sock_h); #endif connect_done = PR_IntervalNow(); if ( PR_Send(sock_h, data_buffer, _client_data, 0, PR_INTERVAL_NO_TIMEOUT) < _client_data) { fprintf(stderr, "Error sending client data for iteration %d in client thread %d\n", index, *id ); goto done; } #ifdef DEBUG fprintf(stdout, "client thread %d socket wrote %d\n", *id, _client_data); #endif write_done = PR_IntervalNow(); if ( (bytes = _readn(sock_h, data_buffer, _server_data)) < _server_data) { fprintf(stderr, "Error reading server data for iteration %d in client thread %d (read %d bytes)\n", index, *id, bytes ); goto done; } #ifdef DEBUG fprintf(stdout, "client thread %d socket read %d\n", *id, _server_data); #endif read_done = PR_IntervalNow(); PR_Close(sock_h); close_done = PR_IntervalNow(); timer_data[2*(*id)+1].d_connect += _delta(&start, &connect_done); timer_data[2*(*id)+1].d_cl_data += _delta(&connect_done, &write_done); timer_data[2*(*id)+1].d_sv_data += _delta(&write_done, &read_done); timer_data[2*(*id)+1].d_close += _delta(&read_done, &close_done); timer_data[2*(*id)+1].d_total += _delta(&start, &close_done); timer_data[2*(*id)+1].requests++; } done: if (data_buffer != NULL) PR_Free (data_buffer); _thread_exit(*id); return; } static void do_work(void) { int index; _thread_exit_count = _threads * 2; for (index=0; index<_threads; index++) { PRThread *thread; int *id = (int *)PR_Malloc(sizeof(int)); *id = index; if ( (thread = PR_CreateThread(PR_USER_THREAD, _server_thread, id, PR_PRIORITY_NORMAL, scope1, PR_UNJOINABLE_THREAD, 0)) == NULL) fprintf(stderr, "Error creating server thread %d\n", index); } PR_EnterMonitor(exit_cv); while (_thread_exit_count > 0) PR_Wait(exit_cv, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(exit_cv); fprintf(stdout, "TEST COMPLETE!\n"); tally_results(verbose); } static void do_workUU(void) { scope1 = PR_LOCAL_THREAD; scope2 = PR_LOCAL_THREAD; do_work(); } static void do_workUK(void) { scope1 = PR_LOCAL_THREAD; scope2 = PR_GLOBAL_THREAD; do_work(); } static void do_workKU(void) { scope1 = PR_GLOBAL_THREAD; scope2 = PR_LOCAL_THREAD; do_work(); } static void do_workKK(void) { scope1 = PR_GLOBAL_THREAD; scope2 = PR_GLOBAL_THREAD; do_work(); } static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); printf("%40s: %6.2f usec\n", msg, d / _iterations); } int main(int argc, char **argv) { #if defined(XP_UNIX) || defined(XP_OS2) int opt; PR_IMPORT_DATA(char *) optarg; #endif #if defined(XP_UNIX) || defined(XP_OS2) while ( (opt = getopt(argc, argv, "c:s:i:t:v")) != EOF) { switch(opt) { case 'i': _iterations = atoi(optarg); break; case 't': _threads_max = _threads = atoi(optarg); break; case 'c': _client_data = atoi(optarg); break; case 's': _server_data = atoi(optarg); break; case 'v': verbose = 1; break; default: break; } } #endif PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); fprintf(stdout, "Running test for %d iterations with %d simultaneous threads.\n", _iterations, _threads); fprintf(stdout, "\tWill send %d bytes of client data and %d bytes of server data\n", _client_data, _server_data); if ( (exit_cv = PR_NewMonitor()) == NULL) fprintf(stderr, "Error creating monitor for exit cv\n"); if ( (timer_data = (timer_slot_t *)PR_Malloc(2*_threads * sizeof(timer_slot_t))) == NULL) fprintf(stderr, "error allocating thread time results array\n"); memset(timer_data, 0 , 2*_threads*sizeof(timer_slot_t)); Measure(do_workUU, "select loop user/user"); Measure(do_workUK, "select loop user/kernel"); Measure(do_workKU, "select loop kernel/user"); Measure(do_workKK, "select loop kernel/kernel"); return 0; } void tally_results(int verbose) { int index; unsigned long tot_connect = 0; unsigned long tot_cl_data = 0; unsigned long tot_sv_data = 0; unsigned long tot_close = 0; unsigned long tot_all = 0; unsigned long tot_requests = 0; fprintf(stdout, "Server results:\n\n"); for (index=0; index<_threads_max*2; index+=2) { if (verbose) fprintf(stdout, "server thread %u\t%u\t%u\t%u\t%u\t%u\t%u\n", index, timer_data[index].requests, timer_data[index].d_connect, timer_data[index].d_cl_data, timer_data[index].d_sv_data, timer_data[index].d_close, timer_data[index].d_total); tot_connect += timer_data[index].d_connect / _threads; tot_cl_data += timer_data[index].d_cl_data / _threads; tot_sv_data += timer_data[index].d_sv_data / _threads; tot_close += timer_data[index].d_close / _threads; tot_all += timer_data[index].d_total / _threads; tot_requests += timer_data[index].requests / _threads; } fprintf(stdout, "----------\n"); fprintf(stdout, "server per thread totals %u\t%u\t%u\t%u\t%u\n", tot_requests, tot_connect, tot_cl_data, tot_sv_data, tot_close); fprintf(stdout, "server per thread elapsed time %u\n", tot_all); fprintf(stdout, "----------\n"); tot_connect = tot_cl_data = tot_sv_data = tot_close = tot_all = tot_requests = 0; fprintf(stdout, "Client results:\n\n"); for (index=1; index<_threads_max*2; index+=2) { if (verbose) fprintf(stdout, "client thread %u\t%u\t%u\t%u\t%u\t%u\t%u\n", index, timer_data[index].requests, timer_data[index].d_connect, timer_data[index].d_cl_data, timer_data[index].d_sv_data, timer_data[index].d_close, timer_data[index].d_total); tot_connect += timer_data[index].d_connect / _threads; tot_cl_data += timer_data[index].d_cl_data / _threads; tot_sv_data += timer_data[index].d_sv_data / _threads; tot_close += timer_data[index].d_close / _threads; tot_all += timer_data[index].d_total / _threads; tot_requests += timer_data[index].requests / _threads; } fprintf(stdout, "----------\n"); fprintf(stdout, "client per thread totals %u\t%u\t%u\t%u\t%u\n", tot_requests, tot_connect, tot_cl_data, tot_sv_data, tot_close); fprintf(stdout, "client per thread elapsed time %u\n", tot_all); } nspr-4.11/nspr/pr/tests/selct_er.c0000755000000000000000000001315212623070344015266 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1997 - Netscape Communications Corporation ** ** Name: prselect_err.c ** ** Description: tests PR_Select with sockets Error condition functions. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ #ifdef XP_BEOS #include int main() { printf( "This test is not ported to the BeOS\n" ); return 0; } #else /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "primpl.h" #include "pprio.h" #include "prnetdb.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *badFD; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. Error\n"); printf("reporting operations are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = AF_INET; addr.inet.ip = PR_htonl(INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* Testing bad fd */ if (debug_mode) printf("PR_Select should detect a bad file descriptor\n"); if ((badFD = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a TCP socket\n"); failed_already=1; goto exit_now; } PR_FD_SET(badFD, &readFdSet); /* * Make the fd invalid */ #if defined(XP_UNIX) close(PR_FileDesc2NativeHandle(badFD)); #elif defined(XP_OS2) soclose(PR_FileDesc2NativeHandle(badFD)); #elif defined(WIN32) || defined(WIN16) closesocket(PR_FileDesc2NativeHandle(badFD)); #else #error "Unknown architecture" #endif retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); if (retVal != -1 || PR_GetError() != PR_BAD_DESCRIPTOR_ERROR) { fprintf(stderr, "Failed to detect the bad fd: " "PR_Select returns %d\n", retVal); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); failed_already=1; } goto exit_now; } if (debug_mode) printf("PR_Select detected a bad fd. Test passed.\n\n"); PR_FD_CLR(badFD, &readFdSet); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; } #endif /* XP_BEOS */ nspr-4.11/nspr/pr/tests/selct_nm.c0000644000000000000000000001726412623070344015277 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1997 - Netscape Communications Corporation ** ** Name: prselect_norm.c ** ** Description: tests PR_Select with sockets - Normal operations. ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prio.h" #include "prlog.h" #include "prprf.h" #include "prerror.h" #include "prnetdb.h" #include "obsolete/probslet.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; static void clientThreadFunc(void *arg) { PRUintn port = (PRUintn) arg; PRFileDesc *sock; PRNetAddr addr; char buf[128]; int i; addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons((PRUint16)port); addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); PR_snprintf(buf, sizeof(buf), "%hu", addr.inet.port); for (i = 0; i < 5; i++) { sock = PR_NewTCPSocket(); PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT); PR_Write(sock, buf, sizeof(buf)); PR_Close(sock); } } int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRFileDesc *fds0[10], *fds1[10], **fds, **other_fds; PRIntn nfds; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRThread *clientThread; PRInt32 retVal; PRIntn i, j; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. \n"); printf(" Normal operation are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort1, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } clientThread = PR_CreateThread(PR_USER_THREAD, clientThreadFunc, (void *) listenPort2, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (clientThread == NULL) { fprintf(stderr, "can't create thread\n"); failed_already=1; goto exit_now; } if (debug_mode) { printf("Two client threads are created. Each of them will\n"); printf("send data to one of the two ports the server is listening on.\n"); printf("The data they send is the port number. Each of them send\n"); printf("the data five times, so you should see ten lines below,\n"); printf("interleaved in an arbitrary order.\n"); } /* set up the fd array */ fds = fds0; other_fds = fds1; fds[0] = listenSock1; fds[1] = listenSock2; nfds = 2; /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* 20 events total */ i = 0; while (i < 20) { PRFileDesc **tmp; int nextIndex; int nEvents = 0; retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(retVal != 0); /* no timeout */ if (retVal == -1) { fprintf(stderr, "PR_Select failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); failed_already=1; goto exit_now; } nextIndex = 2; /* the two listening sockets */ for (j = 0; j < 2; j++) { other_fds[j] = fds[j]; if (PR_FD_ISSET(fds[j], &readFdSet)) { PRFileDesc *sock; nEvents++; sock = PR_Accept(fds[j], NULL, PR_INTERVAL_NO_TIMEOUT); if (sock == NULL) { fprintf(stderr, "PR_Accept() failed\n"); failed_already=1; goto exit_now; } other_fds[nextIndex] = sock; PR_FD_SET(sock, &readFdSet); nextIndex++; } PR_FD_SET(fds[j], &readFdSet); } for (j = 2; j < nfds; j++) { if (PR_FD_ISSET(fds[j], &readFdSet)) { PRInt32 nBytes; PR_FD_CLR(fds[j], &readFdSet); nEvents++; nBytes = PR_Read(fds[j], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read() failed\n"); failed_already=1; goto exit_now; } /* Just to be safe */ buf[127] = '\0'; PR_Close(fds[j]); if (debug_mode) printf("The server received \"%s\" from a client\n", buf); } else { PR_FD_SET(fds[j], &readFdSet); other_fds[nextIndex] = fds[j]; nextIndex++; } } PR_ASSERT(retVal == nEvents); /* swap */ tmp = fds; fds = other_fds; other_fds = tmp; nfds = nextIndex; i += nEvents; } if (debug_mode) printf("Test passed\n"); PR_Cleanup(); goto exit_now; exit_now: if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/selct_to.c0000644000000000000000000001200412623070344015272 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** 1997 - Netscape Communications Corporation ** ** Name: prselect_to.c ** ** Description: tests PR_Select with sockets. Time out functions ** ** Modification History: ** 14-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prio.h" #include "prlog.h" #include "prprf.h" #include "prnetdb.h" #include "obsolete/probslet.h" #include "prerror.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; int main(int argc, char **argv) { PRFileDesc *listenSock1, *listenSock2; PRUint16 listenPort1, listenPort2; PRNetAddr addr; PR_fd_set readFdSet; char buf[128]; PRInt32 retVal; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (debug_mode) { printf("This program tests PR_Select with sockets. Timeout \n"); printf("operations are tested.\n\n"); } /* Create two listening sockets */ if ((listenSock1 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock1, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort1 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock1, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } if ((listenSock2 = PR_NewTCPSocket()) == NULL) { fprintf(stderr, "Can't create a new TCP socket\n"); failed_already=1; goto exit_now; } addr.inet.family = PR_AF_INET; addr.inet.ip = PR_htonl(PR_INADDR_ANY); addr.inet.port = PR_htons(0); if (PR_Bind(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "Can't bind socket\n"); failed_already=1; goto exit_now; } if (PR_GetSockName(listenSock2, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); failed_already=1; goto exit_now; } listenPort2 = PR_ntohs(addr.inet.port); if (PR_Listen(listenSock2, 5) == PR_FAILURE) { fprintf(stderr, "Can't listen on a socket\n"); failed_already=1; goto exit_now; } PR_snprintf(buf, sizeof(buf), "The server thread is listening on ports %hu and %hu\n\n", listenPort1, listenPort2); if (debug_mode) printf("%s", buf); /* Set up the fd set */ PR_FD_ZERO(&readFdSet); PR_FD_SET(listenSock1, &readFdSet); PR_FD_SET(listenSock2, &readFdSet); /* Testing timeout */ if (debug_mode) printf("PR_Select should time out in 5 seconds\n"); retVal = PR_Select(0 /* unused */, &readFdSet, NULL, NULL, PR_SecondsToInterval(5)); if (retVal != 0) { PR_snprintf(buf, sizeof(buf), "PR_Select should time out and return 0, but it returns %ld\n", retVal); fprintf(stderr, "%s", buf); if (retVal == -1) { fprintf(stderr, "Error %d, oserror %d\n", PR_GetError(), PR_GetOSError()); failed_already=1; } goto exit_now; } if (debug_mode) printf("PR_Select timed out. Test passed.\n\n"); PR_Cleanup(); exit_now: if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/select2.c0000644000000000000000000002104512623070344015024 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: select2.c ** ** Description: Measure PR_Select and Empty_Select performance. ** ** Modification History: ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prttools.h" #include "primpl.h" #include #include #include #if defined(OS2) #include #endif #define PORT 8000 #define DEFAULT_COUNT 10 PRInt32 count; /*********************************************************************** ** PRIVATE FUNCTION: Test_Result ** DESCRIPTION: Used in conjunction with the regress tool, prints out the ** status of the test case. ** INPUTS: PASS/FAIL ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: Determine what the status is and print accordingly. ** ***********************************************************************/ static void Test_Result (int result) { switch (result) { case PASS: printf ("PASS\n"); break; case FAIL: printf ("FAIL\n"); break; default: printf ("NOSTATUS\n"); break; } } static void EmptyPRSelect(void) { PRInt32 index = count; PRInt32 rv; for (; index--;) rv = PR_Select(0, NULL, NULL, NULL, PR_INTERVAL_NO_WAIT); } static void EmptyNativeSelect(void) { PRInt32 rv; PRInt32 index = count; struct timeval timeout; timeout.tv_sec = timeout.tv_usec = 0; for (; index--;) rv = select(0, NULL, NULL, NULL, &timeout); } static void PRSelectTest(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); return; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address\n"); PR_Close(listenSocket); return; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); PR_Close(listenSocket); return; } if (debug_mode) printf("Listening on port %d\n", PORT); { PRFileDesc *newSock; PRNetAddr rAddr; PRInt32 loops = 0; PR_fd_set rdset; PRInt32 rv; PRInt32 bytesRead; char buf[11]; loops++; if (debug_mode) printf("Going into accept\n"); newSock = PR_Accept(listenSocket, &rAddr, PR_INTERVAL_NO_TIMEOUT); if (newSock) { if (debug_mode) printf("Got connection!\n"); } else { if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError()); else Test_Result (FAIL); } PR_FD_ZERO(&rdset); PR_FD_SET(newSock, &rdset); if (debug_mode) printf("Going into select \n"); rv = PR_Select(0, &rdset, 0, 0, PR_INTERVAL_NO_TIMEOUT); if (debug_mode) printf("return from select is %d\n", rv); if (PR_FD_ISSET(newSock, &rdset)) { if (debug_mode) printf("I can't believe it- the socket is ready okay!\n"); } else { if (debug_mode) printf("Damn; the select test failed...\n"); else Test_Result (FAIL); } strcpy(buf, "XXXXXXXXXX"); bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT); buf[10] = '\0'; if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf); PR_Close(newSock); } } #if defined(XP_UNIX) static void NativeSelectTest(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); return; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address\n"); PR_Close(listenSocket); return; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); PR_Close(listenSocket); return; } if (debug_mode) printf("Listening on port %d\n", PORT); { PRIntn osfd; char buf[11]; fd_set rdset; PRNetAddr rAddr; PRFileDesc *newSock; struct timeval timeout; PRInt32 bytesRead, rv, loops = 0; loops++; if (debug_mode) printf("Going into accept\n"); newSock = PR_Accept(listenSocket, &rAddr, PR_INTERVAL_NO_TIMEOUT); if (newSock) { if (debug_mode) printf("Got connection!\n"); } else { if (debug_mode) printf("PR_Accept failed: error code %d\n", PR_GetError()); else Test_Result (FAIL); } osfd = PR_FileDesc2NativeHandle(newSock); FD_ZERO(&rdset); FD_SET(osfd, &rdset); if (debug_mode) printf("Going into select \n"); timeout.tv_sec = 2; timeout.tv_usec = 0; rv = select(osfd + 1, &rdset, NULL, NULL, &timeout); if (debug_mode) printf("return from select is %d\n", rv); if (FD_ISSET(osfd, &rdset)) { if (debug_mode) printf("I can't believe it- the socket is ready okay!\n"); } else { if (debug_mode) printf("Damn; the select test failed...\n"); else Test_Result (FAIL); } strcpy(buf, "XXXXXXXXXX"); bytesRead = PR_Recv(newSock, buf, 10, 0, PR_INTERVAL_NO_TIMEOUT); buf[10] = '\0'; if (debug_mode) printf("Recv completed with %d bytes, %s\n", bytesRead, buf); PR_Close(newSock); } } /* NativeSelectTest */ #endif /* defined(XP_UNIX) */ /************************************************************************/ static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; PRInt32 tot; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); tot = PR_IntervalToMilliseconds(stop-start); if (debug_mode) printf("%40s: %6.2f usec avg, %d msec total\n", msg, d / count, tot); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (argc > 2) { count = atoi(argv[2]); } else { count = DEFAULT_COUNT; } #if defined(XP_UNIX) Measure(NativeSelectTest, "time to call 1 element select()"); #endif Measure(EmptyPRSelect, "time to call Empty PR_select()"); Measure(EmptyNativeSelect, "time to call Empty select()"); Measure(PRSelectTest, "time to call 1 element PR_select()"); if (!debug_mode) Test_Result (NOSTATUS); PR_Cleanup(); } nspr-4.11/nspr/pr/tests/selintr.c0000644000000000000000000000236212623070344015144 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test whether classic NSPR's select() wrapper properly blocks * the periodic SIGALRM clocks. On some platforms (such as * HP-UX and SINIX) an interrupted select() system call is * restarted with the originally specified timeout, ignoring * the time that has elapsed. If a select() call is interrupted * repeatedly, it will never time out. (See Bugzilla bug #39674.) */ #if !defined(XP_UNIX) /* * This test is applicable to Unix only. */ int main() { return 0; } #else /* XP_UNIX */ #include "nspr.h" #include #include #ifdef SYMBIAN #include #endif int main(int argc, char **argv) { struct timeval timeout; int rv; PR_SetError(0, 0); /* force NSPR to initialize */ PR_EnableClockInterrupts(); /* 2 seconds timeout */ timeout.tv_sec = 2; timeout.tv_usec = 0; rv = select(1, NULL, NULL, NULL, &timeout); printf("select returned %d\n", rv); return 0; } #endif /* XP_UNIX */ nspr-4.11/nspr/pr/tests/sem.c0000644000000000000000000001221712623070344014250 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: sem.c ** ** Description: Tests Semaphonre functions. ** ** Modification History: ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "prpriv.h" #include #include #include PRIntn failed_already=0; PRIntn debug_mode; /* Since we don't have stdin, stdout everywhere, we will fake it with our in-memory buffers called stdin and stdout. */ #define SBSIZE 1024 #include "obsolete/prsem.h" static char stdinBuf[SBSIZE]; static char stdoutBuf[SBSIZE]; static PRUintn stdinBufIdx = 0; static PRUintn stdoutBufIdx = 0; static PRStatus finalResult = PR_SUCCESS; static size_t dread (PRUintn device, char *buf, size_t bufSize) { PRUintn i; /* during first read call, initialize the stdinBuf buffer*/ if (stdinBufIdx == 0) { for (i=0; i 0); } static void writer(void) { PRUintn i = 0; size_t nbytes; do { (void) PR_WaitSem(fullBufs); nbytes = buf[i].nbytes; if (nbytes > 0) { nbytes = dwrite(1, buf[i].data, nbytes); PR_PostSem(emptyBufs); i = (i + 1) % 2; } } while (nbytes > 0); } int main(int argc, char **argv) { PRThread *r; PR_STDIO_INIT(); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); } /* main test */ emptyBufs = PR_NewSem(2); /* two empty buffers */ fullBufs = PR_NewSem(0); /* zero full buffers */ /* create the reader thread */ r = PR_CreateThread(PR_USER_THREAD, reader, 0, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); /* Do the writer operation in this thread */ writer(); PR_DestroySem(emptyBufs); PR_DestroySem(fullBufs); if (finalResult == PR_SUCCESS) { if (debug_mode) printf("sem Test Passed.\n"); } else{ if (debug_mode) printf("sem Test Failed.\n"); failed_already=1; } PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/sema.c0000644000000000000000000001064512623070344014414 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #define SEM_NAME1 "/tmp/foo.sem" #define SEM_NAME2 "/tmp/bar.sem" #define SEM_MODE 0666 #define ITERATIONS 1000 static PRBool debug_mode = PR_FALSE; static PRIntn iterations = ITERATIONS; static PRIntn counter; static PRSem *sem1, *sem2; /* * Thread 2 waits on semaphore 2 and posts to semaphore 1. */ void ThreadFunc(void *arg) { PRIntn i; for (i = 0; i < iterations; i++) { if (PR_WaitSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_WaitSemaphore failed\n"); exit(1); } if (counter == 2*i+1) { if (debug_mode) printf("thread 2: counter = %d\n", counter); } else { fprintf(stderr, "thread 2: counter should be %d but is %d\n", 2*i+1, counter); exit(1); } counter++; if (PR_PostSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_PostSemaphore failed\n"); exit(1); } } } static void Help(void) { fprintf(stderr, "sema test program usage:\n"); fprintf(stderr, "\t-d debug mode (FALSE)\n"); fprintf(stderr, "\t-c loop count (%d)\n", ITERATIONS); fprintf(stderr, "\t-h this message\n"); } /* Help */ int main(int argc, char **argv) { PRThread *thred; PRIntn i; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop count */ iterations = atoi(opt->value); break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) { fprintf(stderr, "warning: removed semaphore %s left over " "from previous run\n", SEM_NAME1); } if (PR_DeleteSemaphore(SEM_NAME2) == PR_SUCCESS) { fprintf(stderr, "warning: removed semaphore %s left over " "from previous run\n", SEM_NAME2); } sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 1); if (NULL == sem1) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0); if (NULL == sem2) { fprintf(stderr, "PR_OpenSemaphore failed\n"); exit(1); } thred = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == thred) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } /* * Thread 1 waits on semaphore 1 and posts to semaphore 2. */ for (i = 0; i < iterations; i++) { if (PR_WaitSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_WaitSemaphore failed\n"); exit(1); } if (counter == 2*i) { if (debug_mode) printf("thread 1: counter = %d\n", counter); } else { fprintf(stderr, "thread 1: counter should be %d but is %d\n", 2*i, counter); exit(1); } counter++; if (PR_PostSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_PostSemaphore failed\n"); exit(1); } } if (PR_JoinThread(thred) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } if (PR_CloseSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); } if (PR_CloseSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); } if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSemaphore failed\n"); } if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSemaphore failed\n"); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/semaerr.c0000644000000000000000000000670412623070344015126 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #ifdef SYMBIAN #define NO_SUCH_SEM_NAME "c:\\data\\nosuchsem.sem" #define SEM_NAME1 "c:\\data\\foo.sem" #define EXE_NAME "nspr_tests_semaerr1.exe" #else #define NO_SUCH_SEM_NAME "/tmp/nosuchsem.sem" #define SEM_NAME1 "/tmp/foo.sem" #define EXE_NAME "semaerr1" #endif #define SEM_MODE 0666 static PRBool debug_mode = PR_FALSE; static void Help(void) { fprintf(stderr, "semaerr test program usage:\n"); fprintf(stderr, "\t-d debug mode (FALSE)\n"); fprintf(stderr, "\t-h this message\n"); } /* Help */ int main(int argc, char **argv) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dh"); PRSem *sem; char *child_argv[32]; char **child_arg; PRProcess *proc; PRInt32 exit_code; while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); /* * Open a nonexistent semaphore without the PR_SEM_CREATE * flag should fail with PR_FILE_NOT_FOUND_ERROR. */ (void) PR_DeleteSemaphore(NO_SUCH_SEM_NAME); sem = PR_OpenSemaphore(NO_SUCH_SEM_NAME, 0, 0, 0); if (NULL != sem) { fprintf(stderr, "Opening nonexistent semaphore %s " "without the PR_SEM_CREATE flag should fail " "but succeeded\n", NO_SUCH_SEM_NAME); exit(1); } if (PR_GetError() != PR_FILE_NOT_FOUND_ERROR) { fprintf(stderr, "Expected error is %d but got (%d, %d)\n", PR_FILE_NOT_FOUND_ERROR, PR_GetError(), PR_GetOSError()); exit(1); } /* * Create a semaphore and let the another process * try PR_SEM_CREATE and PR_SEM_CREATE|PR_SEM_EXCL. */ if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) { fprintf(stderr, "warning: deleted semaphore %s from previous " "run of the test\n", SEM_NAME1); } sem = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0); if (sem == NULL) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } child_arg = child_argv; *child_arg++ = EXE_NAME; if (debug_mode) { *child_arg++ = "-d"; } *child_arg = NULL; proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); if (proc == NULL) { fprintf(stderr, "PR_CreateProcess failed\n"); exit(1); } if (PR_WaitProcess(proc, &exit_code) == PR_FAILURE) { fprintf(stderr, "PR_WaitProcess failed\n"); exit(1); } if (exit_code != 0) { fprintf(stderr, "process semaerr1 failed\n"); exit(1); } if (PR_CloseSemaphore(sem) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); exit(1); } if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSemaphore failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/semaerr1.c0000644000000000000000000000622312623070344015203 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #ifdef SYMBIAN #define SEM_NAME1 "c:\\data\\foo.sem" #define SEM_NAME2 "c:\\data\\bar.sem" #else #define SEM_NAME1 "/tmp/foo.sem" #define SEM_NAME2 "/tmp/bar.sem" #endif #define SEM_MODE 0666 static PRBool debug_mode = PR_FALSE; static void Help(void) { fprintf(stderr, "semaerr1 test program usage:\n"); fprintf(stderr, "\t-d debug mode (FALSE)\n"); fprintf(stderr, "\t-h this message\n"); } /* Help */ int main(int argc, char **argv) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dh"); PRSem *sem; while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); /* * PR_SEM_CREATE|PR_SEM_EXCL should be able to * create a nonexistent semaphore. */ (void) PR_DeleteSemaphore(SEM_NAME2); sem = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE|PR_SEM_EXCL, SEM_MODE, 0); if (sem == NULL) { fprintf(stderr, "PR_OpenSemaphore failed\n"); exit(1); } if (PR_CloseSemaphore(sem) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); exit(1); } if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSemaphore failed\n"); exit(1); } /* * Opening an existing semaphore with PR_SEM_CREATE|PR_SEM_EXCL. * should fail with PR_FILE_EXISTS_ERROR. */ sem = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE|PR_SEM_EXCL, SEM_MODE, 0); if (sem != NULL) { fprintf(stderr, "PR_OpenSemaphore should fail but succeeded\n"); exit(1); } if (PR_GetError() != PR_FILE_EXISTS_ERROR) { fprintf(stderr, "Expect %d but got %d\n", PR_FILE_EXISTS_ERROR, PR_GetError()); exit(1); } /* * Try again, with just PR_SEM_CREATE. This should succeed. */ sem = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 0); if (sem == NULL) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } if (PR_CloseSemaphore(sem) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); exit(1); } sem = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE|PR_SEM_EXCL, SEM_MODE, 0); if (sem == NULL) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } if (PR_CloseSemaphore(sem) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/semaping.c0000644000000000000000000001312212623070344015263 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #ifdef SYMBIAN #define SHM_NAME "c:\\data\\counter" #define SEM_NAME1 "c:\\data\\foo.sem" #define SEM_NAME2 "c:\\data\\bar.sem" #define EXE_NAME "nspr_tests_semapong.exe" #else #define SHM_NAME "/tmp/counter" #define SEM_NAME1 "/tmp/foo.sem" #define SEM_NAME2 "/tmp/bar.sem" #define EXE_NAME "semapong" #endif #define SEM_MODE 0666 #define SHM_MODE 0666 #define ITERATIONS 1000 static PRBool debug_mode = PR_FALSE; static PRIntn iterations = ITERATIONS; static PRSem *sem1, *sem2; static void Help(void) { fprintf(stderr, "semaping test program usage:\n"); fprintf(stderr, "\t-d debug mode (FALSE)\n"); fprintf(stderr, "\t-c loop count (%d)\n", ITERATIONS); fprintf(stderr, "\t-h this message\n"); } /* Help */ int main(int argc, char **argv) { PRProcess *proc; PRIntn i; char *child_argv[32]; char **child_arg; char iterations_buf[32]; PRSharedMemory *shm; PRIntn *counter_addr; PRInt32 exit_code; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop count */ iterations = atoi(opt->value); break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); if (PR_DeleteSharedMemory(SHM_NAME) == PR_SUCCESS) { fprintf(stderr, "warning: removed shared memory %s left over " "from previous run\n", SHM_NAME); } if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) { fprintf(stderr, "warning: removed semaphore %s left over " "from previous run\n", SEM_NAME1); } if (PR_DeleteSemaphore(SEM_NAME2) == PR_SUCCESS) { fprintf(stderr, "warning: removed semaphore %s left over " "from previous run\n", SEM_NAME2); } shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), PR_SHM_CREATE, SHM_MODE); if (NULL == shm) { fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } counter_addr = PR_AttachSharedMemory(shm, 0); if (NULL == counter_addr) { fprintf(stderr, "PR_AttachSharedMemory failed\n"); exit(1); } *counter_addr = 0; sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 1); if (NULL == sem1) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0); if (NULL == sem2) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } child_arg = &child_argv[0]; *child_arg++ = EXE_NAME; if (debug_mode != PR_FALSE) { *child_arg++ = "-d"; } if (iterations != ITERATIONS) { *child_arg++ = "-c"; PR_snprintf(iterations_buf, sizeof(iterations_buf), "%d", iterations); *child_arg++ = iterations_buf; } *child_arg = NULL; proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL); if (NULL == proc) { fprintf(stderr, "PR_CreateProcess failed\n"); exit(1); } /* * Process 1 waits on semaphore 1 and posts to semaphore 2. */ for (i = 0; i < iterations; i++) { if (PR_WaitSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_WaitSemaphore failed\n"); exit(1); } if (*counter_addr == 2*i) { if (debug_mode) printf("process 1: counter = %d\n", *counter_addr); } else { fprintf(stderr, "process 1: counter should be %d but is %d\n", 2*i, *counter_addr); exit(1); } (*counter_addr)++; if (PR_PostSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_PostSemaphore failed\n"); exit(1); } } if (PR_DetachSharedMemory(shm, counter_addr) == PR_FAILURE) { fprintf(stderr, "PR_DetachSharedMemory failed\n"); exit(1); } if (PR_CloseSharedMemory(shm) == PR_FAILURE) { fprintf(stderr, "PR_CloseSharedMemory failed\n"); exit(1); } if (PR_CloseSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); } if (PR_CloseSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); } if (PR_WaitProcess(proc, &exit_code) == PR_FAILURE) { fprintf(stderr, "PR_WaitProcess failed\n"); exit(1); } if (exit_code != 0) { fprintf(stderr, "process 2 failed with exit code %d\n", exit_code); exit(1); } if (PR_DeleteSharedMemory(SHM_NAME) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSharedMemory failed\n"); } if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSemaphore failed\n"); } if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) { fprintf(stderr, "PR_DeleteSemaphore failed\n"); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/semapong.c0000644000000000000000000000722512623070344015300 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #ifdef SYMBIAN #define SHM_NAME "c:\\data\\counter" #define SEM_NAME1 "c:\\data\\foo.sem" #define SEM_NAME2 "c:\\data\\bar.sem" #else #define SHM_NAME "/tmp/counter" #define SEM_NAME1 "/tmp/foo.sem" #define SEM_NAME2 "/tmp/bar.sem" #endif #define ITERATIONS 1000 static PRBool debug_mode = PR_FALSE; static PRIntn iterations = ITERATIONS; static PRSem *sem1, *sem2; static void Help(void) { fprintf(stderr, "semapong test program usage:\n"); fprintf(stderr, "\t-d debug mode (FALSE)\n"); fprintf(stderr, "\t-c loop count (%d)\n", ITERATIONS); fprintf(stderr, "\t-h this message\n"); } /* Help */ int main(int argc, char **argv) { PRIntn i; PRSharedMemory *shm; PRIntn *counter_addr; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop count */ iterations = atoi(opt->value); break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), 0, 0666); if (NULL == shm) { fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } sem1 = PR_OpenSemaphore(SEM_NAME1, 0, 0, 0); if (NULL == sem1) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } sem2 = PR_OpenSemaphore(SEM_NAME2, 0, 0, 0); if (NULL == sem2) { fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } counter_addr = PR_AttachSharedMemory(shm, 0); if (NULL == counter_addr) { fprintf(stderr, "PR_AttachSharedMemory failed\n"); exit(1); } /* * Process 2 waits on semaphore 2 and posts to semaphore 1. */ for (i = 0; i < iterations; i++) { if (PR_WaitSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_WaitSemaphore failed\n"); exit(1); } if (*counter_addr == 2*i+1) { if (debug_mode) printf("process 2: counter = %d\n", *counter_addr); } else { fprintf(stderr, "process 2: counter should be %d but is %d\n", 2*i+1, *counter_addr); exit(1); } (*counter_addr)++; if (PR_PostSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_PostSemaphore failed\n"); exit(1); } } if (PR_DetachSharedMemory(shm, counter_addr) == PR_FAILURE) { fprintf(stderr, "PR_DetachSharedMemory failed\n"); exit(1); } if (PR_CloseSharedMemory(shm) == PR_FAILURE) { fprintf(stderr, "PR_CloseSharedMemory failed\n"); exit(1); } if (PR_CloseSemaphore(sem1) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); } if (PR_CloseSemaphore(sem2) == PR_FAILURE) { fprintf(stderr, "PR_CloseSemaphore failed\n"); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/sendzlf.c0000644000000000000000000001472112623070344015133 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test: sendzlf.c * * Description: send a zero-length file with PR_SendFile and * PR_TransmitFile. */ #define ZERO_LEN_FILE_NAME "zerolen.tmp" #define HEADER_STR "Header" #define HEADER_LEN 6 /* length of HEADER_STR, not counting the null byte */ #define TRAILER_STR "Trailer" #define TRAILER_LEN 7 /* length of TRAILER_STR, not counting the null byte */ #include "nspr.h" #include #include #include static void ClientThread(void *arg) { PRFileDesc *sock; PRNetAddr addr; PRUint16 port = (PRUint16) arg; char buf[1024]; char *bufPtr; PRInt32 nbytes; PRInt32 ntotal; PRInt32 nexpected; sock = PR_NewTCPSocket(); if (NULL == sock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { fprintf(stderr, "PR_Connect failed\n"); exit(1); } ntotal = 0; bufPtr = buf; while ((nbytes = PR_Read(sock, bufPtr, sizeof(buf)-ntotal)) > 0) { ntotal += nbytes; bufPtr += nbytes; } if (-1 == nbytes) { fprintf(stderr, "PR_Read failed\n"); exit(1); } nexpected = HEADER_LEN+TRAILER_LEN+TRAILER_LEN+HEADER_LEN+HEADER_LEN; if (ntotal != nexpected) { fprintf(stderr, "total bytes read should be %d but is %d\n", nexpected, ntotal); exit(1); } if (memcmp(buf, HEADER_STR TRAILER_STR TRAILER_STR HEADER_STR HEADER_STR, nexpected) != 0) { fprintf(stderr, "wrong data is received\n"); exit(1); } if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } static void ServerThread(void *arg) { PRFileDesc *listenSock = (PRFileDesc *) arg; PRFileDesc *acceptSock; PRFileDesc *file; PRSendFileData sfd; char header[1024], trailer[1024]; PRInt32 nbytes; /* Create a zero-length file */ file = PR_Open(ZERO_LEN_FILE_NAME, PR_CREATE_FILE|PR_TRUNCATE|PR_RDWR, 0666); if (NULL == file) { fprintf(stderr, "PR_Open failed\n"); exit(1); } sfd.fd = file; sfd.file_offset = 0; sfd.file_nbytes = 0; memcpy(header, HEADER_STR, HEADER_LEN); memcpy(trailer, TRAILER_STR, TRAILER_LEN); sfd.header = header; sfd.hlen = HEADER_LEN; sfd.trailer = trailer; sfd.tlen = TRAILER_LEN; acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == acceptSock) { fprintf(stderr, "PR_Accept failed\n"); exit(1); } /* Send both header and trailer */ nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (HEADER_LEN+TRAILER_LEN != nbytes) { fprintf(stderr, "PR_SendFile should return %d but returned %d\n", HEADER_LEN+TRAILER_LEN, nbytes); exit(1); } /* Trailer only, no header */ sfd.hlen = 0; nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (TRAILER_LEN != nbytes) { fprintf(stderr, "PR_SendFile should return %d but returned %d\n", TRAILER_LEN, nbytes); exit(1); } /* Header only, no trailer */ sfd.hlen = HEADER_LEN; sfd.tlen = 0; nbytes = PR_SendFile(acceptSock, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (HEADER_LEN != nbytes) { fprintf(stderr, "PR_SendFile should return %d but returned %d\n", HEADER_LEN, nbytes); exit(1); } /* Try PR_TransmitFile */ nbytes = PR_TransmitFile(acceptSock, file, header, HEADER_LEN, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (HEADER_LEN != nbytes) { fprintf(stderr, "PR_TransmitFile should return %d but returned %d\n", HEADER_LEN, nbytes); exit(1); } if (PR_Close(acceptSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Close(file) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_Delete(ZERO_LEN_FILE_NAME) == PR_FAILURE) { fprintf(stderr, "PR_Delete failed\n"); exit(1); } } int main(int argc, char **argv) { PRFileDesc *listenSock; PRThread *clientThread; PRThread *serverThread; PRNetAddr addr; PRThreadScope scope = PR_GLOBAL_THREAD; listenSock = PR_NewTCPSocket(); if (NULL == listenSock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } if (PR_Bind(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } /* Find out what port number we are bound to. */ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } if (PR_Listen(listenSock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)), PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (NULL == clientThread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } serverThread = PR_CreateThread(PR_USER_THREAD, ServerThread, listenSock, PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (NULL == serverThread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } if (PR_JoinThread(clientThread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } if (PR_JoinThread(serverThread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } if (PR_Close(listenSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/server_test.c0000644000000000000000000004133312623070344016032 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** This server simulates a server running in loopback mode. ** ** The idea is that a single server is created. The server initially creates ** a number of worker threads. Then, with the server running, a number of ** clients are created which start requesting service from the server. ** ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "pprthred.h" #include #define PORT 15004 #define THREAD_STACKSIZE 0 #define PASS 0 #define FAIL 1 static int debug_mode = 0; static int _iterations = 1000; static int _clients = 1; static int _client_data = 250; static int _server_data = (8*1024); static PRThreadScope ServerScope, ClientScope; #define SERVER "Server" #define MAIN "Main" #define SERVER_STATE_STARTUP 0 #define SERVER_STATE_READY 1 #define SERVER_STATE_DYING 2 #define SERVER_STATE_DEAD 4 int ServerState; PRLock *ServerStateCVLock; PRCondVar *ServerStateCV; #undef DEBUGPRINTS #ifdef DEBUGPRINTS #define DPRINTF printf #else #define DPRINTF #endif /*********************************************************************** ** PRIVATE FUNCTION: Test_Result ** DESCRIPTION: Used in conjunction with the regress tool, prints out the ** status of the test case. ** INPUTS: PASS/FAIL ** OUTPUTS: None ** RETURN: None ** SIDE EFFECTS: ** ** RESTRICTIONS: ** None ** MEMORY: NA ** ALGORITHM: Determine what the status is and print accordingly. ** ***********************************************************************/ static void Test_Result (int result) { switch (result) { case PASS: printf ("PASS\n"); break; case FAIL: printf ("FAIL\n"); break; default: break; } } static void do_work(void); /* --- Server state functions --------------------------------------------- */ void SetServerState(char *waiter, PRInt32 state) { PR_Lock(ServerStateCVLock); ServerState = state; PR_NotifyCondVar(ServerStateCV); if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state); PR_Unlock(ServerStateCVLock); } int WaitServerState(char *waiter, PRInt32 state) { PRInt32 rv; PR_Lock(ServerStateCVLock); if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state); while(!(ServerState & state)) PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT); rv = ServerState; if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", waiter, state, ServerState); PR_Unlock(ServerStateCVLock); return rv; } /* --- Server Functions ------------------------------------------- */ PRLock *workerThreadsLock; PRInt32 workerThreads; PRInt32 workerThreadsBusy; void WorkerThreadFunc(void *_listenSock) { PRFileDesc *listenSock = (PRFileDesc *)_listenSock; PRInt32 bytesRead; PRInt32 bytesWritten; char *dataBuf; char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); if (debug_mode) DPRINTF("\tServer worker thread running\n"); while(1) { PRInt32 bytesToRead = _client_data; PRInt32 bytesToWrite = _server_data; PRFileDesc *newSock; PRNetAddr *rAddr; PRInt32 loops = 0; loops++; if (debug_mode) DPRINTF("\tServer thread going into accept\n"); bytesRead = PR_AcceptRead(listenSock, &newSock, &rAddr, dataBuf, bytesToRead, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead); PR_AtomicIncrement(&workerThreadsBusy); #ifdef SYMBIAN if (workerThreadsBusy == workerThreads && workerThreads<1) { #else if (workerThreadsBusy == workerThreads) { #endif PR_Lock(workerThreadsLock); if (workerThreadsBusy == workerThreads) { PRThread *WorkerThread; WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSock, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("Error creating client thread %d\n", workerThreads); } else { PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads); } } PR_Unlock(workerThreadsLock); } bytesToRead -= bytesRead; while (bytesToRead) { bytesRead = PR_Recv(newSock, dataBuf, bytesToRead, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead); } bytesWritten = PR_Send(newSock, sendBuf, bytesToWrite, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesWritten != _server_data) { if (debug_mode) printf("\tError sending data to client (%d, %d)\n", bytesWritten, PR_GetOSError()); } else { if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten); } PR_Close(newSock); PR_AtomicDecrement(&workerThreadsBusy); } } PRFileDesc * ServerSetup(void) { PRFileDesc *listenSocket; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); else Test_Result(FAIL); return NULL; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address: OS error %d\n", PR_GetOSError()); else Test_Result(FAIL); PR_Close(listenSocket); return NULL; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); else Test_Result(FAIL); PR_Close(listenSocket); return NULL; } /* Create Clients */ workerThreads = 0; workerThreadsBusy = 0; workerThreadsLock = PR_NewLock(); WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSocket, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); PR_Close(listenSocket); return NULL; } PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer created primordial worker thread\n"); return listenSocket; } /* The main server loop */ void ServerThreadFunc(void *unused) { PRFileDesc *listenSocket; /* Do setup */ listenSocket = ServerSetup(); if (!listenSocket) { SetServerState(SERVER, SERVER_STATE_DEAD); } else { if (debug_mode) DPRINTF("\tServer up\n"); /* Tell clients they can start now. */ SetServerState(SERVER, SERVER_STATE_READY); /* Now wait for server death signal */ WaitServerState(SERVER, SERVER_STATE_DYING); /* Cleanup */ SetServerState(SERVER, SERVER_STATE_DEAD); } } /* --- Client Functions ------------------------------------------- */ PRInt32 numRequests; PRInt32 numClients; PRMonitor *clientMonitor; void ClientThreadFunc(void *unused) { PRNetAddr serverAddr; PRFileDesc *clientSocket; char *sendBuf; char *recvBuf; PRInt32 rv; PRInt32 bytesNeeded; sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char)); if (!recvBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); while(numRequests > 0) { if ( (numRequests % 10) == 0 ) if (debug_mode) printf("."); if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests); clientSocket = PR_NewTCPSocket(); if (!clientSocket) { if (debug_mode) printf("Client error creating socket: OS error %d\n", PR_GetOSError()); continue; } if (debug_mode) DPRINTF("\tClient connecting\n"); rv = PR_Connect(clientSocket, &serverAddr, PR_INTERVAL_NO_TIMEOUT); if (!clientSocket) { if (debug_mode) printf("\tClient error connecting\n"); continue; } if (debug_mode) DPRINTF("\tClient connected\n"); rv = PR_Send(clientSocket, sendBuf, _client_data, 0, PR_INTERVAL_NO_TIMEOUT); if (rv != _client_data) { if (debug_mode) printf("Client error sending data (%d)\n", rv); PR_Close(clientSocket); continue; } if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv); bytesNeeded = _server_data; while(bytesNeeded) { rv = PR_Recv(clientSocket, recvBuf, bytesNeeded, 0, PR_INTERVAL_NO_TIMEOUT); if (rv <= 0) { if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", rv, (_server_data - bytesNeeded), _server_data); break; } if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv); bytesNeeded -= rv; } PR_Close(clientSocket); PR_AtomicDecrement(&numRequests); } PR_EnterMonitor(clientMonitor); --numClients; PR_Notify(clientMonitor); PR_ExitMonitor(clientMonitor); PR_DELETE(sendBuf); PR_DELETE(recvBuf); } void RunClients(void) { PRInt32 index; numRequests = _iterations; numClients = _clients; clientMonitor = PR_NewMonitor(); for (index=0; index<_clients; index++) { PRThread *clientThread; clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, NULL, PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); } else if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients); } PR_EnterMonitor(clientMonitor); while(numClients) PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(clientMonitor); } /* --- Main Function ---------------------------------------------- */ static void do_work() { PRThread *ServerThread; PRInt32 state; SetServerState(MAIN, SERVER_STATE_STARTUP); ServerThread = PR_CreateThread( PR_USER_THREAD, ServerThreadFunc, NULL, PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; } /* Wait for server to be ready */ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD); if (!(state & SERVER_STATE_DEAD)) { /* Run Test Clients */ RunClients(); /* Send death signal to server */ SetServerState(MAIN, SERVER_STATE_DYING); } PR_JoinThread(ServerThread); } static void do_workUU(void) { ServerScope = PR_LOCAL_THREAD; ClientScope = PR_LOCAL_THREAD; do_work(); } static void do_workUK(void) { ServerScope = PR_LOCAL_THREAD; ClientScope = PR_GLOBAL_THREAD; do_work(); } static void do_workKU(void) { ServerScope = PR_GLOBAL_THREAD; ClientScope = PR_LOCAL_THREAD; do_work(); } static void do_workKK(void) { ServerScope = PR_GLOBAL_THREAD; ClientScope = PR_GLOBAL_THREAD; do_work(); } static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ #ifndef SYMBIAN if (debug_mode) { printf("Enter number of iterations: \n"); scanf("%d", &_iterations); printf("Enter number of clients : \n"); scanf("%d", &_clients); printf("Enter size of client data : \n"); scanf("%d", &_client_data); printf("Enter size of server data : \n"); scanf("%d", &_server_data); } else #endif { _iterations = 10; _clients = 1; _client_data = 10; _server_data = 10; } if (debug_mode) { printf("\n\n%d iterations with %d client threads.\n", _iterations, _clients); printf("Sending %d bytes of client data and %d bytes of server data\n", _client_data, _server_data); } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); ServerStateCVLock = PR_NewLock(); ServerStateCV = PR_NewCondVar(ServerStateCVLock); Measure(do_workUU, "server loop user/user"); #if 0 Measure(do_workUK, "server loop user/kernel"); Measure(do_workKU, "server loop kernel/user"); Measure(do_workKK, "server loop kernel/kernel"); #endif PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/servr_kk.c0000644000000000000000000004067112623070344015317 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** This server simulates a server running in loopback mode. ** ** The idea is that a single server is created. The server initially creates ** a number of worker threads. Then, with the server running, a number of ** clients are created which start requesting service from the server. ** ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "pprthred.h" #include #define PORT 15004 #define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; static int _client_data = 250; static int _server_data = (8*1024); static PRThreadScope ServerScope, ClientScope; #define SERVER "Server" #define MAIN "Main" #define SERVER_STATE_STARTUP 0 #define SERVER_STATE_READY 1 #define SERVER_STATE_DYING 2 #define SERVER_STATE_DEAD 4 int ServerState; PRLock *ServerStateCVLock; PRCondVar *ServerStateCV; #ifdef DEBUGPRINTS #define DPRINTF printf #else #define DPRINTF #endif PRIntn failed_already=0; PRIntn debug_mode; static void do_work(void); /* --- Server state functions --------------------------------------------- */ void SetServerState(char *waiter, PRInt32 state) { PR_Lock(ServerStateCVLock); ServerState = state; PR_NotifyCondVar(ServerStateCV); if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state); PR_Unlock(ServerStateCVLock); } int WaitServerState(char *waiter, PRInt32 state) { PRInt32 rv; PR_Lock(ServerStateCVLock); if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state); while(!(ServerState & state)) PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT); rv = ServerState; if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", waiter, state, ServerState); PR_Unlock(ServerStateCVLock); return rv; } /* --- Server Functions ------------------------------------------- */ PRLock *workerThreadsLock; PRInt32 workerThreads; PRInt32 workerThreadsBusy; void WorkerThreadFunc(void *_listenSock) { PRFileDesc *listenSock = (PRFileDesc *)_listenSock; PRInt32 bytesRead; PRInt32 bytesWritten; char *dataBuf; char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); if (debug_mode) DPRINTF("\tServer worker thread running\n"); while(1) { PRInt32 bytesToRead = _client_data; PRInt32 bytesToWrite = _server_data; PRFileDesc *newSock; PRNetAddr *rAddr; PRInt32 loops = 0; loops++; if (debug_mode) DPRINTF("\tServer thread going into accept\n"); bytesRead = PR_AcceptRead(listenSock, &newSock, &rAddr, dataBuf, bytesToRead, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead); PR_AtomicIncrement(&workerThreadsBusy); #ifdef SYMBIAN if (workerThreadsBusy == workerThreads && workerThreads<1) { #else if (workerThreadsBusy == workerThreads) { #endif PR_Lock(workerThreadsLock); if (workerThreadsBusy == workerThreads) { PRThread *WorkerThread; WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSock, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("Error creating client thread %d\n", workerThreads); } else { PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads); } } PR_Unlock(workerThreadsLock); } bytesToRead -= bytesRead; while (bytesToRead) { bytesRead = PR_Recv(newSock, dataBuf, bytesToRead, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead); } bytesWritten = PR_Send(newSock, sendBuf, bytesToWrite, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesWritten != _server_data) { if (debug_mode) printf("\tError sending data to client (%d, %d)\n", bytesWritten, PR_GetOSError()); } else { if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten); } PR_Close(newSock); PR_AtomicDecrement(&workerThreadsBusy); } } PRFileDesc * ServerSetup(void) { PRFileDesc *listenSocket; PRSocketOptionData sockOpt; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); else failed_already=1; return NULL; } sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) { if (debug_mode) printf("\tServer error setting socket option: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); else failed_already=1; PR_Close(listenSocket); return NULL; } /* Create Clients */ workerThreads = 0; workerThreadsBusy = 0; workerThreadsLock = PR_NewLock(); WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSocket, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); PR_Close(listenSocket); return NULL; } PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer created primordial worker thread\n"); return listenSocket; } /* The main server loop */ void ServerThreadFunc(void *unused) { PRFileDesc *listenSocket; /* Do setup */ listenSocket = ServerSetup(); if (!listenSocket) { SetServerState(SERVER, SERVER_STATE_DEAD); } else { if (debug_mode) DPRINTF("\tServer up\n"); /* Tell clients they can start now. */ SetServerState(SERVER, SERVER_STATE_READY); /* Now wait for server death signal */ WaitServerState(SERVER, SERVER_STATE_DYING); /* Cleanup */ SetServerState(SERVER, SERVER_STATE_DEAD); } } /* --- Client Functions ------------------------------------------- */ PRInt32 numRequests; PRInt32 numClients; PRMonitor *clientMonitor; void ClientThreadFunc(void *unused) { PRNetAddr serverAddr; PRFileDesc *clientSocket; char *sendBuf; char *recvBuf; PRInt32 rv; PRInt32 bytesNeeded; sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char)); if (!recvBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); while(numRequests > 0) { if ( (numRequests % 10) == 0 ) if (debug_mode) printf("."); if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests); clientSocket = PR_NewTCPSocket(); if (!clientSocket) { if (debug_mode) printf("Client error creating socket: OS error %d\n", PR_GetOSError()); continue; } if (debug_mode) DPRINTF("\tClient connecting\n"); rv = PR_Connect(clientSocket, &serverAddr, PR_INTERVAL_NO_TIMEOUT); if (!clientSocket) { if (debug_mode) printf("\tClient error connecting\n"); continue; } if (debug_mode) DPRINTF("\tClient connected\n"); rv = PR_Send(clientSocket, sendBuf, _client_data, 0, PR_INTERVAL_NO_TIMEOUT); if (rv != _client_data) { if (debug_mode) printf("Client error sending data (%d)\n", rv); PR_Close(clientSocket); continue; } if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv); bytesNeeded = _server_data; while(bytesNeeded) { rv = PR_Recv(clientSocket, recvBuf, bytesNeeded, 0, PR_INTERVAL_NO_TIMEOUT); if (rv <= 0) { if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", rv, (_server_data - bytesNeeded), _server_data); break; } if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv); bytesNeeded -= rv; } PR_Close(clientSocket); PR_AtomicDecrement(&numRequests); } PR_EnterMonitor(clientMonitor); --numClients; PR_Notify(clientMonitor); PR_ExitMonitor(clientMonitor); PR_DELETE(sendBuf); PR_DELETE(recvBuf); } void RunClients(void) { PRInt32 index; numRequests = _iterations; numClients = _clients; clientMonitor = PR_NewMonitor(); for (index=0; index<_clients; index++) { PRThread *clientThread; clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, NULL, PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); } else if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients); } PR_EnterMonitor(clientMonitor); while(numClients) PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(clientMonitor); } /* --- Main Function ---------------------------------------------- */ static void do_work() { PRThread *ServerThread; PRInt32 state; SetServerState(MAIN, SERVER_STATE_STARTUP); ServerThread = PR_CreateThread( PR_USER_THREAD, ServerThreadFunc, NULL, PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; } /* Wait for server to be ready */ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD); if (!(state & SERVER_STATE_DEAD)) { /* Run Test Clients */ RunClients(); /* Send death signal to server */ SetServerState(MAIN, SERVER_STATE_DYING); } PR_JoinThread(ServerThread); } static void do_workUU(void) { ServerScope = PR_LOCAL_THREAD; ClientScope = PR_LOCAL_THREAD; do_work(); } static void do_workUK(void) { ServerScope = PR_LOCAL_THREAD; ClientScope = PR_GLOBAL_THREAD; do_work(); } static void do_workKU(void) { ServerScope = PR_GLOBAL_THREAD; ClientScope = PR_LOCAL_THREAD; do_work(); } static void do_workKK(void) { ServerScope = PR_GLOBAL_THREAD; ClientScope = PR_GLOBAL_THREAD; do_work(); } static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ #ifndef SYMBIAN if (debug_mode) { printf("Enter number of iterations: \n"); scanf("%d", &_iterations); printf("Enter number of clients : \n"); scanf("%d", &_clients); printf("Enter size of client data : \n"); scanf("%d", &_client_data); printf("Enter size of server data : \n"); scanf("%d", &_server_data); } else #endif { _iterations = 7; _clients = 7; _client_data = 100; _server_data = 100; } if (debug_mode) { printf("\n\n%d iterations with %d client threads.\n", _iterations, _clients); printf("Sending %d bytes of client data and %d bytes of server data\n", _client_data, _server_data); } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetThreadRecycleMode(64); ServerStateCVLock = PR_NewLock(); ServerStateCV = PR_NewCondVar(ServerStateCVLock); Measure(do_workKK, "server loop kernel/kernel"); PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/servr_ku.c0000644000000000000000000004012212623070344015320 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** This server simulates a server running in loopback mode. ** ** The idea is that a single server is created. The server initially creates ** a number of worker threads. Then, with the server running, a number of ** clients are created which start requesting service from the server. ** ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "pprthred.h" #include #define PORT 15004 #define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; static int _client_data = 250; static int _server_data = (8*1024); static PRThreadScope ServerScope, ClientScope; #define SERVER "Server" #define MAIN "Main" #define SERVER_STATE_STARTUP 0 #define SERVER_STATE_READY 1 #define SERVER_STATE_DYING 2 #define SERVER_STATE_DEAD 4 int ServerState; PRLock *ServerStateCVLock; PRCondVar *ServerStateCV; #ifdef DEBUGPRINTS #define DPRINTF printf #else #define DPRINTF #endif PRIntn failed_already=0; PRIntn debug_mode; static void do_work(void); /* --- Server state functions --------------------------------------------- */ void SetServerState(char *waiter, PRInt32 state) { PR_Lock(ServerStateCVLock); ServerState = state; PR_NotifyCondVar(ServerStateCV); if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state); PR_Unlock(ServerStateCVLock); } int WaitServerState(char *waiter, PRInt32 state) { PRInt32 rv; PR_Lock(ServerStateCVLock); if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state); while(!(ServerState & state)) PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT); rv = ServerState; if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", waiter, state, ServerState); PR_Unlock(ServerStateCVLock); return rv; } /* --- Server Functions ------------------------------------------- */ PRLock *workerThreadsLock; PRInt32 workerThreads; PRInt32 workerThreadsBusy; void WorkerThreadFunc(void *_listenSock) { PRFileDesc *listenSock = (PRFileDesc *)_listenSock; PRInt32 bytesRead; PRInt32 bytesWritten; char *dataBuf; char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); if (debug_mode) DPRINTF("\tServer worker thread running\n"); while(1) { PRInt32 bytesToRead = _client_data; PRInt32 bytesToWrite = _server_data; PRFileDesc *newSock; PRNetAddr *rAddr; PRInt32 loops = 0; loops++; if (debug_mode) DPRINTF("\tServer thread going into accept\n"); bytesRead = PR_AcceptRead(listenSock, &newSock, &rAddr, dataBuf, bytesToRead, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead); PR_AtomicIncrement(&workerThreadsBusy); #ifdef SYMBIAN if (workerThreadsBusy == workerThreads && workerThreads<1) { #else if (workerThreadsBusy == workerThreads) { #endif PR_Lock(workerThreadsLock); if (workerThreadsBusy == workerThreads) { PRThread *WorkerThread; WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSock, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("Error creating client thread %d\n", workerThreads); } else { PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads); } } PR_Unlock(workerThreadsLock); } bytesToRead -= bytesRead; while (bytesToRead) { bytesRead = PR_Recv(newSock, dataBuf, bytesToRead, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead); } bytesWritten = PR_Send(newSock, sendBuf, bytesToWrite, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesWritten != _server_data) { if (debug_mode) printf("\tError sending data to client (%d, %d)\n", bytesWritten, PR_GetOSError()); } else { if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten); } PR_Close(newSock); PR_AtomicDecrement(&workerThreadsBusy); } } PRFileDesc * ServerSetup(void) { PRFileDesc *listenSocket; PRSocketOptionData sockOpt; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); else failed_already=1; return NULL; } sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) { if (debug_mode) printf("\tServer error setting socket option: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); else failed_already=1; PR_Close(listenSocket); return NULL; } /* Create Clients */ workerThreads = 0; workerThreadsBusy = 0; workerThreadsLock = PR_NewLock(); WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSocket, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); PR_Close(listenSocket); return NULL; } PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer created primordial worker thread\n"); return listenSocket; } /* The main server loop */ void ServerThreadFunc(void *unused) { PRFileDesc *listenSocket; /* Do setup */ listenSocket = ServerSetup(); if (!listenSocket) { SetServerState(SERVER, SERVER_STATE_DEAD); } else { if (debug_mode) DPRINTF("\tServer up\n"); /* Tell clients they can start now. */ SetServerState(SERVER, SERVER_STATE_READY); /* Now wait for server death signal */ WaitServerState(SERVER, SERVER_STATE_DYING); /* Cleanup */ SetServerState(SERVER, SERVER_STATE_DEAD); } } /* --- Client Functions ------------------------------------------- */ PRInt32 numRequests; PRInt32 numClients; PRMonitor *clientMonitor; void ClientThreadFunc(void *unused) { PRNetAddr serverAddr; PRFileDesc *clientSocket; char *sendBuf; char *recvBuf; PRInt32 rv; PRInt32 bytesNeeded; sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char)); if (!recvBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); while(numRequests > 0) { if ( (numRequests % 10) == 0 ) if (debug_mode) printf("."); if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests); clientSocket = PR_NewTCPSocket(); if (!clientSocket) { if (debug_mode) printf("Client error creating socket: OS error %d\n", PR_GetOSError()); continue; } if (debug_mode) DPRINTF("\tClient connecting\n"); rv = PR_Connect(clientSocket, &serverAddr, PR_INTERVAL_NO_TIMEOUT); if (!clientSocket) { if (debug_mode) printf("\tClient error connecting\n"); continue; } if (debug_mode) DPRINTF("\tClient connected\n"); rv = PR_Send(clientSocket, sendBuf, _client_data, 0, PR_INTERVAL_NO_TIMEOUT); if (rv != _client_data) { if (debug_mode) printf("Client error sending data (%d)\n", rv); PR_Close(clientSocket); continue; } if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv); bytesNeeded = _server_data; while(bytesNeeded) { rv = PR_Recv(clientSocket, recvBuf, bytesNeeded, 0, PR_INTERVAL_NO_TIMEOUT); if (rv <= 0) { if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", rv, (_server_data - bytesNeeded), _server_data); break; } if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv); bytesNeeded -= rv; } PR_Close(clientSocket); PR_AtomicDecrement(&numRequests); } PR_EnterMonitor(clientMonitor); --numClients; PR_Notify(clientMonitor); PR_ExitMonitor(clientMonitor); PR_DELETE(sendBuf); PR_DELETE(recvBuf); } void RunClients(void) { PRInt32 index; numRequests = _iterations; numClients = _clients; clientMonitor = PR_NewMonitor(); for (index=0; index<_clients; index++) { PRThread *clientThread; clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, NULL, PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); } else if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients); } PR_EnterMonitor(clientMonitor); while(numClients) PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(clientMonitor); } /* --- Main Function ---------------------------------------------- */ static void do_work() { PRThread *ServerThread; PRInt32 state; SetServerState(MAIN, SERVER_STATE_STARTUP); ServerThread = PR_CreateThread( PR_USER_THREAD, ServerThreadFunc, NULL, PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; } /* Wait for server to be ready */ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD); if (!(state & SERVER_STATE_DEAD)) { /* Run Test Clients */ RunClients(); /* Send death signal to server */ SetServerState(MAIN, SERVER_STATE_DYING); } PR_JoinThread(ServerThread); } static void do_workKU(void) { ServerScope = PR_GLOBAL_THREAD; ClientScope = PR_LOCAL_THREAD; do_work(); } static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ #ifndef SYMBIAN if (debug_mode) { printf("Enter number of iterations: \n"); scanf("%d", &_iterations); printf("Enter number of clients : \n"); scanf("%d", &_clients); printf("Enter size of client data : \n"); scanf("%d", &_client_data); printf("Enter size of server data : \n"); scanf("%d", &_server_data); } else #endif { _iterations = 7; _clients = 7; _client_data = 100; _server_data = 100; } if (debug_mode) { printf("\n\n%d iterations with %d client threads.\n", _iterations, _clients); printf("Sending %d bytes of client data and %d bytes of server data\n", _client_data, _server_data); } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetThreadRecycleMode(64); ServerStateCVLock = PR_NewLock(); ServerStateCV = PR_NewCondVar(ServerStateCVLock); Measure(do_workKU, "server loop kernel/user"); PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/servr_uk.c0000644000000000000000000004010312623070344015317 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** This server simulates a server running in loopback mode. ** ** The idea is that a single server is created. The server initially creates ** a number of worker threads. Then, with the server running, a number of ** clients are created which start requesting service from the server. ** ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "pprthred.h" #include #define PORT 15004 #define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; static int _client_data = 250; static int _server_data = (8*1024); static PRThreadScope ServerScope, ClientScope; #define SERVER "Server" #define MAIN "Main" #define SERVER_STATE_STARTUP 0 #define SERVER_STATE_READY 1 #define SERVER_STATE_DYING 2 #define SERVER_STATE_DEAD 4 int ServerState; PRLock *ServerStateCVLock; PRCondVar *ServerStateCV; #ifdef DEBUGPRINTS #define DPRINTF printf #else #define DPRINTF #endif PRIntn failed_already=0; PRIntn debug_mode; static void do_work(void); /* --- Server state functions --------------------------------------------- */ void SetServerState(char *waiter, PRInt32 state) { PR_Lock(ServerStateCVLock); ServerState = state; PR_NotifyCondVar(ServerStateCV); if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state); PR_Unlock(ServerStateCVLock); } int WaitServerState(char *waiter, PRInt32 state) { PRInt32 rv; PR_Lock(ServerStateCVLock); if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state); while(!(ServerState & state)) PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT); rv = ServerState; if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", waiter, state, ServerState); PR_Unlock(ServerStateCVLock); return rv; } /* --- Server Functions ------------------------------------------- */ PRLock *workerThreadsLock; PRInt32 workerThreads; PRInt32 workerThreadsBusy; void WorkerThreadFunc(void *_listenSock) { PRFileDesc *listenSock = (PRFileDesc *)_listenSock; PRInt32 bytesRead; PRInt32 bytesWritten; char *dataBuf; char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); if (debug_mode) DPRINTF("\tServer worker thread running\n"); while(1) { PRInt32 bytesToRead = _client_data; PRInt32 bytesToWrite = _server_data; PRFileDesc *newSock; PRNetAddr *rAddr; PRInt32 loops = 0; loops++; if (debug_mode) DPRINTF("\tServer thread going into accept\n"); bytesRead = PR_AcceptRead(listenSock, &newSock, &rAddr, dataBuf, bytesToRead, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead); PR_AtomicIncrement(&workerThreadsBusy); #ifdef SYMBIAN if (workerThreadsBusy == workerThreads && workerThreads<1) { #else if (workerThreadsBusy == workerThreads) { #endif PR_Lock(workerThreadsLock); if (workerThreadsBusy == workerThreads) { PRThread *WorkerThread; WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSock, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("Error creating client thread %d\n", workerThreads); } else { PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads); } } PR_Unlock(workerThreadsLock); } bytesToRead -= bytesRead; while (bytesToRead) { bytesRead = PR_Recv(newSock, dataBuf, bytesToRead, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead); } bytesWritten = PR_Send(newSock, sendBuf, bytesToWrite, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesWritten != _server_data) { if (debug_mode) printf("\tError sending data to client (%d, %d)\n", bytesWritten, PR_GetOSError()); } else { if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten); } PR_Close(newSock); PR_AtomicDecrement(&workerThreadsBusy); } } PRFileDesc * ServerSetup(void) { PRFileDesc *listenSocket; PRSocketOptionData sockOpt; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); else return NULL; } sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) { if (debug_mode) printf("\tServer error setting socket option: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); else failed_already=1; PR_Close(listenSocket); return NULL; } /* Create Clients */ workerThreads = 0; workerThreadsBusy = 0; workerThreadsLock = PR_NewLock(); WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSocket, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); PR_Close(listenSocket); return NULL; } PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer created primordial worker thread\n"); return listenSocket; } /* The main server loop */ void ServerThreadFunc(void *unused) { PRFileDesc *listenSocket; /* Do setup */ listenSocket = ServerSetup(); if (!listenSocket) { SetServerState(SERVER, SERVER_STATE_DEAD); } else { if (debug_mode) DPRINTF("\tServer up\n"); /* Tell clients they can start now. */ SetServerState(SERVER, SERVER_STATE_READY); /* Now wait for server death signal */ WaitServerState(SERVER, SERVER_STATE_DYING); /* Cleanup */ SetServerState(SERVER, SERVER_STATE_DEAD); } } /* --- Client Functions ------------------------------------------- */ PRInt32 numRequests; PRInt32 numClients; PRMonitor *clientMonitor; void ClientThreadFunc(void *unused) { PRNetAddr serverAddr; PRFileDesc *clientSocket; char *sendBuf; char *recvBuf; PRInt32 rv; PRInt32 bytesNeeded; sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char)); if (!recvBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); while(numRequests > 0) { if ( (numRequests % 10) == 0 ) if (debug_mode) printf("."); if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests); clientSocket = PR_NewTCPSocket(); if (!clientSocket) { if (debug_mode) printf("Client error creating socket: OS error %d\n", PR_GetOSError()); continue; } if (debug_mode) DPRINTF("\tClient connecting\n"); rv = PR_Connect(clientSocket, &serverAddr, PR_INTERVAL_NO_TIMEOUT); if (!clientSocket) { if (debug_mode) printf("\tClient error connecting\n"); continue; } if (debug_mode) DPRINTF("\tClient connected\n"); rv = PR_Send(clientSocket, sendBuf, _client_data, 0, PR_INTERVAL_NO_TIMEOUT); if (rv != _client_data) { if (debug_mode) printf("Client error sending data (%d)\n", rv); PR_Close(clientSocket); continue; } if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv); bytesNeeded = _server_data; while(bytesNeeded) { rv = PR_Recv(clientSocket, recvBuf, bytesNeeded, 0, PR_INTERVAL_NO_TIMEOUT); if (rv <= 0) { if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", rv, (_server_data - bytesNeeded), _server_data); break; } if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv); bytesNeeded -= rv; } PR_Close(clientSocket); PR_AtomicDecrement(&numRequests); } PR_EnterMonitor(clientMonitor); --numClients; PR_Notify(clientMonitor); PR_ExitMonitor(clientMonitor); PR_DELETE(sendBuf); PR_DELETE(recvBuf); } void RunClients(void) { PRInt32 index; numRequests = _iterations; numClients = _clients; clientMonitor = PR_NewMonitor(); for (index=0; index<_clients; index++) { PRThread *clientThread; clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, NULL, PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); } else if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients); } PR_EnterMonitor(clientMonitor); while(numClients) PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(clientMonitor); } /* --- Main Function ---------------------------------------------- */ static void do_work() { PRThread *ServerThread; PRInt32 state; SetServerState(MAIN, SERVER_STATE_STARTUP); ServerThread = PR_CreateThread( PR_USER_THREAD, ServerThreadFunc, NULL, PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; } /* Wait for server to be ready */ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD); if (!(state & SERVER_STATE_DEAD)) { /* Run Test Clients */ RunClients(); /* Send death signal to server */ SetServerState(MAIN, SERVER_STATE_DYING); } PR_JoinThread(ServerThread); } static void do_workUK(void) { ServerScope = PR_LOCAL_THREAD; ClientScope = PR_GLOBAL_THREAD; do_work(); } static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ #ifndef SYMBIAN if (debug_mode) { printf("Enter number of iterations: \n"); scanf("%d", &_iterations); printf("Enter number of clients : \n"); scanf("%d", &_clients); printf("Enter size of client data : \n"); scanf("%d", &_client_data); printf("Enter size of server data : \n"); scanf("%d", &_server_data); } else #endif { _iterations = 7; _clients = 7; _client_data = 100; _server_data = 100; } if (debug_mode) { printf("\n\n%d iterations with %d client threads.\n", _iterations, _clients); printf("Sending %d bytes of client data and %d bytes of server data\n", _client_data, _server_data); } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetThreadRecycleMode(64); ServerStateCVLock = PR_NewLock(); ServerStateCV = PR_NewCondVar(ServerStateCVLock); Measure(do_workUK, "server loop user/kernel"); PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/servr_uu.c0000644000000000000000000004012612623070344015336 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** This server simulates a server running in loopback mode. ** ** The idea is that a single server is created. The server initially creates ** a number of worker threads. Then, with the server running, a number of ** clients are created which start requesting service from the server. ** ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "pprthred.h" #include #define PORT 15004 #define THREAD_STACKSIZE 0 static int _iterations = 1000; static int _clients = 1; static int _client_data = 250; static int _server_data = (8*1024); static PRThreadScope ServerScope, ClientScope; #define SERVER "Server" #define MAIN "Main" #define SERVER_STATE_STARTUP 0 #define SERVER_STATE_READY 1 #define SERVER_STATE_DYING 2 #define SERVER_STATE_DEAD 4 int ServerState; PRLock *ServerStateCVLock; PRCondVar *ServerStateCV; #ifdef DEBUGPRINTS #define DPRINTF printf #else #define DPRINTF #endif PRIntn failed_already=0; PRIntn debug_mode; static void do_work(void); /* --- Server state functions --------------------------------------------- */ void SetServerState(char *waiter, PRInt32 state) { PR_Lock(ServerStateCVLock); ServerState = state; PR_NotifyCondVar(ServerStateCV); if (debug_mode) DPRINTF("\t%s changed state to %d\n", waiter, state); PR_Unlock(ServerStateCVLock); } int WaitServerState(char *waiter, PRInt32 state) { PRInt32 rv; PR_Lock(ServerStateCVLock); if (debug_mode) DPRINTF("\t%s waiting for state %d\n", waiter, state); while(!(ServerState & state)) PR_WaitCondVar(ServerStateCV, PR_INTERVAL_NO_TIMEOUT); rv = ServerState; if (debug_mode) DPRINTF("\t%s resuming from wait for state %d; state now %d\n", waiter, state, ServerState); PR_Unlock(ServerStateCVLock); return rv; } /* --- Server Functions ------------------------------------------- */ PRLock *workerThreadsLock; PRInt32 workerThreads; PRInt32 workerThreadsBusy; void WorkerThreadFunc(void *_listenSock) { PRFileDesc *listenSock = (PRFileDesc *)_listenSock; PRInt32 bytesRead; PRInt32 bytesWritten; char *dataBuf; char *sendBuf; if (debug_mode) DPRINTF("\tServer buffer is %d bytes; %d data, %d netaddrs\n", _client_data+(2*sizeof(PRNetAddr))+32, _client_data, (2*sizeof(PRNetAddr))+32); dataBuf = (char *)PR_MALLOC(_client_data + 2*sizeof(PRNetAddr) + 32); if (!dataBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); sendBuf = (char *)PR_MALLOC(_server_data *sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tServer could not malloc space!?\n"); if (debug_mode) DPRINTF("\tServer worker thread running\n"); while(1) { PRInt32 bytesToRead = _client_data; PRInt32 bytesToWrite = _server_data; PRFileDesc *newSock; PRNetAddr *rAddr; PRInt32 loops = 0; loops++; if (debug_mode) DPRINTF("\tServer thread going into accept\n"); bytesRead = PR_AcceptRead(listenSock, &newSock, &rAddr, dataBuf, bytesToRead, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error in accept (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer accepted connection (%d bytes)\n", bytesRead); PR_AtomicIncrement(&workerThreadsBusy); #ifdef SYMBIAN if (workerThreadsBusy == workerThreads && workerThreads<1) { #else if (workerThreadsBusy == workerThreads) { #endif PR_Lock(workerThreadsLock); if (workerThreadsBusy == workerThreads) { PRThread *WorkerThread; WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSock, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("Error creating client thread %d\n", workerThreads); } else { PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer creates worker (%d)\n", workerThreads); } } PR_Unlock(workerThreadsLock); } bytesToRead -= bytesRead; while (bytesToRead) { bytesRead = PR_Recv(newSock, dataBuf, bytesToRead, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesRead < 0) { if (debug_mode) printf("\tServer error receiving data (%d)\n", bytesRead); continue; } if (debug_mode) DPRINTF("\tServer received %d bytes\n", bytesRead); } bytesWritten = PR_Send(newSock, sendBuf, bytesToWrite, 0, PR_INTERVAL_NO_TIMEOUT); if (bytesWritten != _server_data) { if (debug_mode) printf("\tError sending data to client (%d, %d)\n", bytesWritten, PR_GetOSError()); } else { if (debug_mode) DPRINTF("\tServer sent %d bytes\n", bytesWritten); } PR_Close(newSock); PR_AtomicDecrement(&workerThreadsBusy); } } PRFileDesc * ServerSetup(void) { PRFileDesc *listenSocket; PRSocketOptionData sockOpt; PRNetAddr serverAddr; PRThread *WorkerThread; if ( (listenSocket = PR_NewTCPSocket()) == NULL) { if (debug_mode) printf("\tServer error creating listen socket\n"); else failed_already=1; return NULL; } sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; if ( PR_SetSocketOption(listenSocket, &sockOpt) == PR_FAILURE) { if (debug_mode) printf("\tServer error setting socket option: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_ANY); if ( PR_Bind(listenSocket, &serverAddr) == PR_FAILURE) { if (debug_mode) printf("\tServer error binding to server address: OS error %d\n", PR_GetOSError()); else failed_already=1; PR_Close(listenSocket); return NULL; } if ( PR_Listen(listenSocket, 128) == PR_FAILURE) { if (debug_mode) printf("\tServer error listening to server socket\n"); else failed_already=1; PR_Close(listenSocket); return NULL; } /* Create Clients */ workerThreads = 0; workerThreadsBusy = 0; workerThreadsLock = PR_NewLock(); WorkerThread = PR_CreateThread( PR_SYSTEM_THREAD, WorkerThreadFunc, listenSocket, PR_PRIORITY_NORMAL, ServerScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!WorkerThread) { if (debug_mode) printf("error creating working thread\n"); PR_Close(listenSocket); return NULL; } PR_AtomicIncrement(&workerThreads); if (debug_mode) DPRINTF("\tServer created primordial worker thread\n"); return listenSocket; } /* The main server loop */ void ServerThreadFunc(void *unused) { PRFileDesc *listenSocket; /* Do setup */ listenSocket = ServerSetup(); if (!listenSocket) { SetServerState(SERVER, SERVER_STATE_DEAD); } else { if (debug_mode) DPRINTF("\tServer up\n"); /* Tell clients they can start now. */ SetServerState(SERVER, SERVER_STATE_READY); /* Now wait for server death signal */ WaitServerState(SERVER, SERVER_STATE_DYING); /* Cleanup */ SetServerState(SERVER, SERVER_STATE_DEAD); } } /* --- Client Functions ------------------------------------------- */ PRInt32 numRequests; PRInt32 numClients; PRMonitor *clientMonitor; void ClientThreadFunc(void *unused) { PRNetAddr serverAddr; PRFileDesc *clientSocket; char *sendBuf; char *recvBuf; PRInt32 rv; PRInt32 bytesNeeded; sendBuf = (char *)PR_MALLOC(_client_data * sizeof(char)); if (!sendBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); recvBuf = (char *)PR_MALLOC(_server_data * sizeof(char)); if (!recvBuf) if (debug_mode) printf("\tClient could not malloc space!?\n"); memset(&serverAddr, 0, sizeof(PRNetAddr)); serverAddr.inet.family = PR_AF_INET; serverAddr.inet.port = PR_htons(PORT); serverAddr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); while(numRequests > 0) { if ( (numRequests % 10) == 0 ) if (debug_mode) printf("."); if (debug_mode) DPRINTF("\tClient starting request %d\n", numRequests); clientSocket = PR_NewTCPSocket(); if (!clientSocket) { if (debug_mode) printf("Client error creating socket: OS error %d\n", PR_GetOSError()); continue; } if (debug_mode) DPRINTF("\tClient connecting\n"); rv = PR_Connect(clientSocket, &serverAddr, PR_INTERVAL_NO_TIMEOUT); if (!clientSocket) { if (debug_mode) printf("\tClient error connecting\n"); continue; } if (debug_mode) DPRINTF("\tClient connected\n"); rv = PR_Send(clientSocket, sendBuf, _client_data, 0, PR_INTERVAL_NO_TIMEOUT); if (rv != _client_data) { if (debug_mode) printf("Client error sending data (%d)\n", rv); PR_Close(clientSocket); continue; } if (debug_mode) DPRINTF("\tClient sent %d bytes\n", rv); bytesNeeded = _server_data; while(bytesNeeded) { rv = PR_Recv(clientSocket, recvBuf, bytesNeeded, 0, PR_INTERVAL_NO_TIMEOUT); if (rv <= 0) { if (debug_mode) printf("Client error receiving data (%d) (%d/%d)\n", rv, (_server_data - bytesNeeded), _server_data); break; } if (debug_mode) DPRINTF("\tClient received %d bytes; need %d more\n", rv, bytesNeeded - rv); bytesNeeded -= rv; } PR_Close(clientSocket); PR_AtomicDecrement(&numRequests); } PR_EnterMonitor(clientMonitor); --numClients; PR_Notify(clientMonitor); PR_ExitMonitor(clientMonitor); PR_DELETE(sendBuf); PR_DELETE(recvBuf); } void RunClients(void) { PRInt32 index; numRequests = _iterations; numClients = _clients; clientMonitor = PR_NewMonitor(); for (index=0; index<_clients; index++) { PRThread *clientThread; clientThread = PR_CreateThread( PR_USER_THREAD, ClientThreadFunc, NULL, PR_PRIORITY_NORMAL, ClientScope, PR_UNJOINABLE_THREAD, THREAD_STACKSIZE); if (!clientThread) { if (debug_mode) printf("\terror creating client thread %d\n", index); } else if (debug_mode) DPRINTF("\tMain created client %d/%d\n", index+1, _clients); } PR_EnterMonitor(clientMonitor); while(numClients) PR_Wait(clientMonitor, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(clientMonitor); } /* --- Main Function ---------------------------------------------- */ static void do_work() { PRThread *ServerThread; PRInt32 state; SetServerState(MAIN, SERVER_STATE_STARTUP); ServerThread = PR_CreateThread( PR_USER_THREAD, ServerThreadFunc, NULL, PR_PRIORITY_NORMAL, ServerScope, PR_JOINABLE_THREAD, THREAD_STACKSIZE); if (!ServerThread) { if (debug_mode) printf("error creating main server thread\n"); return; } /* Wait for server to be ready */ state = WaitServerState(MAIN, SERVER_STATE_READY|SERVER_STATE_DEAD); if (!(state & SERVER_STATE_DEAD)) { /* Run Test Clients */ RunClients(); /* Send death signal to server */ SetServerState(MAIN, SERVER_STATE_DYING); } PR_JoinThread(ServerThread); } static void do_workUU(void) { ServerScope = PR_LOCAL_THREAD; ClientScope = PR_LOCAL_THREAD; do_work(); } static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); if (debug_mode) printf("\n%40s: %6.2f usec\n", msg, d / _iterations); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); /* main test */ #ifndef SYMBIAN if (debug_mode) { printf("Enter number of iterations: \n"); scanf("%d", &_iterations); printf("Enter number of clients : \n"); scanf("%d", &_clients); printf("Enter size of client data : \n"); scanf("%d", &_client_data); printf("Enter size of server data : \n"); scanf("%d", &_server_data); } else #endif { _iterations = 7; _clients = 7; _client_data = 100; _server_data = 100; } if (debug_mode) { printf("\n\n%d iterations with %d client threads.\n", _iterations, _clients); printf("Sending %d bytes of client data and %d bytes of server data\n", _client_data, _server_data); } PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetThreadRecycleMode(64); ServerStateCVLock = PR_NewLock(); ServerStateCV = PR_NewCondVar(ServerStateCVLock); Measure(do_workUU, "server loop user/user"); PR_Cleanup(); if(failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/short_thread.c0000644000000000000000000000265612623070344016160 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "nspr.h" #include "plgetopt.h" /* * Create a thread that exits right away; useful for testing race conditions in thread * creation */ int _debug_on = 0; #define DPRINTF(arg) if (_debug_on) printf arg static void housecleaning(void *cur_time); int main (int argc, char **argv) { static PRIntervalTime thread_start_time; static PRThread *housekeeping_tid = NULL; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); if (( housekeeping_tid = PR_CreateThread (PR_USER_THREAD, housecleaning, (void*)&thread_start_time, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0)) == NULL ) { fprintf(stderr, "simple_test: Error - PR_CreateThread failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); exit( 1 ); } PR_Cleanup(); return(0); } static void housecleaning (void *cur_time) { DPRINTF(("Child Thread exiting\n")); } nspr-4.11/nspr/pr/tests/sigpipe.c0000644000000000000000000000437412623070344015131 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ************************************************************************* * * Test: sigpipe.c * * Test the SIGPIPE handler in NSPR. This test applies to Unix only. * ************************************************************************* */ #if !defined(XP_UNIX) && !defined(XP_OS2) int main(void) { /* This test applies to Unix and OS/2. */ return 0; } #else /* XP_UNIX && OS/2 */ #include "nspr.h" #ifdef XP_OS2 #define INCL_DOSQUEUES #define INCL_DOSERRORS #include #endif #include #include #include static void Test(void *arg) { #ifdef XP_OS2 HFILE pipefd[2]; #else int pipefd[2]; #endif int rv; char c = '\0'; #ifdef XP_OS2 if (DosCreatePipe(&pipefd[0], &pipefd[1], 4096) != 0) { #else if (pipe(pipefd) == -1) { #endif fprintf(stderr, "cannot create pipe: %d\n", errno); exit(1); } close(pipefd[0]); rv = write(pipefd[1], &c, 1); if (rv != -1) { fprintf(stderr, "write to broken pipe should have failed with EPIPE but returned %d\n", rv); exit(1); } #ifdef SYMBIAN /* Have mercy on the unknown 142 errno, it seems ok */ if (errno != EPIPE && errno != 142) { #else if (errno != EPIPE) { #endif fprintf(stderr, "write to broken pipe failed but with wrong errno: %d\n", errno); exit(1); } close(pipefd[1]); printf("write to broken pipe failed with EPIPE, as expected\n"); } int main(int argc, char **argv) { PRThread *thread; /* This initializes NSPR. */ PR_SetError(0, 0); thread = PR_CreateThread(PR_USER_THREAD, Test, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (thread == NULL) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } if (PR_JoinThread(thread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } Test(NULL); printf("PASSED\n"); return 0; } #endif /* XP_UNIX */ nspr-4.11/nspr/pr/tests/sleep.c0000644000000000000000000000535212623070344014576 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #if defined(XP_UNIX) || defined(XP_OS2) #include #ifndef XP_OS2 #include #endif #include #if defined(HAVE_SVID_GETTOD) #define GTOD(_a) gettimeofday(_a) #else #define GTOD(_a) gettimeofday((_a), NULL) #endif static PRIntn rv = 0; static void Other(void *unused) { PRIntn didit = 0; while (PR_SUCCESS == PR_Sleep(PR_MillisecondsToInterval(250))) { fprintf(stderr, "."); didit += 1; } if (didit < 5) rv = 1; } int main(int argc, char **argv) { PRUint32 elapsed; PRThread *thread; struct timeval timein, timeout; PRInt32 onePercent = 3000000UL / 100UL; fprintf (stderr, "First sleep will sleep 3 seconds.\n"); fprintf (stderr, " sleep 1 begin\n"); (void)GTOD(&timein); sleep (3); (void)GTOD(&timeout); fprintf (stderr, " sleep 1 end\n"); elapsed = 1000000UL * (timeout.tv_sec - timein.tv_sec); elapsed += (timeout.tv_usec - timein.tv_usec); fprintf(stderr, "elapsed %u usecs\n", elapsed); if (labs(elapsed - 3000000UL) > onePercent) rv = 1; PR_Init (PR_USER_THREAD, PR_PRIORITY_NORMAL, 100); PR_STDIO_INIT(); fprintf (stderr, "Second sleep should do the same (does it?).\n"); fprintf (stderr, " sleep 2 begin\n"); (void)GTOD(&timein); sleep (3); (void)GTOD(&timeout); fprintf (stderr, " sleep 2 end\n"); elapsed = 1000000UL * (timeout.tv_sec - timein.tv_sec); elapsed += (timeout.tv_usec - timein.tv_usec); fprintf(stderr, "elapsed %u usecs\n", elapsed); if (labs(elapsed - 3000000UL) > onePercent) rv = 1; fprintf (stderr, "What happens to other threads?\n"); fprintf (stderr, "You should see dots every quarter second.\n"); fprintf (stderr, "If you don't, you're probably running on classic NSPR.\n"); thread = PR_CreateThread( PR_USER_THREAD, Other, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); fprintf (stderr, " sleep 2 begin\n"); (void)GTOD(&timein); sleep (3); (void)GTOD(&timeout); fprintf (stderr, " sleep 2 end\n"); PR_Interrupt(thread); PR_JoinThread(thread); elapsed = 1000000UL * (timeout.tv_sec - timein.tv_sec); elapsed += (timeout.tv_usec - timein.tv_usec); fprintf(stderr, "elapsed %u usecs\n", elapsed); if (labs(elapsed - 3000000UL) > onePercent) rv = 1; fprintf(stderr, "%s\n", (0 == rv) ? "PASSED" : "FAILED"); return rv; } #else /* defined(XP_UNIX) */ PRIntn main() { return 2; } #endif /* defined(XP_UNIX) */ nspr-4.11/nspr/pr/tests/socket.c0000644000000000000000000021165712623070344014765 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: socket.c ** ** Description: Test socket functionality. ** ** Modification History: */ #include "primpl.h" #include "plgetopt.h" #include #include #include #ifdef XP_UNIX #include #endif #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include #endif #ifdef WIN32 #include #endif static int _debug_on = 0; static int test_cancelio = 0; #include "obsolete/prsem.h" #ifdef XP_PC #define mode_t int #endif #define DPRINTF(arg) if (_debug_on) printf arg #ifdef XP_PC char *TEST_DIR = "prdir"; char *SMALL_FILE_NAME = "prsmallf"; char *LARGE_FILE_NAME = "prlargef"; #elif defined(SYMBIAN) char *TEST_DIR = "c:\\data\\prsocket"; char *SMALL_FILE_NAME = "c:\\data\\prsocket\\small_file"; char *LARGE_FILE_NAME = "c:\\data\\prsocket\\large_file"; #else char *TEST_DIR = "/tmp/prsocket_test_dir"; char *SMALL_FILE_NAME = "/tmp/prsocket_test_dir/small_file"; char *LARGE_FILE_NAME = "/tmp/prsocket_test_dir/large_file"; #endif #define SMALL_FILE_SIZE (3 * 1024) /* 3 KB */ #define SMALL_FILE_OFFSET_1 (512) #define SMALL_FILE_LEN_1 (1 * 1024) /* 1 KB */ #define SMALL_FILE_OFFSET_2 (75) #define SMALL_FILE_LEN_2 (758) #define SMALL_FILE_OFFSET_3 (1024) #define SMALL_FILE_LEN_3 (SMALL_FILE_SIZE - SMALL_FILE_OFFSET_3) #define SMALL_FILE_HEADER_SIZE (64) /* 64 bytes */ #define SMALL_FILE_TRAILER_SIZE (128) /* 128 bytes */ #define LARGE_FILE_SIZE (3 * 1024 * 1024) /* 3 MB */ #define LARGE_FILE_OFFSET_1 (0) #define LARGE_FILE_LEN_1 (2 * 1024 * 1024) /* 2 MB */ #define LARGE_FILE_OFFSET_2 (64) #define LARGE_FILE_LEN_2 (1 * 1024 * 1024 + 75) #define LARGE_FILE_OFFSET_3 (2 * 1024 * 1024 - 128) #define LARGE_FILE_LEN_3 (LARGE_FILE_SIZE - LARGE_FILE_OFFSET_3) #define LARGE_FILE_OFFSET_4 PR_GetPageSize() #define LARGE_FILE_LEN_4 769 #define LARGE_FILE_HEADER_SIZE (512) #define LARGE_FILE_TRAILER_SIZE (64) #define BUF_DATA_SIZE (2 * 1024) #define TCP_MESG_SIZE 1024 /* * set UDP datagram size small enough that datagrams sent to a port on the * local host will not be lost */ #define UDP_DGRAM_SIZE 128 #define NUM_TCP_CLIENTS 5 /* for a listen queue depth of 5 */ #define NUM_UDP_CLIENTS 10 #ifdef SYMBIAN #define NUM_TRANSMITFILE_CLIENTS 1 #else #define NUM_TRANSMITFILE_CLIENTS 4 #endif #define NUM_TCP_CONNECTIONS_PER_CLIENT 5 #define NUM_TCP_MESGS_PER_CONNECTION 10 #define NUM_UDP_DATAGRAMS_PER_CLIENT 5 #define TCP_SERVER_PORT 10000 #define UDP_SERVER_PORT TCP_SERVER_PORT #define SERVER_MAX_BIND_COUNT 100 #ifdef WINCE #define perror(s) #endif static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS; static PRInt32 num_udp_clients = NUM_UDP_CLIENTS; static PRInt32 num_transmitfile_clients = NUM_TRANSMITFILE_CLIENTS; static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT; static PRInt32 tcp_mesg_size = TCP_MESG_SIZE; static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION; static PRInt32 num_udp_datagrams_per_client = NUM_UDP_DATAGRAMS_PER_CLIENT; static PRInt32 udp_datagram_size = UDP_DGRAM_SIZE; static PRInt32 thread_count; PRUint16 server_domain = PR_AF_INET, client_domain = PR_AF_INET; /* an I/O layer that uses the emulated senfile method */ static PRDescIdentity emuSendFileIdentity; static PRIOMethods emuSendFileMethods; int failed_already=0; typedef struct buffer { char data[BUF_DATA_SIZE]; } buffer; PRNetAddr tcp_server_addr, udp_server_addr; typedef struct Serve_Client_Param { PRFileDesc *sockfd; /* socket to read from/write to */ PRInt32 datalen; /* bytes of data transfered in each read/write */ } Serve_Client_Param; typedef struct Server_Param { PRSemaphore *addr_sem; /* sem to post on, after setting up the address */ PRMonitor *exit_mon; /* monitor to signal on exit */ PRInt32 *exit_counter; /* counter to decrement, before exit */ PRInt32 datalen; /* bytes of data transfered in each read/write */ } Server_Param; typedef struct Client_Param { PRNetAddr server_addr; PRMonitor *exit_mon; /* monitor to signal on exit */ PRInt32 *exit_counter; /* counter to decrement, before exit */ PRInt32 datalen; PRInt32 udp_connect; /* if set clients connect udp sockets */ } Client_Param; /* the sendfile method in emuSendFileMethods */ static PRInt32 PR_CALLBACK emu_SendFile(PRFileDesc *sd, PRSendFileData *sfd, PRTransmitFileFlags flags, PRIntervalTime timeout) { return PR_EmulateSendFile(sd, sfd, flags, timeout); } /* the transmitfile method in emuSendFileMethods */ static PRInt32 PR_CALLBACK emu_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, const void *headers, PRInt32 hlen, PRTransmitFileFlags flags, PRIntervalTime timeout) { PRSendFileData sfd; sfd.fd = fd; sfd.file_offset = 0; sfd.file_nbytes = 0; sfd.header = headers; sfd.hlen = hlen; sfd.trailer = NULL; sfd.tlen = 0; return emu_SendFile(sd, &sfd, flags, timeout); } /* * readn * read data from sockfd into buf */ static PRInt32 readn(PRFileDesc *sockfd, char *buf, int len) { int rem; int bytes; int offset = 0; int err; PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; if (test_cancelio) timeout = PR_SecondsToInterval(2); for (rem=len; rem; offset += bytes, rem -= bytes) { DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n", PR_GetCurrentThread(), rem)); retry: bytes = PR_Recv(sockfd, buf + offset, rem, 0, timeout); DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n", PR_GetCurrentThread(), bytes)); if (bytes < 0) { #ifdef WINNT printf("PR_Recv: error = %d oserr = %d\n",(err = PR_GetError()), PR_GetOSError()); if ((test_cancelio) && (err == PR_IO_TIMEOUT_ERROR)) { if (PR_NT_CancelIo(sockfd) != PR_SUCCESS) printf("PR_NT_CancelIO: error = %d\n",PR_GetError()); timeout = PR_INTERVAL_NO_TIMEOUT; goto retry; } #endif return -1; } } return len; } /* * writen * write data from buf to sockfd */ static PRInt32 writen(PRFileDesc *sockfd, char *buf, int len) { int rem; int bytes; int offset = 0; for (rem=len; rem; offset += bytes, rem -= bytes) { DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n", PR_GetCurrentThread(), rem)); bytes = PR_Send(sockfd, buf + offset, rem, 0, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n", PR_GetCurrentThread(), bytes)); if (bytes <= 0) return -1; } return len; } /* * Serve_Client * Thread, started by the server, for serving a client connection. * Reads data from socket and writes it back, unmodified, and * closes the socket */ static void PR_CALLBACK Serve_Client(void *arg) { Serve_Client_Param *scp = (Serve_Client_Param *) arg; PRFileDesc *sockfd; buffer *in_buf; PRInt32 bytes, j; sockfd = scp->sockfd; bytes = scp->datalen; in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; goto exit; } for (j = 0; j < num_tcp_mesgs_per_connection; j++) { /* * Read data from client and send it back to the client unmodified */ if (readn(sockfd, in_buf->data, bytes) < bytes) { fprintf(stderr,"prsocket_test: ERROR - Serve_Client:readn\n"); failed_already=1; goto exit; } /* Shutdown only RCV will cause error on Symbian OS */ #if !defined(SYMBIAN) /* * shutdown reads, after the last read */ if (j == num_tcp_mesgs_per_connection - 1) if (PR_Shutdown(sockfd, PR_SHUTDOWN_RCV) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); } #endif DPRINTF(("Serve_Client [0x%lx]: inbuf[0] = 0x%lx\n",PR_GetCurrentThread(), (*((int *) in_buf->data)))); if (writen(sockfd, in_buf->data, bytes) < bytes) { fprintf(stderr,"prsocket_test: ERROR - Serve_Client:writen\n"); failed_already=1; goto exit; } } /* * shutdown reads and writes */ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); failed_already=1; } exit: PR_Close(sockfd); if (in_buf) { PR_DELETE(in_buf); } } PRThread* create_new_thread(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize, PRInt32 index) { PRInt32 native_thread = 0; PR_ASSERT(state == PR_UNJOINABLE_THREAD); #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) switch(index % 4) { case 0: scope = (PR_LOCAL_THREAD); break; case 1: scope = (PR_GLOBAL_THREAD); break; case 2: scope = (PR_GLOBAL_BOUND_THREAD); break; case 3: native_thread = 1; break; default: PR_NOT_REACHED("Invalid scope"); break; } if (native_thread) { #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) pthread_t tid; if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg)) return((PRThread *) tid); else return (NULL); #else HANDLE thandle; unsigned tid; thandle = (HANDLE) _beginthreadex( NULL, stackSize, (unsigned (__stdcall *)(void *))start, arg, STACK_SIZE_PARAM_IS_A_RESERVATION, &tid); return((PRThread *) thandle); #endif } else { return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); } #else return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); #endif } /* * TCP Server * Server Thread * Bind an address to a socket and listen for incoming connections * Start a Serve_Client thread for each incoming connection. */ static void PR_CALLBACK TCP_Server(void *arg) { PRThread *t; Server_Param *sp = (Server_Param *) arg; Serve_Client_Param *scp; PRFileDesc *sockfd, *newsockfd; PRNetAddr netaddr; PRInt32 i; /* * Create a tcp socket */ if ((sockfd = PR_OpenTCPSocket(server_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); goto exit; } memset(&netaddr, 0 , sizeof(netaddr)); if (PR_SetNetAddr(PR_IpAddrAny, server_domain, TCP_SERVER_PORT, &netaddr) == PR_FAILURE) { fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); goto exit; } /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); failed_already=1; goto exit; } if (PR_Listen(sockfd, 32) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); failed_already=1; goto exit; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; goto exit; } DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain, PR_ntohs(PR_NetAddrInetPort(&netaddr)), &tcp_server_addr) == PR_FAILURE) { fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); goto exit; } if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET)) PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK), &tcp_server_addr.ipv6.ip); /* * Wake up parent thread because server address is bound and made * available in the global variable 'tcp_server_addr' */ PR_PostSem(sp->addr_sem); for (i = 0; i < (num_tcp_clients * num_tcp_connections_per_client); i++) { /* test both null and non-null 'addr' argument to PR_Accept */ PRNetAddr *addrp = (i%2 ? &netaddr: NULL); DPRINTF(("TCP_Server: Accepting connection\n")); if ((newsockfd = PR_Accept(sockfd, addrp, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"prsocket_test: ERROR - PR_Accept failed\n"); goto exit; } DPRINTF(("TCP_Server: Accepted connection\n")); scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); goto exit; } /* * Start a Serve_Client thread for each incoming connection */ scp->sockfd = newsockfd; scp->datalen = sp->datalen; t = create_new_thread(PR_USER_THREAD, Serve_Client, (void *)scp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0, i); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; goto exit; } DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", t)); } exit: if (sockfd) { PR_Close(sockfd); } /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("TCP_Server [0x%lx] exiting\n", PR_GetCurrentThread())); } /* * UDP Server * Server Thread * Bind an address to a socket, read data from clients and send data * back to clients */ static void PR_CALLBACK UDP_Server(void *arg) { Server_Param *sp = (Server_Param *) arg; PRFileDesc *sockfd; buffer *in_buf; PRNetAddr netaddr; PRInt32 bytes, i, rv = 0; bytes = sp->datalen; /* * Create a udp socket */ if ((sockfd = PR_OpenUDPSocket(server_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_NewUDPSocket failed\n"); failed_already=1; return; } memset(&netaddr, 0 , sizeof(netaddr)); if (PR_SetNetAddr(PR_IpAddrAny, server_domain, UDP_SERVER_PORT, &netaddr) == PR_FAILURE) { fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); failed_already=1; return; } /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); failed_already=1; return; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; return; } DPRINTF(("PR_Bind: UDP Server netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); /* * We can't use the IP address returned by PR_GetSockName in * netaddr.inet.ip because netaddr.inet.ip is returned * as 0 (= PR_INADDR_ANY). */ if (PR_SetNetAddr(PR_IpAddrLoopback, client_domain, PR_ntohs(PR_NetAddrInetPort(&netaddr)), &udp_server_addr) == PR_FAILURE) { fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); failed_already=1; return; } if ((client_domain == PR_AF_INET6) && (server_domain == PR_AF_INET)) PR_ConvertIPv4AddrToIPv6(PR_htonl(INADDR_LOOPBACK), &udp_server_addr.ipv6.ip); /* * Wake up parent thread because server address is bound and made * available in the global variable 'udp_server_addr' */ PR_PostSem(sp->addr_sem); bytes = sp->datalen; in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } /* * Receive datagrams from clients and send them back, unmodified, to the * clients */ memset(&netaddr, 0 , sizeof(netaddr)); for (i = 0; i < (num_udp_clients * num_udp_datagrams_per_client); i++) { DPRINTF(("UDP_Server: calling PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", netaddr.inet.ip, netaddr.inet.port, bytes, in_buf->data, in_buf->data[0])); rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("UDP_Server: PR_RecvFrom client - ip = 0x%lx, port = %d bytes = %d inbuf = 0x%lx, inbuf[0] = 0x%lx\n", netaddr.inet.ip, netaddr.inet.port, rv, in_buf->data, in_buf->data[0])); if (rv != bytes) { return; } rv = PR_SendTo(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } } PR_DELETE(in_buf); PR_Close(sockfd); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("UDP_Server [0x%x] exiting\n", PR_GetCurrentThread())); } /* * TCP_Client * Client Thread * Connect to the server at the address specified in the argument. * Fill in a buffer, write data to server, read it back and check * for data corruption. * Close the socket for server connection */ static void PR_CALLBACK TCP_Client(void *arg) { Client_Param *cp = (Client_Param *) arg; PRFileDesc *sockfd; buffer *in_buf, *out_buf; union PRNetAddr netaddr; PRInt32 bytes, i, j; bytes = cp->datalen; out_buf = PR_NEW(buffer); if (out_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } netaddr = cp->server_addr; for (i = 0; i < num_tcp_connections_per_client; i++) { if ((sockfd = PR_OpenTCPSocket(client_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n"); failed_already=1; return; } if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; return; } for (j = 0; j < num_tcp_mesgs_per_connection; j++) { /* * fill in random data */ memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes); /* * write to server */ #ifdef WINNT if (test_cancelio && (j == 0)) PR_Sleep(PR_SecondsToInterval(12)); #endif if (writen(sockfd, out_buf->data, bytes) < bytes) { fprintf(stderr,"prsocket_test: ERROR - TCP_Client:writen\n"); failed_already=1; return; } DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n", PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data)))); if (readn(sockfd, in_buf->data, bytes) < bytes) { fprintf(stderr,"prsocket_test: ERROR - TCP_Client:readn\n"); failed_already=1; return; } /* * verify the data read */ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) { fprintf(stderr,"prsocket_test: ERROR - data corruption\n"); failed_already=1; return; } } /* * shutdown reads and writes */ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Shutdown\n"); #if defined(SYMBIAN) if (EPIPE != errno) #endif failed_already=1; } PR_Close(sockfd); } PR_DELETE(out_buf); PR_DELETE(in_buf); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(cp->exit_mon); --(*cp->exit_counter); PR_Notify(cp->exit_mon); PR_ExitMonitor(cp->exit_mon); DPRINTF(("TCP_Client [0x%x] exiting\n", PR_GetCurrentThread())); } /* * UDP_Client * Client Thread * Create a socket and bind an address * Communicate with the server at the address specified in the argument. * Fill in a buffer, write data to server, read it back and check * for data corruption. * Close the socket */ static void PR_CALLBACK UDP_Client(void *arg) { Client_Param *cp = (Client_Param *) arg; PRFileDesc *sockfd; buffer *in_buf, *out_buf; union PRNetAddr netaddr; PRInt32 bytes, i, rv; bytes = cp->datalen; out_buf = PR_NEW(buffer); if (out_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer struct\n"); failed_already=1; return; } if ((sockfd = PR_OpenUDPSocket(client_domain)) == NULL) { fprintf(stderr,"prsocket_test: PR_OpenUDPSocket failed\n"); failed_already=1; return; } /* * bind an address for the client, let the system chose the port * number */ memset(&netaddr, 0 , sizeof(netaddr)); if (PR_SetNetAddr(PR_IpAddrAny, client_domain, 0, &netaddr) == PR_FAILURE) { fprintf(stderr,"prsocket_test: PR_SetNetAddr failed\n"); failed_already=1; return; } if (PR_Bind(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); perror("PR_Bind"); return; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; return; } DPRINTF(("PR_Bind: UDP Client netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); netaddr = cp->server_addr; if (cp->udp_connect) { if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ fprintf(stderr,"prsocket_test: PR_Connect failed\n"); failed_already=1; return; } } for (i = 0; i < num_udp_datagrams_per_client; i++) { /* * fill in random data */ DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx bytes = 0x%lx\n", PR_GetCurrentThread(), out_buf->data, bytes)); memset(out_buf->data, ((PRInt32) (&netaddr)) + i, bytes); /* * write to server */ if (cp->udp_connect) rv = PR_Send(sockfd, out_buf->data, bytes, 0, PR_INTERVAL_NO_TIMEOUT); else rv = PR_SendTo(sockfd, out_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } DPRINTF(("UDP_Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n", PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data)))); if (cp->udp_connect) rv = PR_Recv(sockfd, in_buf->data, bytes, 0, PR_INTERVAL_NO_TIMEOUT); else rv = PR_RecvFrom(sockfd, in_buf->data, bytes, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT); if (rv != bytes) { return; } DPRINTF(("UDP_Client [0x%lx]: in_buf = 0x%lx in_buf[0] = 0x%lx\n", PR_GetCurrentThread(), in_buf, (*((int *) in_buf->data)))); /* * verify the data read */ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) { fprintf(stderr,"prsocket_test: ERROR - UDP data corruption\n"); failed_already=1; return; } } PR_Close(sockfd); PR_DELETE(in_buf); PR_DELETE(out_buf); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(cp->exit_mon); --(*cp->exit_counter); PR_Notify(cp->exit_mon); PR_ExitMonitor(cp->exit_mon); PR_DELETE(cp); DPRINTF(("UDP_Client [0x%x] exiting\n", PR_GetCurrentThread())); } /* * TCP_Socket_Client_Server_Test - concurrent server test * * One server and several clients are started * Each client connects to the server and sends a chunk of data * For each connection, server starts another thread to read the data * from the client and send it back to the client, unmodified. * Each client checks that data received from server is same as the * data it sent to the server. * */ static PRInt32 TCP_Socket_Client_Server_Test(void) { int i; PRThread *t; PRSemaphore *server_sem; Server_Param *sparamp; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; datalen = tcp_mesg_size; thread_count = 0; /* * start the server thread */ sparamp = PR_NEW(Server_Param); if (sparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } server_sem = PR_NewSem(0); if (server_sem == NULL) { fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); failed_already=1; return -1; } mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); failed_already=1; return -1; } PR_EnterMonitor(mon2); sparamp->addr_sem = server_sem; sparamp->exit_mon = mon2; sparamp->exit_counter = &thread_count; sparamp->datalen = datalen; t = PR_CreateThread(PR_USER_THREAD, TCP_Server, (void *)sparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } DPRINTF(("Created TCP server = 0x%lx\n", t)); thread_count++; /* * wait till the server address is setup */ PR_WaitSem(server_sem); /* * Now start a bunch of client threads */ cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } cparamp->server_addr = tcp_server_addr; cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; for (i = 0; i < num_tcp_clients; i++) { t = create_new_thread(PR_USER_THREAD, TCP_Client, (void *) cparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0, i); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } DPRINTF(("Created TCP client = 0x%lx\n", t)); thread_count++; } /* Wait for server and client threads to exit */ while (thread_count) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("TCP Server - thread_count = %d\n", thread_count)); } PR_ExitMonitor(mon2); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); return 0; } /* * UDP_Socket_Client_Server_Test - iterative server test * * One server and several clients are started * Each client connects to the server and sends a chunk of data * For each connection, server starts another thread to read the data * from the client and send it back to the client, unmodified. * Each client checks that data received from server is same as the * data it sent to the server. * */ static PRInt32 UDP_Socket_Client_Server_Test(void) { int i; PRThread *t; PRSemaphore *server_sem; Server_Param *sparamp; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; PRInt32 udp_connect = 1; datalen = udp_datagram_size; thread_count = 0; /* * start the server thread */ sparamp = PR_NEW(Server_Param); if (sparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } server_sem = PR_NewSem(0); if (server_sem == NULL) { fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); failed_already=1; return -1; } mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); failed_already=1; return -1; } PR_EnterMonitor(mon2); sparamp->addr_sem = server_sem; sparamp->exit_mon = mon2; sparamp->exit_counter = &thread_count; sparamp->datalen = datalen; DPRINTF(("Creating UDP server")); t = PR_CreateThread(PR_USER_THREAD, UDP_Server, (void *)sparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } thread_count++; /* * wait till the server address is setup */ PR_WaitSem(server_sem); /* * Now start a bunch of client threads */ for (i = 0; i < num_udp_clients; i++) { cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; return -1; } cparamp->server_addr = udp_server_addr; cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; /* * Cause every other client thread to connect udp sockets */ cparamp->udp_connect = udp_connect; if (udp_connect) udp_connect = 0; else udp_connect = 1; DPRINTF(("Creating UDP client %d\n", i)); t = PR_CreateThread(PR_USER_THREAD, UDP_Client, (void *) cparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; return -1; } thread_count++; } /* Wait for server and client threads to exit */ while (thread_count) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("UDP Server - thread_count = %d\n", thread_count)); } PR_ExitMonitor(mon2); printf("%30s","UDP_Socket_Client_Server_Test: "); printf("%2ld Server %2ld Clients\n",1l, num_udp_clients); printf("%30s %2ld datagrams_per_client %4ld bytes_per_datagram\n",":", num_udp_datagrams_per_client, udp_datagram_size); return 0; } static PRFileDesc *small_file_fd, *large_file_fd; static void *small_file_addr, *small_file_header, *large_file_addr; static void *small_file_trailer, *large_file_header, *large_file_trailer; /* * TransmitFile_Client * Client Thread */ static void TransmitFile_Client(void *arg) { PRFileDesc *sockfd; union PRNetAddr netaddr; char *small_buf, *large_buf; Client_Param *cp = (Client_Param *) arg; PRInt32 rlen; small_buf = (char*)PR_Malloc(SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE + SMALL_FILE_TRAILER_SIZE); if (small_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer\n"); failed_already=1; return; } large_buf = (char*)PR_Malloc(LARGE_FILE_SIZE + LARGE_FILE_HEADER_SIZE + LARGE_FILE_TRAILER_SIZE); if (large_buf == NULL) { fprintf(stderr,"prsocket_test: failed to alloc buffer\n"); failed_already=1; return; } netaddr.inet.family = cp->server_addr.inet.family; netaddr.inet.port = cp->server_addr.inet.port; netaddr.inet.ip = cp->server_addr.inet.ip; if ((sockfd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"prsocket_test: PR_NewTCPSocket failed\n"); failed_already=1; return; } if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ fprintf(stderr,"prsocket_test: PR_Connect failed\n"); failed_already=1; return; } /* * read the small file and verify the data */ if (readn(sockfd, small_buf, SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE) != (SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE)) { fprintf(stderr, "prsocket_test: TransmitFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) /* File transmission test can not be done because of large file's size */ if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "prsocket_test: TransmitFile_Client ERROR - small file header data corruption\n"); failed_already=1; return; } if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_SIZE) != 0) { fprintf(stderr, "prsocket_test: TransmitFile_Client ERROR - small file data corruption\n"); failed_already=1; return; } #endif /* * read the large file and verify the data */ if (readn(sockfd, large_buf, LARGE_FILE_SIZE) != LARGE_FILE_SIZE) { fprintf(stderr, "prsocket_test: TransmitFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(large_file_addr, large_buf, LARGE_FILE_SIZE) != 0) { fprintf(stderr, "prsocket_test: TransmitFile_Client ERROR - large file data corruption\n"); failed_already=1; } #endif /* * receive data from PR_SendFile */ /* * case 1: small file with header and trailer */ rlen = SMALL_FILE_SIZE + SMALL_FILE_HEADER_SIZE + SMALL_FILE_TRAILER_SIZE; if (readn(sockfd, small_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 1. ERROR - small file header corruption\n"); failed_already=1; return; } if (memcmp(small_file_addr, small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_SIZE) != 0) { fprintf(stderr, "SendFile 1. ERROR - small file data corruption\n"); failed_already=1; return; } if (memcmp(small_file_trailer, small_buf + SMALL_FILE_HEADER_SIZE + SMALL_FILE_SIZE, SMALL_FILE_TRAILER_SIZE) != 0) { fprintf(stderr, "SendFile 1. ERROR - small file trailer corruption\n"); failed_already=1; return; } #endif /* * case 2: partial large file at zero offset, file with header and trailer */ rlen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE + LARGE_FILE_TRAILER_SIZE; if (readn(sockfd, large_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 2. ERROR - large file header corruption\n"); failed_already=1; return; } if (memcmp(large_file_addr, large_buf + LARGE_FILE_HEADER_SIZE, LARGE_FILE_LEN_1) != 0) { fprintf(stderr, "SendFile 2. ERROR - large file data corruption\n"); failed_already=1; return; } if (memcmp(large_file_trailer, large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_1, LARGE_FILE_TRAILER_SIZE) != 0) { fprintf(stderr, "SendFile 2. ERROR - large file trailer corruption\n"); failed_already=1; return; } #endif /* * case 3: partial small file at non-zero offset, with header */ rlen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE; if (readn(sockfd, small_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 3. ERROR - small file header corruption\n"); failed_already=1; return; } if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_1, small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_1) != 0) { fprintf(stderr, "SendFile 3. ERROR - small file data corruption\n"); failed_already=1; return; } #endif /* * case 4: partial small file at non-zero offset, with trailer */ rlen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE; if (readn(sockfd, small_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_2, small_buf, SMALL_FILE_LEN_2) != 0) { fprintf(stderr, "SendFile 4. ERROR - small file data corruption\n"); failed_already=1; return; } if (memcmp(small_file_trailer, small_buf + SMALL_FILE_LEN_2, SMALL_FILE_TRAILER_SIZE) != 0) { fprintf(stderr, "SendFile 4. ERROR - small file trailer corruption\n"); failed_already=1; return; } #endif /* * case 5: partial large file at non-zero offset, file with header */ rlen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE; if (readn(sockfd, large_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 5. ERROR - large file header corruption\n"); failed_already=1; return; } if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_2, large_buf + LARGE_FILE_HEADER_SIZE, LARGE_FILE_LEN_2) != 0) { fprintf(stderr, "SendFile 5. ERROR - large file data corruption\n"); failed_already=1; return; } #endif /* * case 6: partial small file at non-zero offset, with header */ rlen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE; if (readn(sockfd, small_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(small_file_header, small_buf, SMALL_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 6. ERROR - small file header corruption\n"); return; } if (memcmp((char *) small_file_addr + SMALL_FILE_OFFSET_3, small_buf + SMALL_FILE_HEADER_SIZE, SMALL_FILE_LEN_3) != 0) { #if 0 char *i, *j; int k; i = (char *) small_file_addr + SMALL_FILE_OFFSET_3; j = small_buf + SMALL_FILE_HEADER_SIZE; k = SMALL_FILE_LEN_3; while (k-- > 0) { if (*i++ != *j++) printf("i = %d j = %d\n", (int) (i - ((char *) small_file_addr + SMALL_FILE_OFFSET_3)), (int) (j - (small_buf + SMALL_FILE_HEADER_SIZE))); } #endif fprintf(stderr, "SendFile 6. ERROR - small file data corruption\n"); failed_already=1; return; } #endif /* * case 7: partial large file at non-zero offset, with header */ rlen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE; if (readn(sockfd, large_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 7. ERROR - large file header corruption\n"); failed_already=1; return; } if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_3, large_buf + LARGE_FILE_HEADER_SIZE, LARGE_FILE_LEN_3) != 0) { fprintf(stderr, "SendFile 7. ERROR - large file data corruption\n"); failed_already=1; return; } #endif /* * case 8: partial large file at non-zero, page-aligned offset, with * header and trailer */ rlen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE + LARGE_FILE_TRAILER_SIZE; if (readn(sockfd, large_buf, rlen) != rlen) { fprintf(stderr, "prsocket_test: SendFile_Client failed to receive file\n"); failed_already=1; return; } #if defined(XP_UNIX) && !defined(SYMBIAN) if (memcmp(large_file_header, large_buf, LARGE_FILE_HEADER_SIZE) != 0){ fprintf(stderr, "SendFile 2. ERROR - large file header corruption\n"); failed_already=1; return; } if (memcmp((char *)large_file_addr + LARGE_FILE_OFFSET_4, large_buf + LARGE_FILE_HEADER_SIZE, LARGE_FILE_LEN_4) != 0) { fprintf(stderr, "SendFile 2. ERROR - large file data corruption\n"); failed_already=1; return; } if (memcmp(large_file_trailer, large_buf + LARGE_FILE_HEADER_SIZE + LARGE_FILE_LEN_4, LARGE_FILE_TRAILER_SIZE) != 0) { fprintf(stderr, "SendFile 2. ERROR - large file trailer corruption\n"); failed_already=1; return; } #endif PR_DELETE(small_buf); PR_DELETE(large_buf); PR_Close(sockfd); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(cp->exit_mon); --(*cp->exit_counter); PR_Notify(cp->exit_mon); PR_ExitMonitor(cp->exit_mon); DPRINTF(("TransmitFile_Client [0x%lx] exiting\n", PR_GetCurrentThread())); } /* * Serve_TransmitFile_Client * Thread, started by the server, for serving a client connection. * Trasmits a small file, with a header, and a large file, without * a header */ static void Serve_TransmitFile_Client(void *arg) { Serve_Client_Param *scp = (Serve_Client_Param *) arg; PRFileDesc *sockfd; PRInt32 bytes; PRFileDesc *local_small_file_fd=NULL; PRFileDesc *local_large_file_fd=NULL; PRSendFileData sfd; PRInt32 slen; sockfd = scp->sockfd; local_small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDONLY,0); if (local_small_file_fd == NULL) { fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n", SMALL_FILE_NAME); failed_already=1; goto done; } local_large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDONLY,0); if (local_large_file_fd == NULL) { fprintf(stderr,"prsocket_test failed to open file for transmitting %s\n", LARGE_FILE_NAME); failed_already=1; goto done; } bytes = PR_TransmitFile(sockfd, local_small_file_fd, small_file_header, SMALL_FILE_HEADER_SIZE, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (bytes != (SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE)) { fprintf(stderr, "prsocet_test: PR_TransmitFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } bytes = PR_TransmitFile(sockfd, local_large_file_fd, NULL, 0, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); if (bytes != LARGE_FILE_SIZE) { fprintf(stderr, "prsocket_test: PR_TransmitFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * PR_SendFile test cases */ /* * case 1: small file with header and trailer */ sfd.fd = local_small_file_fd; sfd.file_offset = 0; sfd.file_nbytes = 0; sfd.header = small_file_header; sfd.hlen = SMALL_FILE_HEADER_SIZE; sfd.trailer = small_file_trailer; sfd.tlen = SMALL_FILE_TRAILER_SIZE; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = SMALL_FILE_SIZE+ SMALL_FILE_HEADER_SIZE + SMALL_FILE_TRAILER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 1. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 2: partial large file at zero offset, file with header and trailer */ sfd.fd = local_large_file_fd; sfd.file_offset = 0; sfd.file_nbytes = LARGE_FILE_LEN_1; sfd.header = large_file_header; sfd.hlen = LARGE_FILE_HEADER_SIZE; sfd.trailer = large_file_trailer; sfd.tlen = LARGE_FILE_TRAILER_SIZE; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = LARGE_FILE_LEN_1 + LARGE_FILE_HEADER_SIZE + LARGE_FILE_TRAILER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 3: partial small file at non-zero offset, with header */ sfd.fd = local_small_file_fd; sfd.file_offset = SMALL_FILE_OFFSET_1; sfd.file_nbytes = SMALL_FILE_LEN_1; sfd.header = small_file_header; sfd.hlen = SMALL_FILE_HEADER_SIZE; sfd.trailer = NULL; sfd.tlen = 0; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = SMALL_FILE_LEN_1 + SMALL_FILE_HEADER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 3. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 4: partial small file at non-zero offset, with trailer */ sfd.fd = local_small_file_fd; sfd.file_offset = SMALL_FILE_OFFSET_2; sfd.file_nbytes = SMALL_FILE_LEN_2; sfd.header = NULL; sfd.hlen = 0; sfd.trailer = small_file_trailer; sfd.tlen = SMALL_FILE_TRAILER_SIZE; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = SMALL_FILE_LEN_2 + SMALL_FILE_TRAILER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 4. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 5: partial large file at non-zero offset, file with header */ sfd.fd = local_large_file_fd; sfd.file_offset = LARGE_FILE_OFFSET_2; sfd.file_nbytes = LARGE_FILE_LEN_2; sfd.header = large_file_header; sfd.hlen = LARGE_FILE_HEADER_SIZE; sfd.trailer = NULL; sfd.tlen = 0; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = LARGE_FILE_LEN_2 + LARGE_FILE_HEADER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 5. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 6: partial small file from non-zero offset till end of file, with header */ sfd.fd = local_small_file_fd; sfd.file_offset = SMALL_FILE_OFFSET_3; sfd.file_nbytes = 0; /* data from offset to end-of-file */ sfd.header = small_file_header; sfd.hlen = SMALL_FILE_HEADER_SIZE; sfd.trailer = NULL; sfd.tlen = 0; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = SMALL_FILE_LEN_3 + SMALL_FILE_HEADER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 6. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 7: partial large file at non-zero offset till end-of-file, with header */ sfd.fd = local_large_file_fd; sfd.file_offset = LARGE_FILE_OFFSET_3; sfd.file_nbytes = 0; /* data until end-of-file */ sfd.header = large_file_header; sfd.hlen = LARGE_FILE_HEADER_SIZE; sfd.trailer = NULL; sfd.tlen = 0; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_KEEP_OPEN, PR_INTERVAL_NO_TIMEOUT); slen = LARGE_FILE_LEN_3 + LARGE_FILE_HEADER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 7. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } /* * case 8: partial large file at non-zero page-aligned offset, * with header and trailer */ sfd.fd = local_large_file_fd; sfd.file_offset = LARGE_FILE_OFFSET_4; sfd.file_nbytes = LARGE_FILE_LEN_4; sfd.header = large_file_header; sfd.hlen = LARGE_FILE_HEADER_SIZE; sfd.trailer = large_file_trailer; sfd.tlen = LARGE_FILE_TRAILER_SIZE; bytes = PR_SendFile(sockfd, &sfd, PR_TRANSMITFILE_CLOSE_SOCKET, PR_INTERVAL_NO_TIMEOUT); slen = LARGE_FILE_LEN_4 + LARGE_FILE_HEADER_SIZE + LARGE_FILE_TRAILER_SIZE; if (bytes != slen) { fprintf(stderr, "socket: Error - 2. PR_SendFile send_size = %d, bytes sent = %d\n", slen, bytes); fprintf(stderr, "prsocket_test: PR_SendFile failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; } done: if (local_small_file_fd != NULL) PR_Close(local_small_file_fd); if (local_large_file_fd != NULL) PR_Close(local_large_file_fd); } /* * TransmitFile Server * Server Thread * Bind an address to a socket and listen for incoming connections * Create worker threads to service clients */ static void TransmitFile_Server(void *arg) { PRThread **t = NULL; /* an array of PRThread pointers */ Server_Param *sp = (Server_Param *) arg; Serve_Client_Param *scp; PRFileDesc *sockfd = NULL, *newsockfd; PRNetAddr netaddr; PRInt32 i; t = (PRThread**)PR_MALLOC(num_transmitfile_clients * sizeof(PRThread *)); if (t == NULL) { fprintf(stderr, "prsocket_test: run out of memory\n"); failed_already=1; goto exit; } /* * Create a tcp socket */ if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) { fprintf(stderr,"prsocket_test: PR_OpenTCPSocket failed\n"); failed_already=1; goto exit; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = PR_AF_INET; netaddr.inet.port = PR_htons(TCP_SERVER_PORT); netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"prsocket_test: ERROR - PR_Bind failed\n"); failed_already=1; perror("PR_Bind"); goto exit; } if (PR_Listen(sockfd, 32) < 0) { fprintf(stderr,"prsocket_test: ERROR - PR_Listen failed\n"); failed_already=1; goto exit; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr, "prsocket_test: ERROR - PR_GetSockName failed\n"); failed_already=1; goto exit; } DPRINTF(("TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); tcp_server_addr.inet.family = netaddr.inet.family; tcp_server_addr.inet.port = netaddr.inet.port; tcp_server_addr.inet.ip = netaddr.inet.ip; /* * Wake up parent thread because server address is bound and made * available in the global variable 'tcp_server_addr' */ PR_PostSem(sp->addr_sem); for (i = 0; i < num_transmitfile_clients ; i++) { /* test both null and non-null 'addr' argument to PR_Accept */ PRNetAddr *addrp = (i%2 ? &netaddr: NULL); if ((newsockfd = PR_Accept(sockfd, addrp, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr, "prsocket_test: ERROR - PR_Accept failed\n"); failed_already=1; goto exit; } /* test both regular and emulated PR_SendFile */ if (i%2) { PRFileDesc *layer = PR_CreateIOLayerStub( emuSendFileIdentity, &emuSendFileMethods); if (layer == NULL) { fprintf(stderr, "prsocket_test: ERROR - PR_CreateIOLayerStub failed\n"); failed_already=1; goto exit; } if (PR_PushIOLayer(newsockfd, PR_TOP_IO_LAYER, layer) == PR_FAILURE) { fprintf(stderr, "prsocket_test: ERROR - PR_PushIOLayer failed\n"); failed_already=1; goto exit; } } scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; goto exit; } /* * Start a Serve_Client thread for each incoming connection */ scp->sockfd = newsockfd; scp->datalen = sp->datalen; t[i] = PR_CreateThread(PR_USER_THREAD, Serve_TransmitFile_Client, (void *)scp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); if (t[i] == NULL) { fprintf(stderr, "prsocket_test: PR_CreateThread failed\n"); failed_already=1; goto exit; } DPRINTF(("TransmitFile_Server: Created Serve_TransmitFile_Client = 0x%lx\n", t)); } /* * Wait for all the worker threads to end, so that we know * they are no longer using the small and large file fd's. */ for (i = 0; i < num_transmitfile_clients; i++) { PR_JoinThread(t[i]); } exit: if (t) { PR_DELETE(t); } if (sockfd) { PR_Close(sockfd); } /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(sp->exit_mon); --(*sp->exit_counter); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); DPRINTF(("TransmitFile_Server [0x%lx] exiting\n", PR_GetCurrentThread())); } /* * Socket_Misc_Test - test miscellaneous functions * */ static PRInt32 Socket_Misc_Test(void) { PRIntn i, rv = 0, bytes, count, len; PRThread *t; PRSemaphore *server_sem; Server_Param *sparamp; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; /* * We deliberately pick a buffer size that is not a nice multiple * of 1024. */ #define TRANSMITFILE_BUF_SIZE (4 * 1024 - 11) typedef struct { char data[TRANSMITFILE_BUF_SIZE]; } file_buf; file_buf *buf = NULL; /* * create file(s) to be transmitted */ if ((PR_MkDir(TEST_DIR, 0777)) < 0) { printf("prsocket_test failed to create dir %s\n",TEST_DIR); failed_already=1; return -1; } small_file_fd = PR_Open(SMALL_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); if (small_file_fd == NULL) { fprintf(stderr,"prsocket_test failed to create/open file %s\n", SMALL_FILE_NAME); failed_already=1; rv = -1; goto done; } buf = PR_NEW(file_buf); if (buf == NULL) { fprintf(stderr,"prsocket_test failed to allocate buffer\n"); failed_already=1; rv = -1; goto done; } /* * fill in random data */ for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { buf->data[i] = i; } count = 0; do { len = (SMALL_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ? TRANSMITFILE_BUF_SIZE : (SMALL_FILE_SIZE - count); bytes = PR_Write(small_file_fd, buf->data, len); if (bytes <= 0) { fprintf(stderr, "prsocket_test failed to write to file %s\n", SMALL_FILE_NAME); failed_already=1; rv = -1; goto done; } count += bytes; } while (count < SMALL_FILE_SIZE); #ifdef XP_UNIX /* * map the small file; used in checking for data corruption */ small_file_addr = mmap(0, SMALL_FILE_SIZE, PROT_READ, MAP_SHARED, small_file_fd->secret->md.osfd, 0); if (small_file_addr == (void *) -1) { fprintf(stderr,"prsocket_test failed to mmap file %s\n", SMALL_FILE_NAME); failed_already=1; rv = -1; goto done; } #endif /* * header for small file */ small_file_header = PR_MALLOC(SMALL_FILE_HEADER_SIZE); if (small_file_header == NULL) { fprintf(stderr,"prsocket_test failed to malloc header file\n"); failed_already=1; rv = -1; goto done; } memset(small_file_header, (int) PR_IntervalNow(), SMALL_FILE_HEADER_SIZE); /* * trailer for small file */ small_file_trailer = PR_MALLOC(SMALL_FILE_TRAILER_SIZE); if (small_file_trailer == NULL) { fprintf(stderr,"prsocket_test failed to malloc header trailer\n"); failed_already=1; rv = -1; goto done; } memset(small_file_trailer, (int) PR_IntervalNow(), SMALL_FILE_TRAILER_SIZE); /* * setup large file */ large_file_fd = PR_Open(LARGE_FILE_NAME, PR_RDWR | PR_CREATE_FILE,0777); if (large_file_fd == NULL) { fprintf(stderr,"prsocket_test failed to create/open file %s\n", LARGE_FILE_NAME); failed_already=1; rv = -1; goto done; } /* * fill in random data */ for (i = 0; i < TRANSMITFILE_BUF_SIZE; i++) { buf->data[i] = i; } count = 0; do { len = (LARGE_FILE_SIZE - count) > TRANSMITFILE_BUF_SIZE ? TRANSMITFILE_BUF_SIZE : (LARGE_FILE_SIZE - count); bytes = PR_Write(large_file_fd, buf->data, len); if (bytes <= 0) { fprintf(stderr, "prsocket_test failed to write to file %s: (%ld, %ld)\n", LARGE_FILE_NAME, PR_GetError(), PR_GetOSError()); failed_already=1; rv = -1; goto done; } count += bytes; } while (count < LARGE_FILE_SIZE); #if defined(XP_UNIX) && !defined(SYMBIAN) /* * map the large file; used in checking for data corruption */ large_file_addr = mmap(0, LARGE_FILE_SIZE, PROT_READ, MAP_SHARED, large_file_fd->secret->md.osfd, 0); if (large_file_addr == (void *) -1) { fprintf(stderr,"prsocket_test failed to mmap file %s\n", LARGE_FILE_NAME); failed_already=1; rv = -1; goto done; } #endif /* * header for large file */ large_file_header = PR_MALLOC(LARGE_FILE_HEADER_SIZE); if (large_file_header == NULL) { fprintf(stderr,"prsocket_test failed to malloc header file\n"); failed_already=1; rv = -1; goto done; } memset(large_file_header, (int) PR_IntervalNow(), LARGE_FILE_HEADER_SIZE); /* * trailer for large file */ large_file_trailer = PR_MALLOC(LARGE_FILE_TRAILER_SIZE); if (large_file_trailer == NULL) { fprintf(stderr,"prsocket_test failed to malloc header trailer\n"); failed_already=1; rv = -1; goto done; } memset(large_file_trailer, (int) PR_IntervalNow(), LARGE_FILE_TRAILER_SIZE); datalen = tcp_mesg_size; thread_count = 0; /* * start the server thread */ sparamp = PR_NEW(Server_Param); if (sparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; rv = -1; goto done; } server_sem = PR_NewSem(0); if (server_sem == NULL) { fprintf(stderr,"prsocket_test: PR_NewSem failed\n"); failed_already=1; rv = -1; goto done; } mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"prsocket_test: PR_NewMonitor failed\n"); failed_already=1; rv = -1; goto done; } PR_EnterMonitor(mon2); sparamp->addr_sem = server_sem; sparamp->exit_mon = mon2; sparamp->exit_counter = &thread_count; sparamp->datalen = datalen; t = PR_CreateThread(PR_USER_THREAD, TransmitFile_Server, (void *)sparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); failed_already=1; rv = -1; goto done; } DPRINTF(("Created TCP server = 0x%x\n", t)); thread_count++; /* * wait till the server address is setup */ PR_WaitSem(server_sem); /* * Now start a bunch of client threads */ cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"prsocket_test: PR_NEW failed\n"); failed_already=1; rv = -1; goto done; } cparamp->server_addr = tcp_server_addr; cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); cparamp->exit_mon = mon2; cparamp->exit_counter = &thread_count; cparamp->datalen = datalen; for (i = 0; i < num_transmitfile_clients; i++) { t = create_new_thread(PR_USER_THREAD, TransmitFile_Client, (void *) cparamp, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0, i); if (t == NULL) { fprintf(stderr,"prsocket_test: PR_CreateThread failed\n"); rv = -1; failed_already=1; goto done; } DPRINTF(("Created TransmitFile client = 0x%lx\n", t)); thread_count++; } /* Wait for server and client threads to exit */ while (thread_count) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("Socket_Misc_Test - thread_count = %d\n", thread_count)); } PR_ExitMonitor(mon2); done: if (buf) { PR_DELETE(buf); } #if defined(XP_UNIX) && !defined(SYMBIAN) munmap((char*)small_file_addr, SMALL_FILE_SIZE); munmap((char*)large_file_addr, LARGE_FILE_SIZE); #endif PR_Close(small_file_fd); PR_Close(large_file_fd); if ((PR_Delete(SMALL_FILE_NAME)) == PR_FAILURE) { fprintf(stderr,"prsocket_test: failed to unlink file %s\n", SMALL_FILE_NAME); failed_already=1; } if ((PR_Delete(LARGE_FILE_NAME)) == PR_FAILURE) { fprintf(stderr,"prsocket_test: failed to unlink file %s\n", LARGE_FILE_NAME); failed_already=1; } if ((PR_RmDir(TEST_DIR)) == PR_FAILURE) { fprintf(stderr,"prsocket_test failed to rmdir %s: (%ld, %ld)\n", TEST_DIR, PR_GetError(), PR_GetOSError()); failed_already=1; } printf("%-29s%s","Socket_Misc_Test",":"); printf("%2d Server %2d Clients\n",1, num_transmitfile_clients); printf("%30s Sizes of Transmitted Files - %4d KB, %2d MB \n",":", SMALL_FILE_SIZE/1024, LARGE_FILE_SIZE/(1024 * 1024)); return rv; } /************************************************************************/ /* * Test Socket NSPR APIs */ int main(int argc, char **argv) { /* * -d debug mode */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetConcurrency(4); emuSendFileIdentity = PR_GetUniqueIdentity("Emulated SendFile"); emuSendFileMethods = *PR_GetDefaultIOMethods(); emuSendFileMethods.transmitfile = emu_TransmitFile; emuSendFileMethods.sendfile = emu_SendFile; /* * run client-server test with TCP, Ipv4-Ipv4 */ printf("TCP Client/Server Test - IPv4/Ipv4\n"); if (TCP_Socket_Client_Server_Test() < 0) { printf("TCP_Socket_Client_Server_Test failed\n"); goto done; } else printf("TCP_Socket_Client_Server_Test Passed\n"); /* * client-server test, Ipv6-Ipv4 */ client_domain = PR_AF_INET6; printf("TCP Client/Server Test - IPv6/Ipv4\n"); if (TCP_Socket_Client_Server_Test() < 0) { printf("TCP_Socket_Client_Server_Test failed\n"); goto done; } else printf("TCP_Socket_Client_Server_Test Passed\n"); /* * client-server test, Ipv4-Ipv6 */ client_domain = PR_AF_INET; server_domain = PR_AF_INET6; printf("TCP Client/Server Test - IPv4/Ipv6\n"); if (TCP_Socket_Client_Server_Test() < 0) { printf("TCP_Socket_Client_Server_Test failed\n"); goto done; } else printf("TCP_Socket_Client_Server_Test Passed\n"); /* * client-server test, Ipv6-Ipv6 */ client_domain = PR_AF_INET6; server_domain = PR_AF_INET6; printf("TCP Client/Server Test - IPv6/Ipv6\n"); if (TCP_Socket_Client_Server_Test() < 0) { printf("TCP_Socket_Client_Server_Test failed\n"); goto done; } else printf("TCP_Socket_Client_Server_Test Passed\n"); test_cancelio = 0; #if defined(SYMBIAN) && !defined(__WINSCW__) /* UDP tests only run on Symbian devices but not emulator */ /* * run client-server test with UDP, IPv4/IPv4 */ printf("UDP Client/Server Test - IPv4/Ipv4\n"); client_domain = PR_AF_INET; server_domain = PR_AF_INET; if (UDP_Socket_Client_Server_Test() < 0) { printf("UDP_Socket_Client_Server_Test failed\n"); goto done; } else printf("UDP_Socket_Client_Server_Test Passed\n"); /* * run client-server test with UDP, IPv6/IPv4 */ printf("UDP Client/Server Test - IPv6/Ipv4\n"); client_domain = PR_AF_INET6; server_domain = PR_AF_INET; if (UDP_Socket_Client_Server_Test() < 0) { printf("UDP_Socket_Client_Server_Test failed\n"); goto done; } else printf("UDP_Socket_Client_Server_Test Passed\n"); /* * run client-server test with UDP,IPv4-IPv6 */ printf("UDP Client/Server Test - IPv4/Ipv6\n"); client_domain = PR_AF_INET; server_domain = PR_AF_INET6; if (UDP_Socket_Client_Server_Test() < 0) { printf("UDP_Socket_Client_Server_Test failed\n"); goto done; } else printf("UDP_Socket_Client_Server_Test Passed\n"); /* * run client-server test with UDP,IPv6-IPv6 */ printf("UDP Client/Server Test - IPv6/Ipv6\n"); client_domain = PR_AF_INET6; server_domain = PR_AF_INET6; if (UDP_Socket_Client_Server_Test() < 0) { printf("UDP_Socket_Client_Server_Test failed\n"); goto done; } else printf("UDP_Socket_Client_Server_Test Passed\n"); #endif /* * Misc socket tests - including transmitfile, etc. */ /* File transmission test can not be done in Symbian OS because of * large file's size and the incomplete mmap() implementation. */ #if !defined(WIN16) && !defined(SYMBIAN) /* ** The 'transmit file' test does not run because ** transmit file is not implemented in NSPR yet. ** */ if (Socket_Misc_Test() < 0) { printf("Socket_Misc_Test failed\n"); failed_already=1; goto done; } else printf("Socket_Misc_Test passed\n"); /* * run client-server test with TCP again to test * recycling used sockets from PR_TransmitFile(). */ if (TCP_Socket_Client_Server_Test() < 0) { printf("TCP_Socket_Client_Server_Test failed\n"); goto done; } else printf("TCP_Socket_Client_Server_Test Passed\n"); #endif done: PR_Cleanup(); if (failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/sockopt.c0000644000000000000000000001330512623070344015145 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "prio.h" #include "prinit.h" #include "prprf.h" #include "obsolete/probslet.h" #include "plerror.h" #ifdef XP_UNIX #include /* SO_REUSEPORT */ #endif static PRFileDesc *err = NULL; static PRBool failed = PR_FALSE; static void Failed(const char *msg1, const char *msg2) { if (NULL != msg1) PR_fprintf(err, "%s ", msg1); PL_FPrintError(err, msg2); failed = PR_TRUE; } /* Failed */ static PRSockOption Incr(PRSockOption *option) { PRIntn val = ((PRIntn)*option) + 1; *option = (PRSockOption)val; return (PRSockOption)val; } /* Incr */ int main(int argc, char **argv) { PRStatus rv; PRFileDesc *udp = PR_NewUDPSocket(); PRFileDesc *tcp = PR_NewTCPSocket(); const char *tag[] = { "PR_SockOpt_Nonblocking", /* nonblocking io */ "PR_SockOpt_Linger", /* linger on close if data present */ "PR_SockOpt_Reuseaddr", /* allow local address reuse */ "PR_SockOpt_Keepalive", /* keep connections alive */ "PR_SockOpt_RecvBufferSize", /* send buffer size */ "PR_SockOpt_SendBufferSize", /* receive buffer size */ "PR_SockOpt_IpTimeToLive", /* time to live */ "PR_SockOpt_IpTypeOfService", /* type of service and precedence */ "PR_SockOpt_AddMember", /* add an IP group membership */ "PR_SockOpt_DropMember", /* drop an IP group membership */ "PR_SockOpt_McastInterface", /* multicast interface address */ "PR_SockOpt_McastTimeToLive", /* multicast timetolive */ "PR_SockOpt_McastLoopback", /* multicast loopback */ "PR_SockOpt_NoDelay", /* don't delay send to coalesce packets */ "PR_SockOpt_MaxSegment", /* maximum segment size */ "PR_SockOpt_Broadcast", /* Enable broadcast */ "PR_SockOpt_Reuseport", /* allow local address & port reuse */ "PR_SockOpt_Last" }; err = PR_GetSpecialFD(PR_StandardError); PR_STDIO_INIT(); if (NULL == udp) Failed("PR_NewUDPSocket()", NULL); else if (NULL == tcp) Failed("PR_NewTCPSocket()", NULL); else { PRSockOption option; PRUint32 segment = 1024; PRNetAddr addr; rv = PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr); if (PR_FAILURE == rv) Failed("PR_InitializeNetAddr()", NULL); rv = PR_Bind(udp, &addr); if (PR_FAILURE == rv) Failed("PR_Bind()", NULL); for(option = PR_SockOpt_Linger; option < PR_SockOpt_Last; Incr(&option)) { PRSocketOptionData data; PRFileDesc *fd = tcp; data.option = option; switch (option) { case PR_SockOpt_Nonblocking: data.value.non_blocking = PR_TRUE; break; #ifndef SYMBIAN case PR_SockOpt_Linger: data.value.linger.polarity = PR_TRUE; data.value.linger.linger = PR_SecondsToInterval(2); break; #endif case PR_SockOpt_Reuseaddr: data.value.reuse_addr = PR_TRUE; break; case PR_SockOpt_Keepalive: data.value.keep_alive = PR_TRUE; break; case PR_SockOpt_RecvBufferSize: data.value.recv_buffer_size = segment; break; case PR_SockOpt_SendBufferSize: data.value.send_buffer_size = segment; break; #ifndef SYMBIAN case PR_SockOpt_IpTimeToLive: data.value.ip_ttl = 64; break; case PR_SockOpt_IpTypeOfService: data.value.tos = 0; break; case PR_SockOpt_McastTimeToLive: fd = udp; data.value.mcast_ttl = 4; break; case PR_SockOpt_McastLoopback: fd = udp; data.value.mcast_loopback = PR_TRUE; break; #endif case PR_SockOpt_NoDelay: data.value.no_delay = PR_TRUE; break; #ifndef WIN32 case PR_SockOpt_MaxSegment: data.value.max_segment = segment; break; #endif #ifndef SYMBIAN case PR_SockOpt_Broadcast: fd = udp; data.value.broadcast = PR_TRUE; break; #endif #ifdef SO_REUSEPORT case PR_SockOpt_Reuseport: data.value.reuse_port = PR_TRUE; break; #endif default: continue; } /* * TCP_MAXSEG can only be read, not set */ if (option != PR_SockOpt_MaxSegment) { #ifdef WIN32 if (option != PR_SockOpt_McastLoopback) #endif { rv = PR_SetSocketOption(fd, &data); if (PR_FAILURE == rv) Failed("PR_SetSocketOption()", tag[option]); } } rv = PR_GetSocketOption(fd, &data); if (PR_FAILURE == rv) Failed("PR_GetSocketOption()", tag[option]); } PR_Close(udp); PR_Close(tcp); } PR_fprintf(err, "%s\n", (failed) ? "FAILED" : "PASSED"); return (failed) ? 1 : 0; } /* main */ /* sockopt.c */ nspr-4.11/nspr/pr/tests/sockping.c0000644000000000000000000000735612623070344015311 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: sockping.c * * Description: * This test runs in conjunction with the sockpong test. * This test creates a socket pair and passes one socket * to the sockpong test. Then this test writes "ping" to * to the sockpong test and the sockpong test writes "pong" * back. To run this pair of tests, just invoke sockping. * * Tested areas: process creation, socket pairs, file * descriptor inheritance. */ #include "prerror.h" #include "prio.h" #include "prproces.h" #include #include #include #define NUM_ITERATIONS 10 static char *child_argv[] = { "sockpong", NULL }; int main(int argc, char **argv) { PRFileDesc *sock[2]; PRStatus status; PRProcess *process; PRProcessAttr *attr; char buf[1024]; PRInt32 nBytes; PRInt32 exitCode; int idx; status = PR_NewTCPSocketPair(sock); if (status == PR_FAILURE) { fprintf(stderr, "PR_NewTCPSocketPair failed\n"); exit(1); } status = PR_SetFDInheritable(sock[0], PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } status = PR_SetFDInheritable(sock[1], PR_TRUE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } attr = PR_NewProcessAttr(); if (attr == NULL) { fprintf(stderr, "PR_NewProcessAttr failed\n"); exit(1); } status = PR_ProcessAttrSetInheritableFD(attr, sock[1], "SOCKET"); if (status == PR_FAILURE) { fprintf(stderr, "PR_ProcessAttrSetInheritableFD failed\n"); exit(1); } process = PR_CreateProcess(child_argv[0], child_argv, NULL, attr); if (process == NULL) { fprintf(stderr, "PR_CreateProcess failed\n"); exit(1); } PR_DestroyProcessAttr(attr); status = PR_Close(sock[1]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { strcpy(buf, "ping"); printf("ping process: sending \"%s\"\n", buf); nBytes = PR_Write(sock[0], buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } memset(buf, 0, sizeof(buf)); nBytes = PR_Read(sock[0], buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("ping process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "ping process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "pong") != 0) { fprintf(stderr, "ping process: expected \"pong\" but got \"%s\"\n", buf); exit(1); } } status = PR_Close(sock[0]); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } status = PR_WaitProcess(process, &exitCode); if (status == PR_FAILURE) { fprintf(stderr, "PR_WaitProcess failed\n"); exit(1); } if (exitCode == 0) { printf("PASS\n"); return 0; } else { printf("FAIL\n"); return 1; } } nspr-4.11/nspr/pr/tests/sockpong.c0000644000000000000000000000446212623070344015312 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: sockpong.c * * Description: * This test runs in conjunction with the sockping test. * The sockping test creates a socket pair and passes one * socket to this test. Then the sockping test writes * "ping" to this test and this test writes "pong" back. * To run this pair of tests, just invoke sockping. * * Tested areas: process creation, socket pairs, file * descriptor inheritance. */ #include "prerror.h" #include "prio.h" #include #include #include #define NUM_ITERATIONS 10 int main(int argc, char **argv) { PRFileDesc *sock; PRStatus status; char buf[1024]; PRInt32 nBytes; int idx; sock = PR_GetInheritedFD("SOCKET"); if (sock == NULL) { fprintf(stderr, "PR_GetInheritedFD failed\n"); exit(1); } status = PR_SetFDInheritable(sock, PR_FALSE); if (status == PR_FAILURE) { fprintf(stderr, "PR_SetFDInheritable failed\n"); exit(1); } for (idx = 0; idx < NUM_ITERATIONS; idx++) { memset(buf, 0, sizeof(buf)); nBytes = PR_Read(sock, buf, sizeof(buf)); if (nBytes == -1) { fprintf(stderr, "PR_Read failed: (%d, %d)\n", PR_GetError(), PR_GetOSError()); exit(1); } printf("pong process: received \"%s\"\n", buf); if (nBytes != 5) { fprintf(stderr, "pong process: expected 5 bytes but got %d bytes\n", nBytes); exit(1); } if (strcmp(buf, "ping") != 0) { fprintf(stderr, "pong process: expected \"ping\" but got \"%s\"\n", buf); exit(1); } strcpy(buf, "pong"); printf("pong process: sending \"%s\"\n", buf); nBytes = PR_Write(sock, buf, 5); if (nBytes == -1) { fprintf(stderr, "PR_Write failed\n"); exit(1); } } status = PR_Close(sock); if (status == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } return 0; } nspr-4.11/nspr/pr/tests/sprintf.c0000644000000000000000000002601312623070344015150 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: sprintf.c * Description: * This is a test program for the PR_snprintf() functions defined * in prprf.c. This test program is based on ns/nspr/tests/sprintf.c, * revision 1.10. * Modification History: * 20-May-1997 AGarcia replaced printf statment to return PASS\n. This is to be used by the * regress tool parsing routine. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to * recognize the return code from tha main program. */ #include "prinit.h" #include "prprf.h" #include "prlog.h" #include "prlong.h" #include #include #include static char sbuf[20000]; /* ** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf. ** Make sure the results are identical */ static void test_i(char *pattern, int i) { char *s; char buf[200]; int n; /* try all three routines */ s = PR_smprintf(pattern, i); PR_ASSERT(s != 0); n = PR_snprintf(buf, sizeof(buf), pattern, i); PR_ASSERT(n <= sizeof(buf)); sprintf(sbuf, pattern, i); /* compare results */ if ((strncmp(s, buf, sizeof(buf)) != 0) || (strncmp(s, sbuf, sizeof(sbuf)) != 0)) { fprintf(stderr, "pattern='%s' i=%d\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n", pattern, i, s, buf, sbuf); PR_smprintf_free(s); exit(-1); } PR_smprintf_free(s); } static void TestI(void) { static int nums[] = { 0, 1, -1, 10, -10, 32767, -32768, }; static char *signs[] = { "", "0", "-", "+", " ", "0-", "0+", "0 ", "-0", "-+", "- ", "+0", "+-", "+ ", " 0", " -", " +", "0-+", "0- ", "0+-", "0+ ", "0 -", "0 +", "-0+", "-0 ", "-+0", "-+ ", "- 0", "- +", "+0-", "+0 ", "+-0", "+- ", "+ 0", "+ -", " 0-", " 0+", " -0", " -+", " +0", " +-", "0-+ ", "0- +", "0+- ", "0+ -", "0 -+", "0 +-", "-0+ ", "-0 +", "-+0 ", "-+ 0", "- 0+", "- +0", "+0- ", "+0 -", "+-0 ", "+- 0", "+ 0-", "+ -0", " 0-+", " 0+-", " -0+", " -+0", " +0-", " +-0", }; static char *precs[] = { "", "3", "5", "43", "7.3", "7.5", "7.11", "7.43", }; static char *formats[] = { "d", "o", "x", "u", "hd", "ho", "hx", "hu" }; int f, s, n, p; char fmt[20]; for (f = 0; f < PR_ARRAY_SIZE(formats); f++) { for (s = 0; s < PR_ARRAY_SIZE(signs); s++) { for (p = 0; p < PR_ARRAY_SIZE(precs); p++) { fmt[0] = '%'; fmt[1] = 0; if (signs[s]) strcat(fmt, signs[s]); if (precs[p]) strcat(fmt, precs[p]); if (formats[f]) strcat(fmt, formats[f]); for (n = 0; n < PR_ARRAY_SIZE(nums); n++) { test_i(fmt, nums[n]); } } } } } /************************************************************************/ /* ** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf. ** Make sure the results are identical */ static void test_l(char *pattern, char *spattern, PRInt32 l) { char *s; char buf[200]; int n; /* try all three routines */ s = PR_smprintf(pattern, l); PR_ASSERT(s != 0); n = PR_snprintf(buf, sizeof(buf), pattern, l); PR_ASSERT(n <= sizeof(buf)); sprintf(sbuf, spattern, l); /* compare results */ if ((strncmp(s, buf, sizeof(buf)) != 0) || (strncmp(s, sbuf, sizeof(sbuf)) != 0)) { fprintf(stderr, "pattern='%s' l=%ld\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n", pattern, l, s, buf, sbuf); PR_smprintf_free(s); exit(-1); } PR_smprintf_free(s); } static void TestL(void) { static PRInt32 nums[] = { 0, 1, -1, 10, -10, 32767, -32768, PR_INT32(0x7fffffff), /* 2147483647L */ -1 - PR_INT32(0x7fffffff) /* -2147483648L */ }; static char *signs[] = { "", "0", "-", "+", " ", "0-", "0+", "0 ", "-0", "-+", "- ", "+0", "+-", "+ ", " 0", " -", " +", "0-+", "0- ", "0+-", "0+ ", "0 -", "0 +", "-0+", "-0 ", "-+0", "-+ ", "- 0", "- +", "+0-", "+0 ", "+-0", "+- ", "+ 0", "+ -", " 0-", " 0+", " -0", " -+", " +0", " +-", "0-+ ", "0- +", "0+- ", "0+ -", "0 -+", "0 +-", "-0+ ", "-0 +", "-+0 ", "-+ 0", "- 0+", "- +0", "+0- ", "+0 -", "+-0 ", "+- 0", "+ 0-", "+ -0", " 0-+", " 0+-", " -0+", " -+0", " +0-", " +-0", }; static char *precs[] = { "", "3", "5", "43", ".3", ".43", "7.3", "7.5", "7.11", "7.43", }; static char *formats[] = { "ld", "lo", "lx", "lu" }; #if PR_BYTES_PER_INT == 4 static char *sformats[] = { "d", "o", "x", "u" }; #elif PR_BYTES_PER_LONG == 4 static char *sformats[] = { "ld", "lo", "lx", "lu" }; #else #error Neither int nor long is 4 bytes on this platform #endif int f, s, n, p; char fmt[40], sfmt[40]; for (f = 0; f < PR_ARRAY_SIZE(formats); f++) { for (s = 0; s < PR_ARRAY_SIZE(signs); s++) { for (p = 0; p < PR_ARRAY_SIZE(precs); p++) { fmt[0] = '%'; fmt[1] = 0; if (signs[s]) strcat(fmt, signs[s]); if (precs[p]) strcat(fmt, precs[p]); strcpy(sfmt, fmt); if (formats[f]) strcat(fmt, formats[f]); if (sformats[f]) strcat(sfmt, sformats[f]); for (n = 0; n < PR_ARRAY_SIZE(nums); n++) { test_l(fmt, sfmt, nums[n]); } } } } } /************************************************************************/ /* ** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf. ** Make sure the results are identical */ static void test_ll(char *pattern, char *spattern, PRInt64 l) { char *s; char buf[200]; int n; /* try all three routines */ s = PR_smprintf(pattern, l); PR_ASSERT(s != 0); n = PR_snprintf(buf, sizeof(buf), pattern, l); PR_ASSERT(n <= sizeof(buf)); #if defined(HAVE_LONG_LONG) sprintf(sbuf, spattern, l); /* compare results */ if ((strncmp(s, buf, sizeof(buf)) != 0) || (strncmp(s, sbuf, sizeof(sbuf)) != 0)) { #if PR_BYTES_PER_LONG == 8 #define FORMAT_SPEC "%ld" #elif defined(WIN16) #define FORMAT_SPEC "%Ld" #elif defined(WIN32) #define FORMAT_SPEC "%I64d" #else #define FORMAT_SPEC "%lld" #endif fprintf(stderr, "pattern='%s' ll=" FORMAT_SPEC "\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n", pattern, l, s, buf, sbuf); printf("FAIL\n"); PR_smprintf_free(s); exit(-1); } PR_smprintf_free(s); #else /* compare results */ if ((strncmp(s, buf, sizeof(buf)) != 0)) { fprintf(stderr, "pattern='%s'\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n", pattern, s, buf, sbuf); printf("FAIL\n"); PR_smprintf_free(s); exit(-1); } PR_smprintf_free(s); #endif } static void TestLL(void) { static PRInt64 nums[] = { LL_INIT(0, 0), LL_INIT(0, 1), LL_INIT(0xffffffff, 0xffffffff), /* -1 */ LL_INIT(0, 10), LL_INIT(0xffffffff, 0xfffffff6), /* -10 */ LL_INIT(0, 32767), LL_INIT(0xffffffff, 0xffff8000), /* -32768 */ LL_INIT(0, 0x7fffffff), /* 2147483647 */ LL_INIT(0xffffffff, 0x80000000), /* -2147483648 */ LL_INIT(0x7fffffff, 0xffffffff), /* 9223372036854775807 */ LL_INIT(0x80000000, 0), /* -9223372036854775808 */ PR_INT64(0), PR_INT64(1), PR_INT64(-1), PR_INT64(10), PR_INT64(-10), PR_INT64(32767), PR_INT64(-32768), PR_INT64(2147483647), PR_INT64(-2147483648), PR_INT64(9223372036854775807), PR_INT64(-9223372036854775808) }; static char *signs[] = { "", "0", "-", "+", " ", "0-", "0+", "0 ", "-0", "-+", "- ", "+0", "+-", "+ ", " 0", " -", " +", "0-+", "0- ", "0+-", "0+ ", "0 -", "0 +", "-0+", "-0 ", "-+0", "-+ ", "- 0", "- +", "+0-", "+0 ", "+-0", "+- ", "+ 0", "+ -", " 0-", " 0+", " -0", " -+", " +0", " +-", "0-+ ", "0- +", "0+- ", "0+ -", "0 -+", "0 +-", "-0+ ", "-0 +", "-+0 ", "-+ 0", "- 0+", "- +0", "+0- ", "+0 -", "+-0 ", "+- 0", "+ 0-", "+ -0", " 0-+", " 0+-", " -0+", " -+0", " +0-", " +-0", }; static char *precs[] = { "", "3", "5", "43", ".3", ".43", "7.3", "7.5", "7.11", "7.43", }; static char *formats[] = { "lld", "llo", "llx", "llu" }; #if PR_BYTES_PER_LONG == 8 static char *sformats[] = { "ld", "lo", "lx", "lu" }; #elif defined(WIN16) /* Watcom uses the format string "%Ld" instead of "%lld". */ static char *sformats[] = { "Ld", "Lo", "Lx", "Lu" }; #elif defined(WIN32) static char *sformats[] = { "I64d", "I64o", "I64x", "I64u" }; #else static char *sformats[] = { "lld", "llo", "llx", "llu" }; #endif int f, s, n, p; char fmt[40], sfmt[40]; for (f = 0; f < PR_ARRAY_SIZE(formats); f++) { for (s = 0; s < PR_ARRAY_SIZE(signs); s++) { for (p = 0; p < PR_ARRAY_SIZE(precs); p++) { fmt[0] = '%'; fmt[1] = 0; if (signs[s]) strcat(fmt, signs[s]); if (precs[p]) strcat(fmt, precs[p]); strcpy(sfmt, fmt); if (formats[f]) strcat(fmt, formats[f]); if (sformats[f]) strcat(sfmt, sformats[f]); for (n = 0; n < PR_ARRAY_SIZE(nums); n++) { test_ll(fmt, sfmt, nums[n]); } } } } } /************************************************************************/ /* ** Perform a three way test against PR_smprintf, PR_snprintf, and sprintf. ** Make sure the results are identical */ static void test_s(char *pattern, char *ss) { char *s; unsigned char before[8]; char buf[200]; unsigned char after[8]; int n; memset(before, 0xBB, 8); memset(after, 0xAA, 8); /* try all three routines */ s = PR_smprintf(pattern, ss); PR_ASSERT(s != 0); n = PR_snprintf(buf, sizeof(buf), pattern, ss); PR_ASSERT(n <= sizeof(buf)); sprintf(sbuf, pattern, ss); for (n = 0; n < 8; n++) { PR_ASSERT(before[n] == 0xBB); PR_ASSERT(after[n] == 0xAA); } /* compare results */ if ((strncmp(s, buf, sizeof(buf)) != 0) || (strncmp(s, sbuf, sizeof(sbuf)) != 0)) { fprintf(stderr, "pattern='%s' ss=%.20s\nPR_smprintf='%s'\nPR_snprintf='%s'\n sprintf='%s'\n", pattern, ss, s, buf, sbuf); printf("FAIL\n"); PR_smprintf_free(s); exit(-1); } PR_smprintf_free(s); } static void TestS(void) { static char *strs[] = { "", "a", "abc", "abcde", "abcdefABCDEF", "abcdefghijklmnopqrstuvwxyz0123456789!@#$" "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$" "abcdefghijklmnopqrstuvwxyz0123456789!@#$", }; /* '0' is not relevant to printing strings */ static char *signs[] = { "", "-", "+", " ", "-+", "- ", "+-", "+ ", " -", " +", "-+ ", "- +", "+- ", "+ -", " -+", " +-", }; static char *precs[] = { "", "3", "5", "43", ".3", ".43", "7.3", "7.5", "7.11", "7.43", }; static char *formats[] = { "s" }; int f, s, n, p; char fmt[40]; for (f = 0; f < PR_ARRAY_SIZE(formats); f++) { for (s = 0; s < PR_ARRAY_SIZE(signs); s++) { for (p = 0; p < PR_ARRAY_SIZE(precs); p++) { fmt[0] = '%'; fmt[1] = 0; if (signs[s]) strcat(fmt+strlen(fmt), signs[s]); if (precs[p]) strcat(fmt+strlen(fmt), precs[p]); if (formats[f]) strcat(fmt+strlen(fmt), formats[f]); for (n = 0; n < PR_ARRAY_SIZE(strs); n++) { test_s(fmt, strs[n]); } } } } } /************************************************************************/ int main(int argc, char **argv) { PR_STDIO_INIT(); TestI(); TestL(); TestLL(); TestS(); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/sproc_ch.c0000644000000000000000000000432012623070344015260 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test sproc_ch.c * * The purpose of this test and the sproc_p.c test is to test the shutdown * of all the IRIX sprocs in a program when one of them dies due to an error. * * There are three sprocs in this test: the parent, the child, and the * grandchild. The parent and child sprocs never stop on their own. * The grandchild sproc gets a segmentation fault and dies. You should * You should use "ps" to see if the parent and child sprocs are killed * after the grandchild dies. */ #include "prinit.h" #include #if !defined(IRIX) int main(int argc, char **argv) { printf("This test applies to IRIX only.\n"); return 0; } #else /* IRIX */ #include "prthread.h" #include #include void SegFault(void *unused) { int *p = 0; printf("The grandchild sproc has pid %d.\n", getpid()); printf("The grandchild sproc will get a segmentation fault and die.\n"); printf("The parent and child sprocs should be killed after the " "grandchild sproc dies.\n"); printf("Use 'ps' to make sure this is so.\n"); fflush(stdout); /* Force a segmentation fault */ *p = 0; } void NeverStops(void *unused) { int i = 0; printf("The child sproc has pid %d.\n", getpid()); printf("The child sproc won't stop on its own.\n"); fflush(stdout); /* create the grandchild sproc */ PR_CreateThread(PR_USER_THREAD, SegFault, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); while (1) { i++; } } int main() { int i= 0; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); printf("The parent sproc has pid %d.\n", getpid()); printf("The parent sproc won't stop on its own.\n"); fflush(stdout); /* create the child sproc */ PR_CreateThread(PR_USER_THREAD, NeverStops, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); while (1) { i++; } return 0; } #endif /* IRIX */ nspr-4.11/nspr/pr/tests/sproc_p.c0000644000000000000000000000337612623070344015137 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test sproc_p.c * * The purpose of this test and the sproc_ch.c test is to test the shutdown * of all the IRIX sprocs in a program when one of them dies due to an error. * * In this test, the parent sproc gets a segmentation fault and dies. * The child sproc never stops on its own. You should use "ps" to see if * the child sproc is killed after the parent dies. */ #include "prinit.h" #include #if !defined(IRIX) int main(int argc, char **argv) { printf("This test applies to IRIX only.\n"); return 0; } #else /* IRIX */ #include "prthread.h" #include #include void NeverStops(void *unused) { int i = 0; printf("The child sproc has pid %d.\n", getpid()); printf("The child sproc won't stop on its own.\n"); fflush(stdout); /* I never stop */ while (1) { i++; } } int main() { int *p = 0; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); printf("The parent sproc has pid %d.\n", getpid()); printf("The parent sproc will first create a child sproc.\n"); printf("Then the parent sproc will get a segmentation fault and die.\n"); printf("The child sproc should be killed after the parent sproc dies.\n"); printf("Use 'ps' to make sure this is so.\n"); fflush(stdout); PR_CreateThread(PR_USER_THREAD, NeverStops, NULL, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); /* Force a segmentation fault */ *p = 0; return 0; } #endif /* IRIX */ nspr-4.11/nspr/pr/tests/stack.c0000644000000000000000000001532112623070344014570 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * * Test atomic stack operations * * Two stacks are created and threads add data items (each containing * one of the first n integers) to the first stack, remove data items * from the first stack and add them to the second stack. The primordial * thread compares the sum of the first n integers to the sum of the * integers in the data items in the second stack. The test succeeds if * they are equal. */ #include "nspr.h" #include "plgetopt.h" typedef struct _DataRecord { PRInt32 data; PRStackElem link; } DataRecord; #define RECORD_LINK_PTR(lp) ((DataRecord*) ((char*) (lp) - offsetof(DataRecord,link))) #define MAX_THREAD_CNT 100 #define DEFAULT_THREAD_CNT 4 #define DEFAULT_DATA_CNT 100 #define DEFAULT_LOOP_CNT 10000 /* * sum of the first n numbers using the formula n*(n+1)/2 */ #define SUM_OF_NUMBERS(n) ((n & 1) ? (((n + 1)/2) * n) : ((n/2) * (n+1))) typedef struct stack_data { PRStack *list1; PRStack *list2; PRInt32 initial_data_value; PRInt32 data_cnt; PRInt32 loops; } stack_data; static void stackop(void *arg); static int _debug_on; PRFileDesc *output; PRFileDesc *errhandle; int main(int argc, char **argv) { #if !(defined(SYMBIAN) && defined(__WINS__)) PRInt32 rv, cnt, sum; DataRecord *Item; PRStack *list1, *list2; PRStackElem *node; PRStatus rc; PRInt32 thread_cnt = DEFAULT_THREAD_CNT; PRInt32 data_cnt = DEFAULT_DATA_CNT; PRInt32 loops = DEFAULT_LOOP_CNT; PRThread **threads; stack_data *thread_args; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dt:c:l:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; case 't': /* thread count */ thread_cnt = atoi(opt->value); break; case 'c': /* data count */ data_cnt = atoi(opt->value); break; case 'l': /* loop count */ loops = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_SetConcurrency(4); output = PR_GetSpecialFD(PR_StandardOutput); errhandle = PR_GetSpecialFD(PR_StandardError); list1 = PR_CreateStack("Stack_1"); if (list1 == NULL) { PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n", PR_GetError()); return 1; } list2 = PR_CreateStack("Stack_2"); if (list2 == NULL) { PR_fprintf(errhandle, "PR_CreateStack failed - error %d\n", PR_GetError()); return 1; } threads = (PRThread**) PR_CALLOC(sizeof(PRThread*) * thread_cnt); thread_args = (stack_data *) PR_CALLOC(sizeof(stack_data) * thread_cnt); if (_debug_on) PR_fprintf(output,"%s: thread_cnt = %d data_cnt = %d\n", argv[0], thread_cnt, data_cnt); for(cnt = 0; cnt < thread_cnt; cnt++) { PRThreadScope scope; thread_args[cnt].list1 = list1; thread_args[cnt].list2 = list2; thread_args[cnt].loops = loops; thread_args[cnt].data_cnt = data_cnt; thread_args[cnt].initial_data_value = 1 + cnt * data_cnt; if (cnt & 1) scope = PR_GLOBAL_THREAD; else scope = PR_LOCAL_THREAD; threads[cnt] = PR_CreateThread(PR_USER_THREAD, stackop, &thread_args[cnt], PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (threads[cnt] == NULL) { PR_fprintf(errhandle, "PR_CreateThread failed - error %d\n", PR_GetError()); PR_ProcessExit(2); } if (_debug_on) PR_fprintf(output,"%s: created thread = 0x%x\n", argv[0], threads[cnt]); } for(cnt = 0; cnt < thread_cnt; cnt++) { rc = PR_JoinThread(threads[cnt]); PR_ASSERT(rc == PR_SUCCESS); } node = PR_StackPop(list1); /* * list1 should be empty */ if (node != NULL) { PR_fprintf(errhandle, "Error - Stack 1 not empty\n"); PR_ASSERT(node == NULL); PR_ProcessExit(4); } cnt = data_cnt * thread_cnt; sum = 0; while (cnt-- > 0) { node = PR_StackPop(list2); /* * There should be at least 'cnt' number of records */ if (node == NULL) { PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n"); PR_ProcessExit(3); } Item = RECORD_LINK_PTR(node); sum += Item->data; } node = PR_StackPop(list2); /* * there should be exactly 'cnt' number of records */ if (node != NULL) { PR_fprintf(errhandle, "Error - Stack 2 not empty\n"); PR_ASSERT(node == NULL); PR_ProcessExit(4); } PR_DELETE(threads); PR_DELETE(thread_args); PR_DestroyStack(list1); PR_DestroyStack(list2); if (sum == SUM_OF_NUMBERS(data_cnt * thread_cnt)) { PR_fprintf(output, "%s successful\n", argv[0]); PR_fprintf(output, "\t\tsum = 0x%x, expected = 0x%x\n", sum, SUM_OF_NUMBERS(thread_cnt * data_cnt)); return 0; } else { PR_fprintf(output, "%s failed: sum = 0x%x, expected = 0x%x\n", argv[0], sum, SUM_OF_NUMBERS(data_cnt * thread_cnt)); return 2; } #endif } static void stackop(void *thread_arg) { PRInt32 val, cnt, index, loops; DataRecord *Items, *Item; PRStack *list1, *list2; PRStackElem *node; stack_data *arg = (stack_data *) thread_arg; val = arg->initial_data_value; cnt = arg->data_cnt; loops = arg->loops; list1 = arg->list1; list2 = arg->list2; /* * allocate memory for the data records */ Items = (DataRecord *) PR_CALLOC(sizeof(DataRecord) * cnt); PR_ASSERT(Items != NULL); index = 0; if (_debug_on) PR_fprintf(output, "Thread[0x%x] init_val = %d cnt = %d data1 = 0x%x datan = 0x%x\n", PR_GetCurrentThread(), val, cnt, &Items[0], &Items[cnt-1]); /* * add the data records to list1 */ while (cnt-- > 0) { Items[index].data = val++; PR_StackPush(list1, &Items[index].link); index++; } /* * pop data records from list1 and add them back to list1 * generates contention for the stack accesses */ while (loops-- > 0) { cnt = arg->data_cnt; while (cnt-- > 0) { node = PR_StackPop(list1); if (node == NULL) { PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n"); PR_ASSERT(node != NULL); PR_ProcessExit(3); } PR_StackPush(list1, node); } } /* * remove the data records from list1 and add them to list2 */ cnt = arg->data_cnt; while (cnt-- > 0) { node = PR_StackPop(list1); if (node == NULL) { PR_fprintf(errhandle, "Error - PR_StackPop returned NULL\n"); PR_ASSERT(node != NULL); PR_ProcessExit(3); } PR_StackPush(list2, node); } if (_debug_on) PR_fprintf(output, "Thread[0x%x] init_val = %d cnt = %d exiting\n", PR_GetCurrentThread(), val, cnt); } nspr-4.11/nspr/pr/tests/stat.c0000644000000000000000000000343112623070344014435 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Program to test different ways to get file info; right now it * only works for solaris and OS/2. * */ #include "nspr.h" #include "prpriv.h" #include "prinrval.h" #include #include #include #ifdef XP_OS2 #include #include #include #endif #define DEFAULT_COUNT 100000 PRInt32 count; #ifndef XP_PC char *filename = "/etc/passwd"; #else char *filename = "..\\stat.c"; #endif static void statPRStat(void) { PRFileInfo finfo; PRInt32 index = count; for (;index--;) { PR_GetFileInfo(filename, &finfo); } } static void statStat(void) { struct stat finfo; PRInt32 index = count; for (;index--;) { stat(filename, &finfo); } } /************************************************************************/ static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; PRInt32 tot; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); tot = PR_IntervalToMilliseconds(stop-start); printf("%40s: %6.2f usec avg, %d msec total\n", msg, d / count, tot); } int main(int argc, char **argv) { PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (argc > 1) { count = atoi(argv[1]); } else { count = DEFAULT_COUNT; } Measure(statPRStat, "time to call PR_GetFileInfo()"); Measure(statStat, "time to call stat()"); PR_Cleanup(); } nspr-4.11/nspr/pr/tests/stdio.c0000644000000000000000000000263512623070344014611 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: stdio.c * Description: testing the "special" fds * Modification History: * 20-May-1997 AGarcia - Replace Test succeeded status with PASS. This is used by the * regress tool parsing code. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to ** recognize the return code from tha main program. */ #include "prlog.h" #include "prinit.h" #include "prio.h" #include #include static PRIntn PR_CALLBACK stdio(PRIntn argc, char **argv) { PRInt32 rv; PRFileDesc *out = PR_GetSpecialFD(PR_StandardOutput); PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); rv = PR_Write( out, "This to standard out\n", strlen("This to standard out\n")); PR_ASSERT((PRInt32)strlen("This to standard out\n") == rv); rv = PR_Write( err, "This to standard err\n", strlen("This to standard err\n")); PR_ASSERT((PRInt32)strlen("This to standard err\n") == rv); return 0; } /* stdio */ int main(int argc, char **argv) { PR_STDIO_INIT(); return PR_Initialize(stdio, argc, argv, 0); } /* main */ /* stdio.c */ nspr-4.11/nspr/pr/tests/str2addr.c0000644000000000000000000000264212623070344015212 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: str2addr.c * Description: a test for PR_StringToNetAddr */ #include "nspr.h" #include #include /* Address string to convert */ #define DEFAULT_IPV4_ADDR_STR "207.200.73.41" /* Expected conversion result, in network byte order */ static unsigned char default_ipv4_addr[] = {207, 200, 73, 41}; int main(int argc, char **argv) { PRNetAddr addr; const char *addrStr; unsigned char *bytes; int idx; addrStr = DEFAULT_IPV4_ADDR_STR; if (PR_StringToNetAddr(addrStr, &addr) == PR_FAILURE) { fprintf(stderr, "PR_StringToNetAddr failed\n"); exit(1); } if (addr.inet.family != PR_AF_INET) { fprintf(stderr, "addr.inet.family should be %d but is %d\n", PR_AF_INET, addr.inet.family); exit(1); } bytes = (unsigned char *) &addr.inet.ip; for (idx = 0; idx < 4; idx++) { if (bytes[idx] != default_ipv4_addr[idx]) { fprintf(stderr, "byte %d of IPv4 addr should be %d but is %d\n", idx, default_ipv4_addr[idx], bytes[idx]); exit(1); } } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/strod.c0000644000000000000000000000412512623070344014616 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prinit.h" #include "prio.h" #include "prprf.h" #include "prdtoa.h" #include "plgetopt.h" #include static void Help(void) { PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); PR_fprintf(err, "Usage: /.strod [-n n] [-l n] [-h]\n"); PR_fprintf(err, "\t-n n Number to translate (default: 1234567890123456789)\n"); PR_fprintf(err, "\t-l n Times to loop the test (default: 1)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ static PRIntn PR_CALLBACK RealMain(PRIntn argc, char **argv) { PLOptStatus os; PRIntn loops = 1; PRFloat64 answer; const char *number = "1234567890123456789"; PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); PLOptState *opt = PL_CreateOptState(argc, argv, "hc:l:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'n': /* number to translate */ number = opt->value; break; case 'l': /* number of times to run the tests */ loops = atoi(opt->value); break; case 'h': /* user wants some guidance */ Help(); /* so give him an earful */ return 2; /* but not a lot else */ break; default: break; } } PL_DestroyOptState(opt); PR_fprintf(err, "Settings\n"); PR_fprintf(err, "\tNumber to translate %s\n", number); PR_fprintf(err, "\tLoops to run test: %d\n", loops); while (loops--) { answer = PR_strtod(number, NULL); PR_fprintf(err, "Translation = %20.0f\n", answer); } return 0; } int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ nspr-4.11/nspr/pr/tests/suspend.c0000644000000000000000000001066312623070344015150 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifdef XP_BEOS #include int main() { printf( "This test is not ported to the BeOS\n" ); return 0; } #else #include "nspr.h" #include "prpriv.h" #include "prinrval.h" #include #include #include PRMonitor *mon; PRInt32 count; PRInt32 alive; #define SLEEP_TIME 4 /* secs */ void PR_CALLBACK Level_2_Thread(void *arg) { PR_Sleep(PR_MillisecondsToInterval(4 * 1000)); printf("Level_2_Thread[0x%lx] exiting\n",PR_GetCurrentThread()); return; } void PR_CALLBACK Level_1_Thread(void *arg) { PRUint32 tmp = (PRUint32)arg; PRThreadScope scope = (PRThreadScope) tmp; PRThread *thr; thr = PR_CreateThreadGCAble(PR_USER_THREAD, Level_2_Thread, NULL, PR_PRIORITY_HIGH, scope, PR_JOINABLE_THREAD, 0); if (!thr) { printf("Could not create thread!\n"); } else { printf("Level_1_Thread[0x%lx] created %15s thread 0x%lx\n", PR_GetCurrentThread(), (scope == PR_GLOBAL_THREAD) ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD", thr); PR_JoinThread(thr); } PR_EnterMonitor(mon); alive--; PR_Notify(mon); PR_ExitMonitor(mon); printf("Thread[0x%lx] exiting\n",PR_GetCurrentThread()); } static PRStatus PR_CALLBACK print_thread(PRThread *thread, int i, void *arg) { PRInt32 words; PRWord *registers; printf( "\nprint_thread[0x%lx]: %-20s - i = %ld\n",thread, (PR_GLOBAL_THREAD == PR_GetThreadScope(thread)) ? "PR_GLOBAL_THREAD" : "PR_LOCAL_THREAD", i); registers = PR_GetGCRegisters(thread, 0, (int *)&words); if (registers) printf("Registers R0 = 0x%x R1 = 0x%x R2 = 0x%x R3 = 0x%x\n", registers[0],registers[1],registers[2],registers[3]); printf("Stack Pointer = 0x%lx\n", PR_GetSP(thread)); return PR_SUCCESS; } static void Level_0_Thread(PRThreadScope scope1, PRThreadScope scope2) { PRThread *thr; PRThread *me = PR_GetCurrentThread(); int n; PRInt32 words; PRWord *registers; alive = 0; mon = PR_NewMonitor(); alive = count; for (n=0; n 1) { count = atoi(argv[1]); } else { count = 5; } printf("\n\n%20s%30s\n\n"," ","Suspend_Resume Test"); CreateThreadsUU(); CreateThreadsUK(); CreateThreadsKU(); CreateThreadsKK(); PR_SetConcurrency(2); printf("\n%20s%30s\n\n"," ","Added 2nd CPU\n"); CreateThreadsUK(); CreateThreadsKK(); CreateThreadsUU(); CreateThreadsKU(); PR_Cleanup(); return 0; } #endif /* XP_BEOS */ nspr-4.11/nspr/pr/tests/switch.c0000644000000000000000000001460012623070344014763 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: switch.c ** Description: trying to time context switches */ #include "prinit.h" #include "prcvar.h" #include "prmem.h" #include "prinrval.h" #include "prlock.h" #include "prlog.h" #include "prthread.h" #include "prprf.h" #include "plerror.h" #include "plgetopt.h" #include "private/pprio.h" #include #define INNER_LOOPS 100 #define DEFAULT_LOOPS 100 #define DEFAULT_THREADS 10 static PRFileDesc *debug_out = NULL; static PRBool debug_mode = PR_FALSE, verbosity = PR_FALSE, failed = PR_FALSE; typedef struct Shared { PRLock *ml; PRCondVar *cv; PRBool twiddle; PRThread *thread; struct Shared *next; } Shared; static void Help(void) { debug_out = PR_STDOUT; PR_fprintf( debug_out, "Usage: >./switch [-c n] [-t n] [-d] [-v] [-G] [-C n]\n"); PR_fprintf( debug_out, "-c n\tloops at thread level (default: %d)\n", DEFAULT_LOOPS); PR_fprintf( debug_out, "-t n\tnumber of threads (default: %d)\n", DEFAULT_THREADS); PR_fprintf(debug_out, "-d\tturn on debugging output (default: FALSE)\n"); PR_fprintf(debug_out, "-v\tturn on verbose output (default: FALSE)\n"); PR_fprintf(debug_out, "-G\tglobal threads only (default: FALSE)\n"); PR_fprintf(debug_out, "-C n\tconcurrency setting (default: 1)\n"); } /* Help */ static void PR_CALLBACK Notified(void *arg) { Shared *shared = (Shared*)arg; PRStatus status = PR_SUCCESS; while (PR_SUCCESS == status) { PR_Lock(shared->ml); while (shared->twiddle && (PR_SUCCESS == status)) status = PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT); if (verbosity) PR_fprintf(debug_out, "+"); shared->twiddle = PR_TRUE; shared->next->twiddle = PR_FALSE; PR_NotifyCondVar(shared->next->cv); PR_Unlock(shared->ml); } } /* Notified */ static Shared home; PRIntn PR_CALLBACK Switch(PRIntn argc, char **argv) { PLOptStatus os; PRStatus status; PRBool help = PR_FALSE; PRUintn concurrency = 1; Shared *shared, *link; PRIntervalTime timein, timeout; PRThreadScope thread_scope = PR_LOCAL_THREAD; PRUintn thread_count, inner_count, loop_count, average; PRUintn thread_limit = DEFAULT_THREADS, loop_limit = DEFAULT_LOOPS; PLOptState *opt = PL_CreateOptState(argc, argv, "hdvc:t:C:G"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'v': /* verbose mode */ verbosity = PR_TRUE; case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop counter */ loop_limit = atoi(opt->value); break; case 't': /* thread limit */ thread_limit = atoi(opt->value); break; case 'C': /* Concurrency limit */ concurrency = atoi(opt->value); break; case 'G': /* global threads only */ thread_scope = PR_GLOBAL_THREAD; break; case 'h': /* help message */ Help(); help = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); if (help) return -1; if (PR_TRUE == debug_mode) { debug_out = PR_STDOUT; PR_fprintf(debug_out, "Test parameters\n"); PR_fprintf(debug_out, "\tThreads involved: %d\n", thread_limit); PR_fprintf(debug_out, "\tIteration limit: %d\n", loop_limit); PR_fprintf(debug_out, "\tConcurrency: %d\n", concurrency); PR_fprintf( debug_out, "\tThread type: %s\n", (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL"); } PR_SetConcurrency(concurrency); link = &home; home.ml = PR_NewLock(); home.cv = PR_NewCondVar(home.ml); home.twiddle = PR_FALSE; home.next = NULL; timeout = 0; for (thread_count = 1; thread_count <= thread_limit; ++thread_count) { shared = PR_NEWZAP(Shared); shared->ml = home.ml; shared->cv = PR_NewCondVar(home.ml); shared->twiddle = PR_TRUE; shared->next = link; link = shared; shared->thread = PR_CreateThread( PR_USER_THREAD, Notified, shared, PR_PRIORITY_HIGH, thread_scope, PR_JOINABLE_THREAD, 0); PR_ASSERT(shared->thread != NULL); if (NULL == shared->thread) failed = PR_TRUE; } for (loop_count = 1; loop_count <= loop_limit; ++loop_count) { timein = PR_IntervalNow(); for (inner_count = 0; inner_count < INNER_LOOPS; ++inner_count) { PR_Lock(home.ml); home.twiddle = PR_TRUE; shared->twiddle = PR_FALSE; PR_NotifyCondVar(shared->cv); while (home.twiddle) { status = PR_WaitCondVar(home.cv, PR_INTERVAL_NO_TIMEOUT); if (PR_FAILURE == status) failed = PR_TRUE; } PR_Unlock(home.ml); } timeout += (PR_IntervalNow() - timein); } if (debug_mode) { average = PR_IntervalToMicroseconds(timeout) / (INNER_LOOPS * loop_limit * thread_count); PR_fprintf( debug_out, "Average switch times %d usecs for %d threads\n", average, thread_limit); } link = shared; for (thread_count = 1; thread_count <= thread_limit; ++thread_count) { if (&home == link) break; status = PR_Interrupt(link->thread); if (PR_SUCCESS != status) { failed = PR_TRUE; if (debug_mode) PL_FPrintError(debug_out, "Failed to interrupt"); } link = link->next; } for (thread_count = 1; thread_count <= thread_limit; ++thread_count) { link = shared->next; status = PR_JoinThread(shared->thread); if (PR_SUCCESS != status) { failed = PR_TRUE; if (debug_mode) PL_FPrintError(debug_out, "Failed to join"); } PR_DestroyCondVar(shared->cv); PR_DELETE(shared); if (&home == link) break; shared = link; } PR_DestroyCondVar(home.cv); PR_DestroyLock(home.ml); PR_fprintf(PR_STDOUT, ((failed) ? "FAILED\n" : "PASSED\n")); return ((failed) ? 1 : 0); } /* Switch */ int main(int argc, char **argv) { PRIntn result; PR_STDIO_INIT(); result = PR_Initialize(Switch, argc, argv, 0); return result; } /* main */ /* switch.c */ nspr-4.11/nspr/pr/tests/system.c0000644000000000000000000000304012623070344015002 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prmem.h" #include "prprf.h" #include "prsystem.h" #include "plerror.h" static char *tag[] = { "PR_SI_HOSTNAME", "PR_SI_SYSNAME", "PR_SI_RELEASE", "PR_SI_ARCHITECTURE" }; static PRSysInfo Incr(PRSysInfo *cmd) { PRIntn tmp = (PRIntn)*cmd + 1; *cmd = (PRSysInfo)tmp; return (PRSysInfo)tmp; } /* Incr */ int main(int argc, char **argv) { PRStatus rv; PRSysInfo cmd; PRFileDesc *output = PR_GetSpecialFD(PR_StandardOutput); char *info = (char*)PR_Calloc(SYS_INFO_BUFFER_LENGTH, 1); for (cmd = PR_SI_HOSTNAME; cmd <= PR_SI_ARCHITECTURE; Incr(&cmd)) { rv = PR_GetSystemInfo(cmd, info, SYS_INFO_BUFFER_LENGTH); if (PR_SUCCESS == rv) PR_fprintf(output, "%s: %s\n", tag[cmd], info); else PL_FPrintError(output, tag[cmd]); } PR_DELETE(info); PR_fprintf(output, "Host page size is %d\n", PR_GetPageSize()); PR_fprintf(output, "Page shift is %d\n", PR_GetPageShift()); PR_fprintf(output, "Memory map alignment is %ld\n", PR_GetMemMapAlignment()); PR_fprintf(output, "Number of processors is: %d\n", PR_GetNumberOfProcessors()); PR_fprintf(output, "Physical memory size is: %llu\n", PR_GetPhysicalMemorySize()); return 0; } /* main */ /* system.c */ nspr-4.11/nspr/pr/tests/testbit.c0000644000000000000000000000437012623070344015143 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: lazyinit.c ** Description: Test the functions and macros declared in prbit.h ** */ #include "nspr.h" #define ErrorReport(x) { printf((x)); failed = 1; } prbitmap_t myMap[512/32] = { 0 }; PRInt32 rc; PRInt32 i; PRIntn failed = 0; int main(int argc, char **argv) { /* ** Test bitmap things. */ if ( PR_TEST_BIT( myMap, 0 )) ErrorReport("Test 0.0: Failed\n"); if ( PR_TEST_BIT( myMap, 31 )) ErrorReport("Test 0.1: Failed\n"); if ( PR_TEST_BIT( myMap, 128 )) ErrorReport("Test 0.2: Failed\n"); if ( PR_TEST_BIT( myMap, 129 )) ErrorReport("Test 0.3: Failed\n"); PR_SET_BIT( myMap, 0 ); if ( !PR_TEST_BIT( myMap, 0 )) ErrorReport("Test 1.0: Failed\n"); PR_CLEAR_BIT( myMap, 0 ); if ( PR_TEST_BIT( myMap, 0 )) ErrorReport("Test 1.0.1: Failed\n"); PR_SET_BIT( myMap, 31 ); if ( !PR_TEST_BIT( myMap, 31 )) ErrorReport("Test 1.1: Failed\n"); PR_CLEAR_BIT( myMap, 31 ); if ( PR_TEST_BIT( myMap, 31 )) ErrorReport("Test 1.1.1: Failed\n"); PR_SET_BIT( myMap, 128 ); if ( !PR_TEST_BIT( myMap, 128 )) ErrorReport("Test 1.2: Failed\n"); PR_CLEAR_BIT( myMap, 128 ); if ( PR_TEST_BIT( myMap, 128 )) ErrorReport("Test 1.2.1: Failed\n"); PR_SET_BIT( myMap, 129 ); if ( !PR_TEST_BIT( myMap, 129 )) ErrorReport("Test 1.3: Failed\n"); PR_CLEAR_BIT( myMap, 129 ); if ( PR_TEST_BIT( myMap, 129 )) ErrorReport("Test 1.3.1: Failed\n"); /* ** Test Ceiling and Floor functions and macros */ if ((rc = PR_CeilingLog2(32)) != 5 ) ErrorReport("Test 10.0: Failed\n"); if ((rc = PR_FloorLog2(32)) != 5 ) ErrorReport("Test 10.1: Failed\n"); /* ** Evaluate results and exit */ if (failed) { printf("FAILED\n"); return(1); } else { printf("PASSED\n"); return(0); } } /* end main() */ /* end testbit.c */ nspr-4.11/nspr/pr/tests/testfile.c0000644000000000000000000005332312623070344015306 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "prpriv.h" #include #include #include #ifdef WIN32 #include #include #endif #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include #endif #ifdef SYMBIAN #include #endif #if defined(XP_OS2) #define INCL_DOSFILEMGR #include #include #include #endif /* XP_OS2 */ static int _debug_on = 0; #ifdef WINCE #define setbuf(x,y) #endif #ifdef XP_WIN #define mode_t int #endif #define DPRINTF(arg) if (_debug_on) printf arg PRLock *lock; PRMonitor *mon; PRInt32 count; int thread_count; #ifdef WIN16 #define BUF_DATA_SIZE 256 * 120 #else #define BUF_DATA_SIZE 256 * 1024 #endif #define NUM_RDWR_THREADS 10 #define NUM_DIRTEST_THREADS 4 #define CHUNK_SIZE 512 typedef struct buffer { char data[BUF_DATA_SIZE]; } buffer; typedef struct File_Rdwr_Param { char *pathname; char *buf; int offset; int len; } File_Rdwr_Param; #ifdef XP_PC #ifdef XP_OS2 char *TEST_DIR = "prdir"; #else char *TEST_DIR = "C:\\temp\\prdir"; #endif char *FILE_NAME = "pr_testfile"; char *HIDDEN_FILE_NAME = "hidden_pr_testfile"; #else #ifdef SYMBIAN char *TEST_DIR = "c:\\data\\testfile_dir"; #else char *TEST_DIR = "/tmp/testfile_dir"; #endif char *FILE_NAME = "pr_testfile"; char *HIDDEN_FILE_NAME = ".hidden_pr_testfile"; #endif buffer *in_buf, *out_buf; char pathname[256], renamename[256]; #ifdef WINCE WCHAR wPathname[256]; #endif #define TMPDIR_LEN 64 char testdir[TMPDIR_LEN]; static PRInt32 PR_CALLBACK DirTest(void *argunused); PRInt32 dirtest_failed = 0; PRThread* create_new_thread(PRThreadType type, void (*start)(void *arg), void *arg, PRThreadPriority priority, PRThreadScope scope, PRThreadState state, PRUint32 stackSize, PRInt32 index) { PRInt32 native_thread = 0; PR_ASSERT(state == PR_UNJOINABLE_THREAD); #if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) || defined(XP_OS2) switch(index % 4) { case 0: scope = (PR_LOCAL_THREAD); break; case 1: scope = (PR_GLOBAL_THREAD); break; case 2: scope = (PR_GLOBAL_BOUND_THREAD); break; case 3: native_thread = 1; break; default: PR_NOT_REACHED("Invalid scope"); break; } if (native_thread) { #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) pthread_t tid; if (!pthread_create(&tid, NULL, start, arg)) return((PRThread *) tid); else return (NULL); #elif defined(XP_OS2) TID tid; tid = (TID)_beginthread((void(* _Optlink)(void*))start, NULL, 32768, arg); if (tid == -1) { printf("_beginthread failed. errno %d\n", errno); return (NULL); } else return((PRThread *) tid); #else HANDLE thandle; unsigned tid; thandle = (HANDLE) _beginthreadex( NULL, stackSize, (unsigned (__stdcall *)(void *))start, arg, STACK_SIZE_PARAM_IS_A_RESERVATION, &tid); return((PRThread *) thandle); #endif } else { return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); } #else return(PR_CreateThread(type,start,arg,priority,scope,state,stackSize)); #endif } static void PR_CALLBACK File_Write(void *arg) { PRFileDesc *fd_file; File_Rdwr_Param *fp = (File_Rdwr_Param *) arg; char *name, *buf; int offset, len; setbuf(stdout, NULL); name = fp->pathname; buf = fp->buf; offset = fp->offset; len = fp->len; fd_file = PR_Open(name, PR_RDWR | PR_CREATE_FILE, 0777); if (fd_file == NULL) { printf("testfile failed to create/open file %s\n",name); return; } if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) { printf("testfile failed to seek in file %s\n",name); return; } if ((PR_Write(fd_file, buf, len)) < 0) { printf("testfile failed to write to file %s\n",name); return; } DPRINTF(("Write out_buf[0] = 0x%x\n",(*((int *) buf)))); PR_Close(fd_file); PR_DELETE(fp); PR_EnterMonitor(mon); --thread_count; PR_Notify(mon); PR_ExitMonitor(mon); } static void PR_CALLBACK File_Read(void *arg) { PRFileDesc *fd_file; File_Rdwr_Param *fp = (File_Rdwr_Param *) arg; char *name, *buf; int offset, len; setbuf(stdout, NULL); name = fp->pathname; buf = fp->buf; offset = fp->offset; len = fp->len; fd_file = PR_Open(name, PR_RDONLY, 0); if (fd_file == NULL) { printf("testfile failed to open file %s\n",name); return; } if (PR_Seek(fd_file, offset, PR_SEEK_SET) < 0) { printf("testfile failed to seek in file %s\n",name); return; } if ((PR_Read(fd_file, buf, len)) < 0) { printf("testfile failed to read to file %s\n",name); return; } DPRINTF(("Read in_buf[0] = 0x%x\n",(*((int *) buf)))); PR_Close(fd_file); PR_DELETE(fp); PR_EnterMonitor(mon); --thread_count; PR_Notify(mon); PR_ExitMonitor(mon); } static PRInt32 Misc_File_Tests(char *pathname) { PRFileDesc *fd_file; int len, rv = 0; PRFileInfo file_info, file_info1; char tmpname[1024]; setbuf(stdout, NULL); /* * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access */ fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777); if (fd_file == NULL) { printf("testfile failed to create/open file %s\n",pathname); return -1; } if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) { printf("testfile PR_GetFileInfo failed on file %s\n",pathname); rv = -1; goto cleanup; } if (PR_Access(pathname, PR_ACCESS_EXISTS) != 0) { printf("testfile PR_Access failed on file %s\n",pathname); rv = -1; goto cleanup; } if (PR_Access(pathname, PR_ACCESS_WRITE_OK) != 0) { printf("testfile PR_Access failed on file %s\n",pathname); rv = -1; goto cleanup; } if (PR_Access(pathname, PR_ACCESS_READ_OK) != 0) { printf("testfile PR_Access failed on file %s\n",pathname); rv = -1; goto cleanup; } if (PR_GetFileInfo(pathname, &file_info) < 0) { printf("testfile PR_GetFileInfo failed on file %s\n",pathname); rv = -1; goto cleanup; } if (file_info.type != PR_FILE_FILE) { printf( "testfile: Error - PR_GetFileInfo returned incorrect type for file %s\n", pathname); rv = -1; goto cleanup; } if (file_info.size != 0) { printf( "testfile PR_GetFileInfo returned incorrect size (%d should be 0) for file %s\n", file_info.size, pathname); rv = -1; goto cleanup; } file_info1 = file_info; len = PR_Available(fd_file); if (len < 0) { printf("testfile PR_Available failed on file %s\n",pathname); rv = -1; goto cleanup; } else if (len != 0) { printf( "testfile PR_Available failed: expected/returned = %d/%d bytes\n", 0, len); rv = -1; goto cleanup; } if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) { printf("testfile PR_GetFileInfo failed on file %s\n",pathname); goto cleanup; } if (LL_NE(file_info.creationTime , file_info1.creationTime)) { printf( "testfile PR_GetFileInfo returned incorrect status-change time: %s\n", pathname); printf("ft = %lld, ft1 = %lld\n",file_info.creationTime, file_info1.creationTime); rv = -1; goto cleanup; } len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE); if (len < 0) { printf("testfile failed to write to file %s\n",pathname); rv = -1; goto cleanup; } if (PR_GetOpenFileInfo(fd_file, &file_info) < 0) { printf("testfile PR_GetFileInfo failed on file %s\n",pathname); goto cleanup; } if (file_info.size != CHUNK_SIZE) { printf( "testfile PR_GetFileInfo returned incorrect size (%d should be %d) for file %s\n", file_info.size, CHUNK_SIZE, pathname); rv = -1; goto cleanup; } if (LL_CMP(file_info.modifyTime, < , file_info1.modifyTime)) { printf( "testfile PR_GetFileInfo returned incorrect modify time: %s\n", pathname); printf("ft = %lld, ft1 = %lld\n",file_info.modifyTime, file_info1.modifyTime); rv = -1; goto cleanup; } len = PR_Available(fd_file); if (len < 0) { printf("testfile PR_Available failed on file %s\n",pathname); rv = -1; goto cleanup; } else if (len != 0) { printf( "testfile PR_Available failed: expected/returned = %d/%d bytes\n", 0, len); rv = -1; goto cleanup; } PR_Seek(fd_file, 0, PR_SEEK_SET); len = PR_Available(fd_file); if (len < 0) { printf("testfile PR_Available failed on file %s\n",pathname); rv = -1; goto cleanup; } else if (len != CHUNK_SIZE) { printf( "testfile PR_Available failed: expected/returned = %d/%d bytes\n", CHUNK_SIZE, len); rv = -1; goto cleanup; } PR_Close(fd_file); strcpy(tmpname,pathname); strcat(tmpname,".RENAMED"); if (PR_FAILURE == PR_Rename(pathname, tmpname)) { printf("testfile failed to rename file %s\n",pathname); rv = -1; goto cleanup; } fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777); len = PR_Write(fd_file, out_buf->data, CHUNK_SIZE); PR_Close(fd_file); if (PR_SUCCESS == PR_Rename(pathname, tmpname)) { printf("testfile renamed to existing file %s\n",pathname); } if ((PR_Delete(tmpname)) < 0) { printf("testfile failed to unlink file %s\n",tmpname); rv = -1; } cleanup: if ((PR_Delete(pathname)) < 0) { printf("testfile failed to unlink file %s\n",pathname); rv = -1; } return rv; } static PRInt32 PR_CALLBACK FileTest(void) { PRDir *fd_dir; int i, offset, len, rv = 0; PRThread *t; PRThreadScope scope = PR_GLOBAL_THREAD; File_Rdwr_Param *fparamp; /* * Create Test dir */ if ((PR_MkDir(TEST_DIR, 0777)) < 0) { printf("testfile failed to create dir %s\n",TEST_DIR); return -1; } fd_dir = PR_OpenDir(TEST_DIR); if (fd_dir == NULL) { printf("testfile failed to open dir %s\n",TEST_DIR); rv = -1; goto cleanup; } PR_CloseDir(fd_dir); strcat(pathname, TEST_DIR); strcat(pathname, "/"); strcat(pathname, FILE_NAME); in_buf = PR_NEW(buffer); if (in_buf == NULL) { printf( "testfile failed to alloc buffer struct\n"); rv = -1; goto cleanup; } out_buf = PR_NEW(buffer); if (out_buf == NULL) { printf( "testfile failed to alloc buffer struct\n"); rv = -1; goto cleanup; } /* * Start a bunch of writer threads */ offset = 0; len = CHUNK_SIZE; PR_EnterMonitor(mon); for (i = 0; i < NUM_RDWR_THREADS; i++) { fparamp = PR_NEW(File_Rdwr_Param); if (fparamp == NULL) { printf( "testfile failed to alloc File_Rdwr_Param struct\n"); rv = -1; goto cleanup; } fparamp->pathname = pathname; fparamp->buf = out_buf->data + offset; fparamp->offset = offset; fparamp->len = len; memset(fparamp->buf, i, len); t = create_new_thread(PR_USER_THREAD, File_Write, (void *)fparamp, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0, i); offset += len; } thread_count = i; /* Wait for writer threads to exit */ while (thread_count) { PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(mon); /* * Start a bunch of reader threads */ offset = 0; len = CHUNK_SIZE; PR_EnterMonitor(mon); for (i = 0; i < NUM_RDWR_THREADS; i++) { fparamp = PR_NEW(File_Rdwr_Param); if (fparamp == NULL) { printf( "testfile failed to alloc File_Rdwr_Param struct\n"); rv = -1; goto cleanup; } fparamp->pathname = pathname; fparamp->buf = in_buf->data + offset; fparamp->offset = offset; fparamp->len = len; t = create_new_thread(PR_USER_THREAD, File_Read, (void *)fparamp, PR_PRIORITY_NORMAL, scope, PR_UNJOINABLE_THREAD, 0, i); offset += len; if ((offset + len) > BUF_DATA_SIZE) break; } thread_count = i; /* Wait for reader threads to exit */ while (thread_count) { PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); } PR_ExitMonitor(mon); if (memcmp(in_buf->data, out_buf->data, offset) != 0) { printf("File Test failed: file data corrupted\n"); rv = -1; goto cleanup; } if ((PR_Delete(pathname)) < 0) { printf("testfile failed to unlink file %s\n",pathname); rv = -1; goto cleanup; } /* * Test PR_Available, PR_Seek, PR_GetFileInfo, PR_Rename, PR_Access */ if (Misc_File_Tests(pathname) < 0) { rv = -1; } cleanup: if ((PR_RmDir(TEST_DIR)) < 0) { printf("testfile failed to rmdir %s\n", TEST_DIR); rv = -1; } return rv; } struct dirtest_arg { PRMonitor *mon; PRInt32 done; }; static PRInt32 RunDirTest(void) { int i; PRThread *t; PRMonitor *mon; struct dirtest_arg thrarg; mon = PR_NewMonitor(); if (!mon) { printf("RunDirTest: Error - failed to create monitor\n"); dirtest_failed = 1; return -1; } thrarg.mon = mon; for (i = 0; i < NUM_DIRTEST_THREADS; i++) { thrarg.done= 0; t = create_new_thread(PR_USER_THREAD, DirTest, &thrarg, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0, i); if (!t) { printf("RunDirTest: Error - failed to create thread\n"); dirtest_failed = 1; return -1; } PR_EnterMonitor(mon); while (!thrarg.done) PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT); PR_ExitMonitor(mon); } PR_DestroyMonitor(mon); return 0; } static PRInt32 PR_CALLBACK DirTest(void *arg) { struct dirtest_arg *tinfo = (struct dirtest_arg *) arg; PRFileDesc *fd_file; PRDir *fd_dir; int i; int path_len; PRDirEntry *dirEntry; PRFileInfo info; PRInt32 num_files = 0; #if defined(XP_PC) && defined(WIN32) HANDLE hfile; #endif #define FILES_IN_DIR 20 /* * Create Test dir */ DPRINTF(("Creating test dir %s\n",TEST_DIR)); if ((PR_MkDir(TEST_DIR, 0777)) < 0) { printf( "testfile failed to create dir %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } fd_dir = PR_OpenDir(TEST_DIR); if (fd_dir == NULL) { printf( "testfile failed to open dirctory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } strcpy(pathname, TEST_DIR); strcat(pathname, "/"); strcat(pathname, FILE_NAME); path_len = strlen(pathname); for (i = 0; i < FILES_IN_DIR; i++) { sprintf(pathname + path_len,"%d%s",i,""); DPRINTF(("Creating test file %s\n",pathname)); fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777); if (fd_file == NULL) { printf( "testfile failed to create/open file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } PR_Close(fd_file); } #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS) /* * Create a hidden file - a platform-dependent operation */ strcpy(pathname, TEST_DIR); strcat(pathname, "/"); strcat(pathname, HIDDEN_FILE_NAME); #if defined(XP_UNIX) || defined(XP_BEOS) DPRINTF(("Creating hidden test file %s\n",pathname)); fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, 0777); if (fd_file == NULL) { printf( "testfile failed to create/open hidden file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } PR_Close(fd_file); #elif defined(WINCE) DPRINTF(("Creating hidden test file %s\n",pathname)); MultiByteToWideChar(CP_ACP, 0, pathname, -1, wPathname, 256); hfile = CreateFile(wPathname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("testfile failed to create/open hidden file %s [0, %d]\n", pathname, GetLastError()); return -1; } CloseHandle(hfile); #elif defined(XP_PC) && defined(WIN32) DPRINTF(("Creating hidden test file %s\n",pathname)); hfile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, NULL); if (hfile == INVALID_HANDLE_VALUE) { printf("testfile failed to create/open hidden file %s [0, %d]\n", pathname, GetLastError()); return -1; } CloseHandle(hfile); #elif defined(OS2) DPRINTF(("Creating hidden test file %s\n",pathname)); fd_file = PR_Open(pathname, PR_RDWR | PR_CREATE_FILE, (int)FILE_HIDDEN); if (fd_file == NULL) { printf("testfile failed to create/open hidden file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } PR_Close(fd_file); #endif /* XP_UNIX */ #endif /* XP_UNIX || (XP_PC && WIN32) */ if (PR_FAILURE == PR_CloseDir(fd_dir)) { printf( "testfile failed to close dirctory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } fd_dir = PR_OpenDir(TEST_DIR); if (fd_dir == NULL) { printf( "testfile failed to reopen dirctory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } /* * List all files, including hidden files */ DPRINTF(("Listing all files in directory %s\n",TEST_DIR)); #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS) num_files = FILES_IN_DIR + 1; #else num_files = FILES_IN_DIR; #endif while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_BOTH)) != NULL) { num_files--; strcpy(pathname, TEST_DIR); strcat(pathname, "/"); strcat(pathname, dirEntry->name); DPRINTF(("\t%s\n",dirEntry->name)); if ((PR_GetFileInfo(pathname, &info)) < 0) { printf( "testfile failed to GetFileInfo file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } if (info.type != PR_FILE_FILE) { printf( "testfile incorrect fileinfo for file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } } if (num_files != 0) { printf( "testfile failed to find all files in directory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } PR_CloseDir(fd_dir); #if defined(XP_UNIX) || (defined(XP_PC) && defined(WIN32)) || defined(XP_OS2) || defined(XP_BEOS) /* * List all files, except hidden files */ fd_dir = PR_OpenDir(TEST_DIR); if (fd_dir == NULL) { printf( "testfile failed to reopen dirctory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } DPRINTF(("Listing non-hidden files in directory %s\n",TEST_DIR)); while ((dirEntry = PR_ReadDir(fd_dir, PR_SKIP_HIDDEN)) != NULL) { DPRINTF(("\t%s\n",dirEntry->name)); if (!strcmp(HIDDEN_FILE_NAME, dirEntry->name)) { printf("testfile found hidden file %s\n", pathname); return -1; } } /* * Delete hidden file */ strcpy(pathname, TEST_DIR); strcat(pathname, "/"); strcat(pathname, HIDDEN_FILE_NAME); if (PR_FAILURE == PR_Delete(pathname)) { printf( "testfile failed to delete hidden file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } PR_CloseDir(fd_dir); #endif /* XP_UNIX || (XP_PC && WIN32) */ strcpy(renamename, TEST_DIR); strcat(renamename, ".RENAMED"); if (PR_FAILURE == PR_Rename(TEST_DIR, renamename)) { printf( "testfile failed to rename directory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } if (PR_FAILURE == PR_MkDir(TEST_DIR, 0777)) { printf( "testfile failed to recreate dir %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } if (PR_SUCCESS == PR_Rename(renamename, TEST_DIR)) { printf( "testfile renamed directory to existing name %s\n", renamename); return -1; } if (PR_FAILURE == PR_RmDir(TEST_DIR)) { printf( "testfile failed to rmdir %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } if (PR_FAILURE == PR_Rename(renamename, TEST_DIR)) { printf( "testfile failed to rename directory %s [%d, %d]\n", renamename, PR_GetError(), PR_GetOSError()); return -1; } fd_dir = PR_OpenDir(TEST_DIR); if (fd_dir == NULL) { printf( "testfile failed to reopen directory %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } strcpy(pathname, TEST_DIR); strcat(pathname, "/"); strcat(pathname, FILE_NAME); path_len = strlen(pathname); for (i = 0; i < FILES_IN_DIR; i++) { sprintf(pathname + path_len,"%d%s",i,""); if (PR_FAILURE == PR_Delete(pathname)) { printf( "testfile failed to delete file %s [%d, %d]\n", pathname, PR_GetError(), PR_GetOSError()); return -1; } } PR_CloseDir(fd_dir); if (PR_FAILURE == PR_RmDir(TEST_DIR)) { printf( "testfile failed to rmdir %s [%d, %d]\n", TEST_DIR, PR_GetError(), PR_GetOSError()); return -1; } PR_EnterMonitor(tinfo->mon); tinfo->done = 1; PR_Notify(tinfo->mon); PR_ExitMonitor(tinfo->mon); return 0; } /************************************************************************/ /* * Test file and directory NSPR APIs */ int main(int argc, char **argv) { #ifdef WIN32 PRUint32 len; #endif #if defined(XP_UNIX) || defined(XP_OS2) int opt; extern char *optarg; extern int optind; #endif #if defined(XP_UNIX) || defined(XP_OS2) while ((opt = getopt(argc, argv, "d")) != EOF) { switch(opt) { case 'd': _debug_on = 1; break; default: break; } } #endif PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); mon = PR_NewMonitor(); if (mon == NULL) { printf("testfile: PR_NewMonitor failed\n"); exit(2); } #ifdef WIN32 #ifdef WINCE { WCHAR tdir[TMPDIR_LEN]; len = GetTempPath(TMPDIR_LEN, tdir); if ((len > 0) && (len < (TMPDIR_LEN - 6))) { /* * enough space for prdir */ WideCharToMultiByte(CP_ACP, 0, tdir, -1, testdir, TMPDIR_LEN, 0, 0); } } #else len = GetTempPath(TMPDIR_LEN, testdir); #endif /* WINCE */ if ((len > 0) && (len < (TMPDIR_LEN - 6))) { /* * enough space for prdir */ strcpy((testdir + len),"prdir"); TEST_DIR = testdir; printf("TEST_DIR = %s\n",TEST_DIR); } #endif /* WIN32 */ if (FileTest() < 0) { printf("File Test failed\n"); exit(2); } printf("File Test passed\n"); if ((RunDirTest() < 0) || dirtest_failed) { printf("Dir Test failed\n"); exit(2); } printf("Dir Test passed\n"); PR_DestroyMonitor(mon); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/threads.c0000644000000000000000000001163512623070344015121 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "prinrval.h" #include "plgetopt.h" #include "pprthred.h" #include #include #include PRMonitor *mon; PRInt32 count, iterations, alive; PRBool debug_mode = PR_FALSE, passed = PR_TRUE; void PR_CALLBACK ReallyDumbThread(void *arg) { return; } void PR_CALLBACK DumbThread(void *arg) { PRInt32 tmp = (PRInt32)arg; PRThreadScope scope = (PRThreadScope)tmp; PRThread *thr; thr = PR_CreateThread(PR_USER_THREAD, ReallyDumbThread, NULL, PR_PRIORITY_NORMAL, scope, PR_JOINABLE_THREAD, 0); if (!thr) { if (debug_mode) { printf("Could not create really dumb thread (%d, %d)!\n", PR_GetError(), PR_GetOSError()); } passed = PR_FALSE; } else { PR_JoinThread(thr); } PR_EnterMonitor(mon); alive--; PR_Notify(mon); PR_ExitMonitor(mon); } static void CreateThreads(PRThreadScope scope1, PRThreadScope scope2) { PRThread *thr; int n; alive = 0; mon = PR_NewMonitor(); alive = count; for (n=0; noption) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'c': /* loop counter */ count = atoi(opt->value); break; case 'i': /* loop counter */ iterations = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); } if (0 == count) count = 50; if (0 == iterations) iterations = 10; if (debug_mode) { printf("\ ** Tests lots of thread creations. \n\ ** Create %ld native threads %ld times. \n\ ** Create %ld user threads %ld times \n", iterations,count,iterations,count); } for (index=0; index #include #include #ifdef XP_UNIX #include #endif #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include #endif #ifdef WIN32 #include #endif static int _debug_on = 0; static int server_port = -1; static char *program_name = NULL; #include "obsolete/prsem.h" #ifdef XP_PC #define mode_t int #endif #define DPRINTF(arg) if (_debug_on) printf arg #define BUF_DATA_SIZE (2 * 1024) #define TCP_MESG_SIZE 1024 #define NUM_TCP_CLIENTS 10 /* for a listen queue depth of 5 */ #define NUM_TCP_CONNECTIONS_PER_CLIENT 10 #define NUM_TCP_MESGS_PER_CONNECTION 10 #define TCP_SERVER_PORT 10000 static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS; static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT; static PRInt32 tcp_mesg_size = TCP_MESG_SIZE; static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION; int failed_already=0; typedef struct buffer { char data[BUF_DATA_SIZE]; } buffer; PRNetAddr tcp_server_addr, udp_server_addr; typedef struct Client_Param { PRNetAddr server_addr; PRMonitor *exit_mon; /* monitor to signal on exit */ PRInt32 *exit_counter; /* counter to decrement, before exit */ PRInt32 datalen; } Client_Param; /* * readn * read data from sockfd into buf */ static PRInt32 readn(PRFileDesc *sockfd, char *buf, int len) { int rem; int bytes; int offset = 0; PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; for (rem=len; rem; offset += bytes, rem -= bytes) { DPRINTF(("thread = 0x%lx: calling PR_Recv, bytes = %d\n", PR_GetCurrentThread(), rem)); bytes = PR_Recv(sockfd, buf + offset, rem, 0, timeout); DPRINTF(("thread = 0x%lx: returning from PR_Recv, bytes = %d\n", PR_GetCurrentThread(), bytes)); if (bytes < 0) { return -1; } } return len; } /* * writen * write data from buf to sockfd */ static PRInt32 writen(PRFileDesc *sockfd, char *buf, int len) { int rem; int bytes; int offset = 0; for (rem=len; rem; offset += bytes, rem -= bytes) { DPRINTF(("thread = 0x%lx: calling PR_Send, bytes = %d\n", PR_GetCurrentThread(), rem)); bytes = PR_Send(sockfd, buf + offset, rem, 0, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("thread = 0x%lx: returning from PR_Send, bytes = %d\n", PR_GetCurrentThread(), bytes)); if (bytes <= 0) return -1; } return len; } /* * TCP_Client * Client job * Connect to the server at the address specified in the argument. * Fill in a buffer, write data to server, read it back and check * for data corruption. * Close the socket for server connection */ static void PR_CALLBACK TCP_Client(void *arg) { Client_Param *cp = (Client_Param *) arg; PRFileDesc *sockfd; buffer *in_buf, *out_buf; union PRNetAddr netaddr; PRInt32 bytes, i, j; DPRINTF(("TCP client started\n")); bytes = cp->datalen; out_buf = PR_NEW(buffer); if (out_buf == NULL) { fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name); failed_already=1; return; } in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"%s: failed to alloc buffer struct\n", program_name); failed_already=1; return; } netaddr.inet.family = cp->server_addr.inet.family; netaddr.inet.port = cp->server_addr.inet.port; netaddr.inet.ip = cp->server_addr.inet.ip; for (i = 0; i < num_tcp_connections_per_client; i++) { if ((sockfd = PR_OpenTCPSocket(PR_AF_INET)) == NULL) { fprintf(stderr,"%s: PR_OpenTCPSocket failed\n", program_name); failed_already=1; return; } DPRINTF(("TCP client connecting to server:%d\n", server_port)); if (PR_Connect(sockfd, &netaddr,PR_INTERVAL_NO_TIMEOUT) < 0){ fprintf(stderr, "PR_Connect failed: (%ld, %ld)\n", PR_GetError(), PR_GetOSError()); failed_already=1; return; } for (j = 0; j < num_tcp_mesgs_per_connection; j++) { /* * fill in random data */ memset(out_buf->data, ((PRInt32) (&netaddr)) + i + j, bytes); /* * write to server */ if (writen(sockfd, out_buf->data, bytes) < bytes) { fprintf(stderr,"%s: ERROR - TCP_Client:writen\n", program_name); failed_already=1; return; } /* DPRINTF(("TCP Client [0x%lx]: out_buf = 0x%lx out_buf[0] = 0x%lx\n", PR_GetCurrentThread(), out_buf, (*((int *) out_buf->data)))); */ if (readn(sockfd, in_buf->data, bytes) < bytes) { fprintf(stderr,"%s: ERROR - TCP_Client:readn\n", program_name); failed_already=1; return; } /* * verify the data read */ if (memcmp(in_buf->data, out_buf->data, bytes) != 0) { fprintf(stderr,"%s: ERROR - data corruption\n", program_name); failed_already=1; return; } } /* * shutdown reads and writes */ if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name); failed_already=1; } PR_Close(sockfd); } PR_DELETE(out_buf); PR_DELETE(in_buf); /* * Decrement exit_counter and notify parent thread */ PR_EnterMonitor(cp->exit_mon); --(*cp->exit_counter); PR_Notify(cp->exit_mon); PR_ExitMonitor(cp->exit_mon); DPRINTF(("TCP_Client exiting\n")); } /* * TCP_Socket_Client_Server_Test - concurrent server test * * Each client connects to the server and sends a chunk of data * For each connection, server reads the data * from the client and sends it back to the client, unmodified. * Each client checks that data received from server is same as the * data it sent to the server. * */ static PRInt32 TCP_Socket_Client_Server_Test(void) { int i; Client_Param *cparamp; PRMonitor *mon2; PRInt32 datalen; PRInt32 connections = 0; PRThread *thr; datalen = tcp_mesg_size; connections = 0; mon2 = PR_NewMonitor(); if (mon2 == NULL) { fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name); failed_already=1; return -1; } /* * Start client jobs */ cparamp = PR_NEW(Client_Param); if (cparamp == NULL) { fprintf(stderr,"%s: PR_NEW failed\n", program_name); failed_already=1; return -1; } cparamp->server_addr.inet.family = PR_AF_INET; cparamp->server_addr.inet.port = PR_htons(server_port); cparamp->server_addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK); cparamp->exit_mon = mon2; cparamp->exit_counter = &connections; cparamp->datalen = datalen; for (i = 0; i < num_tcp_clients; i++) { thr = PR_CreateThread(PR_USER_THREAD, TCP_Client, (void *)cparamp, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (NULL == thr) { fprintf(stderr,"%s: PR_CreateThread failed\n", program_name); failed_already=1; return -1; } PR_EnterMonitor(mon2); connections++; PR_ExitMonitor(mon2); DPRINTF(("Created TCP client = 0x%lx\n", thr)); } /* Wait for client jobs to exit */ PR_EnterMonitor(mon2); while (0 != connections) { PR_Wait(mon2, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("Client job count = %d\n", connections)); } PR_ExitMonitor(mon2); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); PR_DELETE(cparamp); return 0; } /************************************************************************/ int main(int argc, char **argv) { /* * -d debug mode */ PLOptStatus os; PLOptState *opt; program_name = argv[0]; opt = PL_CreateOptState(argc, argv, "dp:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; case 'p': server_port = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetConcurrency(4); TCP_Socket_Client_Server_Test(); PR_Cleanup(); if (failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/thrpool_server.c0000644000000000000000000003513512623070344016545 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: thrpool.c ** ** Description: Test threadpool functionality. ** ** Modification History: */ #include "primpl.h" #include "plgetopt.h" #include #include #include #ifdef XP_UNIX #include #endif #if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) #include #endif /* for getcwd */ #if defined(XP_UNIX) || defined (XP_OS2) || defined(XP_BEOS) #include #elif defined(XP_PC) #include #endif #ifdef WIN32 #include #endif static int _debug_on = 0; static char *program_name = NULL; static void serve_client_write(void *arg); #include "obsolete/prsem.h" #ifdef XP_PC #define mode_t int #endif #define DPRINTF(arg) if (_debug_on) printf arg #define BUF_DATA_SIZE (2 * 1024) #define TCP_MESG_SIZE 1024 #define NUM_TCP_CLIENTS 10 /* for a listen queue depth of 5 */ #define NUM_TCP_CONNECTIONS_PER_CLIENT 10 #define NUM_TCP_MESGS_PER_CONNECTION 10 #define TCP_SERVER_PORT 10000 #define SERVER_MAX_BIND_COUNT 100 #ifdef WINCE char *getcwd(char *buf, size_t size) { wchar_t wpath[MAX_PATH]; _wgetcwd(wpath, MAX_PATH); WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0); } #define perror(s) #endif static PRInt32 num_tcp_clients = NUM_TCP_CLIENTS; static PRInt32 num_tcp_connections_per_client = NUM_TCP_CONNECTIONS_PER_CLIENT; static PRInt32 tcp_mesg_size = TCP_MESG_SIZE; static PRInt32 num_tcp_mesgs_per_connection = NUM_TCP_MESGS_PER_CONNECTION; static void TCP_Server_Accept(void *arg); int failed_already=0; typedef struct buffer { char data[BUF_DATA_SIZE]; } buffer; typedef struct Server_Param { PRJobIoDesc iod; /* socket to read from/write to */ PRInt32 datalen; /* bytes of data transfered in each read/write */ PRNetAddr netaddr; PRMonitor *exit_mon; /* monitor to signal on exit */ PRInt32 *job_counterp; /* counter to decrement, before exit */ PRInt32 conn_counter; /* counter to decrement, before exit */ PRThreadPool *tp; } Server_Param; typedef struct Serve_Client_Param { PRJobIoDesc iod; /* socket to read from/write to */ PRInt32 datalen; /* bytes of data transfered in each read/write */ PRMonitor *exit_mon; /* monitor to signal on exit */ PRInt32 *job_counterp; /* counter to decrement, before exit */ PRThreadPool *tp; } Serve_Client_Param; typedef struct Session { PRJobIoDesc iod; /* socket to read from/write to */ buffer *in_buf; PRInt32 bytes; PRInt32 msg_num; PRInt32 bytes_read; PRMonitor *exit_mon; /* monitor to signal on exit */ PRInt32 *job_counterp; /* counter to decrement, before exit */ PRThreadPool *tp; } Session; static void serve_client_read(void *arg) { Session *sp = (Session *) arg; int rem; int bytes; int offset; PRFileDesc *sockfd; char *buf; PRJob *jobp; PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; sockfd = sp->iod.socket; buf = sp->in_buf->data; PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection); PR_ASSERT(sp->bytes_read < sp->bytes); offset = sp->bytes_read; rem = sp->bytes - offset; bytes = PR_Recv(sockfd, buf + offset, rem, 0, timeout); if (bytes < 0) { return; } sp->bytes_read += bytes; sp->iod.timeout = PR_SecondsToInterval(60); if (sp->bytes_read < sp->bytes) { jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } PR_ASSERT(sp->bytes_read == sp->bytes); DPRINTF(("serve_client: read complete, msg(%d) \n", sp->msg_num)); sp->iod.timeout = PR_SecondsToInterval(60); jobp = PR_QueueJob_Write(sp->tp, &sp->iod, serve_client_write, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } static void serve_client_write(void *arg) { Session *sp = (Session *) arg; int bytes; PRFileDesc *sockfd; char *buf; PRJob *jobp; sockfd = sp->iod.socket; buf = sp->in_buf->data; PR_ASSERT(sp->msg_num < num_tcp_mesgs_per_connection); bytes = PR_Send(sockfd, buf, sp->bytes, 0, PR_INTERVAL_NO_TIMEOUT); PR_ASSERT(bytes == sp->bytes); if (bytes < 0) { return; } DPRINTF(("serve_client: write complete, msg(%d) \n", sp->msg_num)); sp->msg_num++; if (sp->msg_num < num_tcp_mesgs_per_connection) { sp->bytes_read = 0; sp->iod.timeout = PR_SecondsToInterval(60); jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } DPRINTF(("serve_client: read/write complete, msg(%d) \n", sp->msg_num)); if (PR_Shutdown(sockfd, PR_SHUTDOWN_BOTH) < 0) { fprintf(stderr,"%s: ERROR - PR_Shutdown\n", program_name); } PR_Close(sockfd); PR_EnterMonitor(sp->exit_mon); --(*sp->job_counterp); PR_Notify(sp->exit_mon); PR_ExitMonitor(sp->exit_mon); PR_DELETE(sp->in_buf); PR_DELETE(sp); return; } /* * Serve_Client * Thread, started by the server, for serving a client connection. * Reads data from socket and writes it back, unmodified, and * closes the socket */ static void PR_CALLBACK Serve_Client(void *arg) { Serve_Client_Param *scp = (Serve_Client_Param *) arg; buffer *in_buf; Session *sp; PRJob *jobp; sp = PR_NEW(Session); sp->iod = scp->iod; in_buf = PR_NEW(buffer); if (in_buf == NULL) { fprintf(stderr,"%s: failed to alloc buffer struct\n",program_name); failed_already=1; return; } sp->in_buf = in_buf; sp->bytes = scp->datalen; sp->msg_num = 0; sp->bytes_read = 0; sp->tp = scp->tp; sp->exit_mon = scp->exit_mon; sp->job_counterp = scp->job_counterp; sp->iod.timeout = PR_SecondsToInterval(60); jobp = PR_QueueJob_Read(sp->tp, &sp->iod, serve_client_read, sp, PR_FALSE); PR_ASSERT(NULL != jobp); PR_DELETE(scp); } static void print_stats(void *arg) { Server_Param *sp = (Server_Param *) arg; PRThreadPool *tp = sp->tp; PRInt32 counter; PRJob *jobp; PR_EnterMonitor(sp->exit_mon); counter = (*sp->job_counterp); PR_ExitMonitor(sp->exit_mon); printf("PRINT_STATS: #client connections = %d\n",counter); jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500), print_stats, sp, PR_FALSE); PR_ASSERT(NULL != jobp); } static int job_counter = 0; /* * TCP Server * Server binds an address to a socket, starts a client process and * listens for incoming connections. * Each client connects to the server and sends a chunk of data * Starts a Serve_Client job for each incoming connection, to read * the data from the client and send it back to the client, unmodified. * Each client checks that data received from server is same as the * data it sent to the server. * Finally, the threadpool is shutdown */ static void PR_CALLBACK TCP_Server(void *arg) { PRThreadPool *tp = (PRThreadPool *) arg; Server_Param *sp; PRFileDesc *sockfd; PRNetAddr netaddr; PRMonitor *sc_mon; PRJob *jobp; int i; PRStatus rval; /* * Create a tcp socket */ if ((sockfd = PR_NewTCPSocket()) == NULL) { fprintf(stderr,"%s: PR_NewTCPSocket failed\n", program_name); return; } memset(&netaddr, 0 , sizeof(netaddr)); netaddr.inet.family = PR_AF_INET; netaddr.inet.port = PR_htons(TCP_SERVER_PORT); netaddr.inet.ip = PR_htonl(PR_INADDR_ANY); /* * try a few times to bind server's address, if addresses are in * use */ i = 0; while (PR_Bind(sockfd, &netaddr) < 0) { if (PR_GetError() == PR_ADDRESS_IN_USE_ERROR) { netaddr.inet.port += 2; if (i++ < SERVER_MAX_BIND_COUNT) continue; } fprintf(stderr,"%s: ERROR - PR_Bind failed\n", program_name); perror("PR_Bind"); failed_already=1; return; } if (PR_Listen(sockfd, 32) < 0) { fprintf(stderr,"%s: ERROR - PR_Listen failed\n", program_name); failed_already=1; return; } if (PR_GetSockName(sockfd, &netaddr) < 0) { fprintf(stderr,"%s: ERROR - PR_GetSockName failed\n", program_name); failed_already=1; return; } DPRINTF(( "TCP_Server: PR_BIND netaddr.inet.ip = 0x%lx, netaddr.inet.port = %d\n", netaddr.inet.ip, netaddr.inet.port)); sp = PR_NEW(Server_Param); if (sp == NULL) { fprintf(stderr,"%s: PR_NEW failed\n", program_name); failed_already=1; return; } sp->iod.socket = sockfd; sp->iod.timeout = PR_SecondsToInterval(60); sp->datalen = tcp_mesg_size; sp->exit_mon = sc_mon; sp->job_counterp = &job_counter; sp->conn_counter = 0; sp->tp = tp; sp->netaddr = netaddr; /* create and cancel an io job */ jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, PR_FALSE); PR_ASSERT(NULL != jobp); rval = PR_CancelJob(jobp); PR_ASSERT(PR_SUCCESS == rval); /* * create the client process */ { #define MAX_ARGS 4 char *argv[MAX_ARGS + 1]; int index = 0; char port[32]; char path[1024 + sizeof("/thrpool_client")]; getcwd(path, sizeof(path)); (void)strcat(path, "/thrpool_client"); #ifdef XP_PC (void)strcat(path, ".exe"); #endif argv[index++] = path; sprintf(port,"%d",PR_ntohs(netaddr.inet.port)); if (_debug_on) { argv[index++] = "-d"; argv[index++] = "-p"; argv[index++] = port; argv[index++] = NULL; } else { argv[index++] = "-p"; argv[index++] = port; argv[index++] = NULL; } PR_ASSERT(MAX_ARGS >= (index - 1)); DPRINTF(("creating client process %s ...\n", path)); if (PR_FAILURE == PR_CreateProcessDetached(path, argv, NULL, NULL)) { fprintf(stderr, "thrpool_server: ERROR - PR_CreateProcessDetached failed\n"); failed_already=1; return; } } sc_mon = PR_NewMonitor(); if (sc_mon == NULL) { fprintf(stderr,"%s: PR_NewMonitor failed\n", program_name); failed_already=1; return; } sp->iod.socket = sockfd; sp->iod.timeout = PR_SecondsToInterval(60); sp->datalen = tcp_mesg_size; sp->exit_mon = sc_mon; sp->job_counterp = &job_counter; sp->conn_counter = 0; sp->tp = tp; sp->netaddr = netaddr; /* create and cancel a timer job */ jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(5000), print_stats, sp, PR_FALSE); PR_ASSERT(NULL != jobp); rval = PR_CancelJob(jobp); PR_ASSERT(PR_SUCCESS == rval); DPRINTF(("TCP_Server: Accepting connections \n")); jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } static void TCP_Server_Accept(void *arg) { Server_Param *sp = (Server_Param *) arg; PRThreadPool *tp = sp->tp; Serve_Client_Param *scp; PRFileDesc *newsockfd; PRJob *jobp; if ((newsockfd = PR_Accept(sp->iod.socket, &sp->netaddr, PR_INTERVAL_NO_TIMEOUT)) == NULL) { fprintf(stderr,"%s: ERROR - PR_Accept failed\n", program_name); failed_already=1; goto exit; } scp = PR_NEW(Serve_Client_Param); if (scp == NULL) { fprintf(stderr,"%s: PR_NEW failed\n", program_name); failed_already=1; goto exit; } /* * Start a Serve_Client job for each incoming connection */ scp->iod.socket = newsockfd; scp->iod.timeout = PR_SecondsToInterval(60); scp->datalen = tcp_mesg_size; scp->exit_mon = sp->exit_mon; scp->job_counterp = sp->job_counterp; scp->tp = sp->tp; PR_EnterMonitor(sp->exit_mon); (*sp->job_counterp)++; PR_ExitMonitor(sp->exit_mon); jobp = PR_QueueJob(tp, Serve_Client, scp, PR_FALSE); PR_ASSERT(NULL != jobp); DPRINTF(("TCP_Server: Created Serve_Client = 0x%lx\n", jobp)); /* * single-threaded update; no lock needed */ sp->conn_counter++; if (sp->conn_counter < (num_tcp_clients * num_tcp_connections_per_client)) { jobp = PR_QueueJob_Accept(tp, &sp->iod, TCP_Server_Accept, sp, PR_FALSE); PR_ASSERT(NULL != jobp); return; } jobp = PR_QueueJob_Timer(tp, PR_MillisecondsToInterval(500), print_stats, sp, PR_FALSE); PR_ASSERT(NULL != jobp); DPRINTF(("TCP_Server: Created print_stats timer job = 0x%lx\n", jobp)); exit: PR_EnterMonitor(sp->exit_mon); /* Wait for server jobs to finish */ while (0 != *sp->job_counterp) { PR_Wait(sp->exit_mon, PR_INTERVAL_NO_TIMEOUT); DPRINTF(("TCP_Server: conn_counter = %d\n", *sp->job_counterp)); } PR_ExitMonitor(sp->exit_mon); if (sp->iod.socket) { PR_Close(sp->iod.socket); } PR_DestroyMonitor(sp->exit_mon); printf("%30s","TCP_Socket_Client_Server_Test:"); printf("%2ld Server %2ld Clients %2ld connections_per_client\n",1l, num_tcp_clients, num_tcp_connections_per_client); printf("%30s %2ld messages_per_connection %4ld bytes_per_message\n",":", num_tcp_mesgs_per_connection, tcp_mesg_size); DPRINTF(("%s: calling PR_ShutdownThreadPool\n", program_name)); PR_ShutdownThreadPool(sp->tp); PR_DELETE(sp); } /************************************************************************/ #define DEFAULT_INITIAL_THREADS 4 #define DEFAULT_MAX_THREADS 100 #define DEFAULT_STACKSIZE (512 * 1024) int main(int argc, char **argv) { PRInt32 initial_threads = DEFAULT_INITIAL_THREADS; PRInt32 max_threads = DEFAULT_MAX_THREADS; PRInt32 stacksize = DEFAULT_STACKSIZE; PRThreadPool *tp = NULL; PRStatus rv; PRJob *jobp; /* * -d debug mode */ PLOptStatus os; PLOptState *opt; program_name = argv[0]; opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); PR_SetConcurrency(4); tp = PR_CreateThreadPool(initial_threads, max_threads, stacksize); if (NULL == tp) { printf("PR_CreateThreadPool failed\n"); failed_already=1; goto done; } jobp = PR_QueueJob(tp, TCP_Server, tp, PR_TRUE); rv = PR_JoinJob(jobp); PR_ASSERT(PR_SUCCESS == rv); DPRINTF(("%s: calling PR_JoinThreadPool\n", program_name)); rv = PR_JoinThreadPool(tp); PR_ASSERT(PR_SUCCESS == rv); DPRINTF(("%s: returning from PR_JoinThreadPool\n", program_name)); done: PR_Cleanup(); if (failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/thruput.c0000644000000000000000000002722612623070344015205 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: thruput.c ** Description: Test server's throughput capability comparing various ** implmentation strategies. ** ** Note: Requires a server machine and an aribitrary number of ** clients to bang on it. Trust the numbers on the server ** more than those being displayed by the various clients. */ #include "prerror.h" #include "prinrval.h" #include "prinit.h" #include "prio.h" #include "prlock.h" #include "prmem.h" #include "prnetdb.h" #include "prprf.h" #include "prthread.h" #include "pprio.h" #include "plerror.h" #include "plgetopt.h" #define ADDR_BUFFER 100 #define PORT_NUMBER 51877 #define SAMPLING_INTERVAL 10 #define BUFFER_SIZE (32 * 1024) static PRInt32 domain = PR_AF_INET; static PRInt32 protocol = 6; /* TCP */ static PRFileDesc *err = NULL; static PRIntn concurrency = 1; static PRInt32 xport_buffer = -1; static PRUint32 initial_streams = 1; static PRInt32 buffer_size = BUFFER_SIZE; static PRThreadScope thread_scope = PR_LOCAL_THREAD; typedef struct Shared { PRLock *ml; PRUint32 sampled; PRUint32 threads; PRIntervalTime timein; PRNetAddr server_address; } Shared; static Shared *shared = NULL; static PRStatus PrintAddress(const PRNetAddr* address) { char buffer[ADDR_BUFFER]; PRStatus rv = PR_NetAddrToString(address, buffer, sizeof(buffer)); if (PR_SUCCESS == rv) PR_fprintf(err, "%s:%u\n", buffer, PR_ntohs(address->inet.port)); else PL_FPrintError(err, "PR_NetAddrToString"); return rv; } /* PrintAddress */ static void PR_CALLBACK Clientel(void *arg) { PRStatus rv; PRFileDesc *xport; PRInt32 bytes, sampled; PRIntervalTime now, interval; PRBool do_display = PR_FALSE; Shared *shared = (Shared*)arg; char *buffer = (char*)PR_Malloc(buffer_size); PRNetAddr *server_address = &shared->server_address; PRIntervalTime connect_timeout = PR_SecondsToInterval(5); PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL); PR_fprintf(err, "Client connecting to "); (void)PrintAddress(server_address); do { xport = PR_Socket(domain, PR_SOCK_STREAM, protocol); if (NULL == xport) { PL_FPrintError(err, "PR_Socket"); return; } if (xport_buffer != -1) { PRSocketOptionData data; data.option = PR_SockOpt_RecvBufferSize; data.value.recv_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(xport, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); data.option = PR_SockOpt_SendBufferSize; data.value.send_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(xport, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); } rv = PR_Connect(xport, server_address, connect_timeout); if (PR_FAILURE == rv) { PL_FPrintError(err, "PR_Connect"); if (PR_IO_TIMEOUT_ERROR != PR_GetError()) PR_Sleep(connect_timeout); PR_Close(xport); /* delete it and start over */ } } while (PR_FAILURE == rv); do { bytes = PR_Recv( xport, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT); PR_Lock(shared->ml); now = PR_IntervalNow(); shared->sampled += bytes; interval = now - shared->timein; if (interval > sampling_interval) { sampled = shared->sampled; shared->timein = now; shared->sampled = 0; do_display = PR_TRUE; } PR_Unlock(shared->ml); if (do_display) { PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval); PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate); do_display = PR_FALSE; } } while (bytes > 0); } /* Clientel */ static void Client(const char *server_name) { PRStatus rv; PRHostEnt host; char buffer[PR_NETDB_BUF_SIZE]; PRIntervalTime dally = PR_SecondsToInterval(60); PR_fprintf(err, "Translating the name %s\n", server_name); rv = PR_GetHostByName(server_name, buffer, sizeof(buffer), &host); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_GetHostByName"); else { if (PR_EnumerateHostEnt( 0, &host, PORT_NUMBER, &shared->server_address) < 0) PL_FPrintError(err, "PR_EnumerateHostEnt"); else { do { shared->threads += 1; (void)PR_CreateThread( PR_USER_THREAD, Clientel, shared, PR_PRIORITY_NORMAL, thread_scope, PR_UNJOINABLE_THREAD, 8 * 1024); if (shared->threads == initial_streams) { PR_Sleep(dally); initial_streams += 1; } } while (PR_TRUE); } } } static void PR_CALLBACK Servette(void *arg) { PRInt32 bytes, sampled; PRIntervalTime now, interval; PRBool do_display = PR_FALSE; PRFileDesc *client = (PRFileDesc*)arg; char *buffer = (char*)PR_Malloc(buffer_size); PRIntervalTime sampling_interval = PR_SecondsToInterval(SAMPLING_INTERVAL); if (xport_buffer != -1) { PRStatus rv; PRSocketOptionData data; data.option = PR_SockOpt_RecvBufferSize; data.value.recv_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(client, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); data.option = PR_SockOpt_SendBufferSize; data.value.send_buffer_size = (PRSize)xport_buffer; rv = PR_SetSocketOption(client, &data); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_SetSocketOption - ignored"); } do { bytes = PR_Send( client, buffer, buffer_size, 0, PR_INTERVAL_NO_TIMEOUT); PR_Lock(shared->ml); now = PR_IntervalNow(); shared->sampled += bytes; interval = now - shared->timein; if (interval > sampling_interval) { sampled = shared->sampled; shared->timein = now; shared->sampled = 0; do_display = PR_TRUE; } PR_Unlock(shared->ml); if (do_display) { PRUint32 rate = sampled / PR_IntervalToMilliseconds(interval); PR_fprintf(err, "%u streams @ %u Kbytes/sec\n", shared->threads, rate); do_display = PR_FALSE; } } while (bytes > 0); } /* Servette */ static void Server(void) { PRStatus rv; PRNetAddr server_address, client_address; PRFileDesc *xport = PR_Socket(domain, PR_SOCK_STREAM, protocol); if (NULL == xport) { PL_FPrintError(err, "PR_Socket"); return; } rv = PR_InitializeNetAddr(PR_IpAddrAny, PORT_NUMBER, &server_address); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_InitializeNetAddr"); else { rv = PR_Bind(xport, &server_address); if (PR_FAILURE == rv) PL_FPrintError(err, "PR_Bind"); else { PRFileDesc *client; rv = PR_Listen(xport, 10); PR_fprintf(err, "Server listening on "); (void)PrintAddress(&server_address); do { client = PR_Accept( xport, &client_address, PR_INTERVAL_NO_TIMEOUT); if (NULL == client) PL_FPrintError(err, "PR_Accept"); else { PR_fprintf(err, "Server accepting from "); (void)PrintAddress(&client_address); shared->threads += 1; (void)PR_CreateThread( PR_USER_THREAD, Servette, client, PR_PRIORITY_NORMAL, thread_scope, PR_UNJOINABLE_THREAD, 8 * 1024); } } while (PR_TRUE); } } } /* Server */ static void Help(void) { PR_fprintf(err, "Usage: [-h] []\n"); PR_fprintf(err, "\t-s Initial # of connections (default: 1)\n"); PR_fprintf(err, "\t-C Set 'concurrency' (default: 1)\n"); PR_fprintf(err, "\t-b Client buffer size (default: 32k)\n"); PR_fprintf(err, "\t-B Transport recv/send buffer size (default: sys)\n"); PR_fprintf(err, "\t-G Use GLOBAL threads (default: LOCAL)\n"); PR_fprintf(err, "\t-X Use XTP transport (default: TCP)\n"); PR_fprintf(err, "\t-6 Use IPv6 (default: IPv4)\n"); PR_fprintf(err, "\t-h This message and nothing else\n"); PR_fprintf(err, "\t DNS name of server\n"); PR_fprintf(err, "\t\tIf is not specified, this host will be\n"); PR_fprintf(err, "\t\tthe server and not act as a client.\n"); } /* Help */ int main(int argc, char **argv) { PLOptStatus os; const char *server_name = NULL; PLOptState *opt = PL_CreateOptState(argc, argv, "hGX6C:b:s:B:"); err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* Name of server */ server_name = opt->value; break; case 'G': /* Globular threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'X': /* Use XTP as the transport */ protocol = 36; break; case '6': /* Use IPv6 */ domain = PR_AF_INET6; break; case 's': /* initial_streams */ initial_streams = atoi(opt->value); break; case 'C': /* concurrency */ concurrency = atoi(opt->value); break; case 'b': /* buffer size */ buffer_size = 1024 * atoi(opt->value); break; case 'B': /* buffer size */ xport_buffer = 1024 * atoi(opt->value); break; case 'h': /* user wants some guidance */ default: Help(); /* so give him an earful */ return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); shared = PR_NEWZAP(Shared); shared->ml = PR_NewLock(); PR_fprintf(err, "This machine is %s\n", (NULL == server_name) ? "the SERVER" : "a CLIENT"); PR_fprintf(err, "Transport being used is %s\n", (6 == protocol) ? "TCP" : "XTP"); if (PR_GLOBAL_THREAD == thread_scope) { if (1 != concurrency) { PR_fprintf(err, " **Concurrency > 1 and GLOBAL threads!?!?\n"); PR_fprintf(err, " **Ignoring concurrency\n"); concurrency = 1; } } if (1 != concurrency) { PR_SetConcurrency(concurrency); PR_fprintf(err, "Concurrency set to %u\n", concurrency); } PR_fprintf(err, "All threads will be %s\n", (PR_GLOBAL_THREAD == thread_scope) ? "GLOBAL" : "LOCAL"); PR_fprintf(err, "Client buffer size will be %u\n", buffer_size); if (-1 != xport_buffer) PR_fprintf( err, "Transport send & receive buffer size will be %u\n", xport_buffer); if (NULL == server_name) Server(); else Client(server_name); return 0; } /* main */ /* thruput.c */ nspr-4.11/nspr/pr/tests/time.c0000644000000000000000000000723612623070344014427 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Program to test different ways to get the time; right now it is tuned * only for solaris. * solaris results (100000 iterations): * time to get time with time(): 4.63 usec avg, 463 msec total * time to get time with gethrtime(): 2.17 usec avg, 217 msec total * time to get time with gettimeofday(): 1.25 usec avg, 125 msec total * * */ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "prpriv.h" #include "prinrval.h" #include #include #include #include #define DEFAULT_COUNT 100000 PRInt32 count; time_t itime; hrtime_t ihrtime; void ftime_init() { itime = time(NULL); ihrtime = gethrtime(); } time_t ftime() { hrtime_t now = gethrtime(); return itime + ((now - ihrtime) / 1000000000ll); } static void timeTime(void) { PRInt32 index = count; time_t rv; for (;index--;) rv = time(NULL); } static void timeGethrtime(void) { PRInt32 index = count; time_t rv; for (;index--;) rv = ftime(); } static void timeGettimeofday(void) { PRInt32 index = count; time_t rv; struct timeval tp; for (;index--;) rv = gettimeofday(&tp, NULL); } static void timePRTime32(void) { PRInt32 index = count; PRInt32 rv32; PRTime q; PRTime rv; LL_I2L(q, 1000000); for (;index--;) { rv = PR_Now(); LL_DIV(rv, rv, q); LL_L2I(rv32, rv); } } static void timePRTime64(void) { PRInt32 index = count; PRTime rv; for (;index--;) rv = PR_Now(); } /************************************************************************/ static void Measure(void (*func)(void), const char *msg) { PRIntervalTime start, stop; double d; PRInt32 tot; start = PR_IntervalNow(); (*func)(); stop = PR_IntervalNow(); d = (double)PR_IntervalToMicroseconds(stop - start); tot = PR_IntervalToMilliseconds(stop-start); if (debug_mode) printf("%40s: %6.2f usec avg, %d msec total\n", msg, d / count, tot); } int main(int argc, char **argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "d:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); if (argc > 1) { count = atoi(argv[1]); } else { count = DEFAULT_COUNT; } ftime_init(); Measure(timeTime, "time to get time with time()"); Measure(timeGethrtime, "time to get time with gethrtime()"); Measure(timeGettimeofday, "time to get time with gettimeofday()"); Measure(timePRTime32, "time to get time with PR_Time() (32bit)"); Measure(timePRTime64, "time to get time with PR_Time() (64bit)"); PR_Cleanup(); return 0; } nspr-4.11/nspr/pr/tests/timemac.c0000644000000000000000000000632512623070344015106 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * file: timemac.c * description: test time and date routines on the Mac */ #include #include "prinit.h" #include "prtime.h" static char *dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" }; static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" }; static void printExplodedTime(const PRExplodedTime *et) { PRInt32 totalOffset; PRInt32 hourOffset, minOffset; const char *sign; /* Print day of the week, month, day, hour, minute, and second */ printf( "%s %s %ld %02ld:%02ld:%02ld ", dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday, et->tm_hour, et->tm_min, et->tm_sec); /* Print time zone */ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset; if (totalOffset == 0) { printf("UTC "); } else { sign = ""; if (totalOffset < 0) { totalOffset = -totalOffset; sign = "-"; } hourOffset = totalOffset / 3600; minOffset = (totalOffset % 3600) / 60; printf("%s%02ld%02ld ", sign, hourOffset, minOffset); } /* Print year */ printf("%d", et->tm_year); } int main(int argc, char** argv) { PR_STDIO_INIT(); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); /* ************************************************************* ** ** Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime ** on the current time ** ************************************************************* */ { PRTime t1, t2; PRExplodedTime et; printf("*********************************************\n"); printf("** **\n"); printf("** Testing PR_Now(), PR_ExplodeTime, and **\n"); printf("** PR_ImplodeTime on the current time **\n"); printf("** **\n"); printf("*********************************************\n\n"); t1 = PR_Now(); /* First try converting to UTC */ PR_ExplodeTime(t1, PR_GMTParameters, &et); if (et.tm_params.tp_gmt_offset || et.tm_params.tp_dst_offset) { printf("ERROR: UTC has nonzero gmt or dst offset.\n"); return 1; } printf("Current UTC is "); printExplodedTime(&et); printf("\n"); t2 = PR_ImplodeTime(&et); if (LL_NE(t1, t2)) { printf("ERROR: Explode and implode are NOT inverse.\n"); return 1; } /* Next, try converting to local (US Pacific) time */ PR_ExplodeTime(t1, PR_LocalTimeParameters, &et); printf("Current local time is "); printExplodedTime(&et); printf("\n"); printf("GMT offset is %ld, DST offset is %ld\n", et.tm_params.tp_gmt_offset, et.tm_params.tp_dst_offset); t2 = PR_ImplodeTime(&et); if (LL_NE(t1, t2)) { printf("ERROR: Explode and implode are NOT inverse.\n"); return 1; } } printf("Please examine the results\n"); return 0; } nspr-4.11/nspr/pr/tests/timetest.c0000644000000000000000000005115112623070344015322 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * file: timetest.c * description: test time and date routines */ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prtime.h" #include "prprf.h" #include #include #include int failed_already=0; PRBool debug_mode = PR_FALSE; static char *dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" }; static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" }; static void PrintExplodedTime(const PRExplodedTime *et) { PRInt32 totalOffset; PRInt32 hourOffset, minOffset; const char *sign; /* Print day of the week, month, day, hour, minute, and second */ if (debug_mode) printf("%s %s %ld %02ld:%02ld:%02ld ", dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday, et->tm_hour, et->tm_min, et->tm_sec); /* Print time zone */ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset; if (totalOffset == 0) { if (debug_mode) printf("UTC "); } else { sign = "+"; if (totalOffset < 0) { totalOffset = -totalOffset; sign = "-"; } hourOffset = totalOffset / 3600; minOffset = (totalOffset % 3600) / 60; if (debug_mode) printf("%s%02ld%02ld ", sign, hourOffset, minOffset); } /* Print year */ if (debug_mode) printf("%hd", et->tm_year); } static int ExplodedTimeIsEqual(const PRExplodedTime *et1, const PRExplodedTime *et2) { if (et1->tm_usec == et2->tm_usec && et1->tm_sec == et2->tm_sec && et1->tm_min == et2->tm_min && et1->tm_hour == et2->tm_hour && et1->tm_mday == et2->tm_mday && et1->tm_month == et2->tm_month && et1->tm_year == et2->tm_year && et1->tm_wday == et2->tm_wday && et1->tm_yday == et2->tm_yday && et1->tm_params.tp_gmt_offset == et2->tm_params.tp_gmt_offset && et1->tm_params.tp_dst_offset == et2->tm_params.tp_dst_offset) { return 1; } else { return 0; } } static void testParseTimeString(PRTime t) { PRExplodedTime et; PRTime t2; char timeString[128]; char buf[128]; PRInt32 totalOffset; PRInt32 hourOffset, minOffset; const char *sign; PRInt64 usec_per_sec; /* Truncate the microsecond part of PRTime */ LL_I2L(usec_per_sec, PR_USEC_PER_SEC); LL_DIV(t, t, usec_per_sec); LL_MUL(t, t, usec_per_sec); PR_ExplodeTime(t, PR_LocalTimeParameters, &et); /* Print day of the week, month, day, hour, minute, and second */ PR_snprintf(timeString, 128, "%s %s %ld %02ld:%02ld:%02ld ", dayOfWeek[et.tm_wday], month[et.tm_month], et.tm_mday, et.tm_hour, et.tm_min, et.tm_sec); /* Print time zone */ totalOffset = et.tm_params.tp_gmt_offset + et.tm_params.tp_dst_offset; if (totalOffset == 0) { strcat(timeString, "GMT "); /* I wanted to use "UTC" here, but * PR_ParseTimeString doesn't * understand "UTC". */ } else { sign = "+"; if (totalOffset < 0) { totalOffset = -totalOffset; sign = "-"; } hourOffset = totalOffset / 3600; minOffset = (totalOffset % 3600) / 60; PR_snprintf(buf, 128, "%s%02ld%02ld ", sign, hourOffset, minOffset); strcat(timeString, buf); } /* Print year */ PR_snprintf(buf, 128, "%hd", et.tm_year); strcat(timeString, buf); if (PR_ParseTimeString(timeString, PR_FALSE, &t2) == PR_FAILURE) { fprintf(stderr, "PR_ParseTimeString() failed\n"); exit(1); } if (LL_NE(t, t2)) { fprintf(stderr, "PR_ParseTimeString() incorrect\n"); PR_snprintf(buf, 128, "t is %lld, t2 is %lld, time string is %s\n", t, t2, timeString); fprintf(stderr, "%s\n", buf); exit(1); } } int main(int argc, char** argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt; PR_STDIO_INIT(); opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); /* Testing zero PRTime (the epoch) */ { PRTime t; PRExplodedTime et; LL_I2L(t, 0); if (debug_mode) printf("The NSPR epoch is:\n"); PR_ExplodeTime(t, PR_LocalTimeParameters, &et); PrintExplodedTime(&et); if (debug_mode) printf("\n"); PR_ExplodeTime(t, PR_GMTParameters, &et); PrintExplodedTime(&et); if (debug_mode) printf("\n\n"); testParseTimeString(t); } /* ************************************************************* ** ** Testing PR_Now(), PR_ExplodeTime, and PR_ImplodeTime ** on the current time ** ************************************************************* */ { PRTime t1, t2; PRExplodedTime et; if (debug_mode) { printf("*********************************************\n"); printf("** **\n"); printf("** Testing PR_Now(), PR_ExplodeTime, and **\n"); printf("** PR_ImplodeTime on the current time **\n"); printf("** **\n"); printf("*********************************************\n\n"); } t1 = PR_Now(); /* First try converting to UTC */ PR_ExplodeTime(t1, PR_GMTParameters, &et); if (et.tm_params.tp_gmt_offset || et.tm_params.tp_dst_offset) { if (debug_mode) printf("ERROR: UTC has nonzero gmt or dst offset.\n"); else failed_already=1; return 1; } if (debug_mode) printf("Current UTC is "); PrintExplodedTime(&et); if (debug_mode) printf("\n"); t2 = PR_ImplodeTime(&et); if (LL_NE(t1, t2)) { if (debug_mode) printf("ERROR: Explode and implode are NOT inverse.\n"); else printf("FAIL\n"); return 1; } /* Next, try converting to local (US Pacific) time */ PR_ExplodeTime(t1, PR_LocalTimeParameters, &et); if (debug_mode) printf("Current local time is "); PrintExplodedTime(&et); if (debug_mode) printf("\n"); if (debug_mode) printf("GMT offset is %ld, DST offset is %ld\n", et.tm_params.tp_gmt_offset, et.tm_params.tp_dst_offset); t2 = PR_ImplodeTime(&et); if (LL_NE(t1, t2)) { if (debug_mode) printf("ERROR: Explode and implode are NOT inverse.\n"); return 1; } if (debug_mode) printf("Please examine the results\n"); testParseTimeString(t1); } /* ******************************************* ** ** Testing PR_NormalizeTime() ** ******************************************* */ /* July 4, 2001 is Wednesday */ { PRExplodedTime et; if (debug_mode) { printf("\n"); printf("**********************************\n"); printf("** **\n"); printf("** Testing PR_NormalizeTime() **\n"); printf("** **\n"); printf("**********************************\n\n"); } et.tm_year = 2001; et.tm_month = 7 - 1; et.tm_mday = 4; et.tm_hour = 0; et.tm_min = 0; et.tm_sec = 0; et.tm_usec = 0; et.tm_params = PR_GMTParameters(&et); PR_NormalizeTime(&et, PR_GMTParameters); if (debug_mode) printf("July 4, 2001 is %s.\n", dayOfWeek[et.tm_wday]); if (et.tm_wday == 3) { if (debug_mode) printf("PASS\n"); } else { if (debug_mode) printf("ERROR: It should be Wednesday\n"); else failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et)); /* June 12, 1997 23:00 PST == June 13, 1997 00:00 PDT */ et.tm_year = 1997; et.tm_month = 6 - 1; et.tm_mday = 12; et.tm_hour = 23; et.tm_min = 0; et.tm_sec = 0; et.tm_usec = 0; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; PR_NormalizeTime(&et, PR_USPacificTimeParameters); if (debug_mode) { printf("Thu Jun 12, 1997 23:00:00 PST is "); } PrintExplodedTime(&et); if (debug_mode) printf(".\n"); if (et.tm_wday == 5) { if (debug_mode) printf("PASS\n"); } else { if (debug_mode) printf("ERROR: It should be Friday\n"); else failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et)); /* Feb 14, 1997 00:00:00 PDT == Feb 13, 1997 23:00:00 PST */ et.tm_year = 1997; et.tm_month = 2 - 1; et.tm_mday = 14; et.tm_hour = 0; et.tm_min = 0; et.tm_sec = 0; et.tm_usec = 0; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 3600; PR_NormalizeTime(&et, PR_USPacificTimeParameters); if (debug_mode) { printf("Fri Feb 14, 1997 00:00:00 PDT is "); } PrintExplodedTime(&et); if (debug_mode) printf(".\n"); if (et.tm_wday == 4) { if (debug_mode) printf("PASS\n"); } else { if (debug_mode) printf("ERROR: It should be Thursday\n"); else failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et)); /* What time is Nov. 7, 1996, 18:29:23 PDT? */ et.tm_year = 1996; et.tm_month = 11 - 1; et.tm_mday = 7; et.tm_hour = 18; et.tm_min = 29; et.tm_sec = 23; et.tm_usec = 0; et.tm_params.tp_gmt_offset = -8 * 3600; /* PDT */ et.tm_params.tp_dst_offset = 3600; PR_NormalizeTime(&et, PR_LocalTimeParameters); if (debug_mode) printf("Nov 7 18:29:23 PDT 1996 is "); PrintExplodedTime(&et); if (debug_mode) printf(".\n"); testParseTimeString(PR_ImplodeTime(&et)); /* What time is Oct. 7, 1995, 18:29:23 PST? */ et.tm_year = 1995; et.tm_month = 10 - 1; et.tm_mday = 7; et.tm_hour = 18; et.tm_min = 29; et.tm_sec = 23; et.tm_params.tp_gmt_offset = -8 * 3600; /* PST */ et.tm_params.tp_dst_offset = 0; PR_NormalizeTime(&et, PR_LocalTimeParameters); if (debug_mode) printf("Oct 7 18:29:23 PST 1995 is "); PrintExplodedTime(&et); if (debug_mode) printf(".\n"); testParseTimeString(PR_ImplodeTime(&et)); if (debug_mode) printf("Please examine the results\n"); } /* ************************************************************** ** ** Testing range of years ** ************************************************************** */ { PRExplodedTime et1, et2; PRTime ttt; PRTime secs; if (debug_mode) { printf("\n"); printf("***************************************\n"); printf("** **\n"); printf("** Testing range of years **\n"); printf("** **\n"); printf("***************************************\n\n"); } /* April 4, 1917 GMT */ et1.tm_usec = 0; et1.tm_sec = 0; et1.tm_min = 0; et1.tm_hour = 0; et1.tm_mday = 4; et1.tm_month = 4 - 1; et1.tm_year = 1917; et1.tm_params = PR_GMTParameters(&et1); PR_NormalizeTime(&et1, PR_LocalTimeParameters); secs = PR_ImplodeTime(&et1); if (LL_GE_ZERO(secs)) { if (debug_mode) printf("ERROR: April 4, 1917 GMT returns a nonnegative second count\n"); failed_already = 1; return 1; } PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2); if (!ExplodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for April 4, 1917 GMT\n"); failed_already=1; return 1; } ttt = PR_ImplodeTime(&et1); testParseTimeString( ttt ); if (debug_mode) printf("Test passed for April 4, 1917\n"); /* July 4, 2050 */ et1.tm_usec = 0; et1.tm_sec = 0; et1.tm_min = 0; et1.tm_hour = 0; et1.tm_mday = 4; et1.tm_month = 7 - 1; et1.tm_year = 2050; et1.tm_params = PR_GMTParameters(&et1); PR_NormalizeTime(&et1, PR_LocalTimeParameters); secs = PR_ImplodeTime(&et1); if (!LL_GE_ZERO(secs)) { if (debug_mode) printf("ERROR: July 4, 2050 GMT returns a negative second count\n"); failed_already = 1; return 1; } PR_ExplodeTime(secs, PR_LocalTimeParameters, &et2); if (!ExplodedTimeIsEqual(&et1, &et2)) { if (debug_mode) printf("ERROR: PR_ImplodeTime and PR_ExplodeTime are not inverse for July 4, 2050 GMT\n"); failed_already=1; return 1; } testParseTimeString(PR_ImplodeTime(&et1)); if (debug_mode) printf("Test passed for July 4, 2050\n"); } /* ************************************************************** ** ** Stress test * ** Go through four years, starting from ** 00:00:00 PST Jan. 1, 2005, incrementing ** every 10 minutes. ** ************************************************************** */ { PRExplodedTime et, et1, et2; PRInt64 usecPer10Min; int day, hour, min; PRTime usecs; int dstInEffect = 0; if (debug_mode) { printf("\n"); printf("*******************************************************\n"); printf("** **\n"); printf("** Stress test Pacific Time **\n"); printf("** Starting from midnight Jan. 1, 2005 PST, **\n"); printf("** going through four years in 10-minute increment **\n"); printf("** **\n"); printf("*******************************************************\n\n"); } LL_I2L(usecPer10Min, 600000000L); /* 00:00:00 PST Jan. 1, 2005 */ et.tm_usec = 0; et.tm_sec = 0; et.tm_min = 0; et.tm_hour = 0; et.tm_mday = 1; et.tm_month = 0; et.tm_year = 2005; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; usecs = PR_ImplodeTime(&et); for (day = 0; day < 4 * 365 + 1; day++) { for (hour = 0; hour < 24; hour++) { for (min = 0; min < 60; min += 10) { LL_ADD(usecs, usecs, usecPer10Min); PR_ExplodeTime(usecs, PR_USPacificTimeParameters, &et1); et2 = et; et2.tm_usec += 600000000L; PR_NormalizeTime(&et2, PR_USPacificTimeParameters); if (!ExplodedTimeIsEqual(&et1, &et2)) { printf("ERROR: componentwise comparison failed\n"); PrintExplodedTime(&et1); printf("\n"); PrintExplodedTime(&et2); printf("\n"); failed_already=1; return 1; } if (LL_NE(usecs, PR_ImplodeTime(&et1))) { printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n"); PrintExplodedTime(&et1); printf("\n"); failed_already=1; return 1; } testParseTimeString(usecs); if (!dstInEffect && et1.tm_params.tp_dst_offset) { dstInEffect = 1; if (debug_mode) { printf("DST changeover from "); PrintExplodedTime(&et); printf(" to "); PrintExplodedTime(&et1); printf(".\n"); } } else if (dstInEffect && !et1.tm_params.tp_dst_offset) { dstInEffect = 0; if (debug_mode) { printf("DST changeover from "); PrintExplodedTime(&et); printf(" to "); PrintExplodedTime(&et1); printf(".\n"); } } et = et1; } } } if (debug_mode) printf("Test passed\n"); } /* Same stress test, but with PR_LocalTimeParameters */ { PRExplodedTime et, et1, et2; PRInt64 usecPer10Min; int day, hour, min; PRTime usecs; int dstInEffect = 0; if (debug_mode) { printf("\n"); printf("*******************************************************\n"); printf("** **\n"); printf("** Stress test Local Time **\n"); printf("** Starting from midnight Jan. 1, 2005 PST, **\n"); printf("** going through four years in 10-minute increment **\n"); printf("** **\n"); printf("*******************************************************\n\n"); } LL_I2L(usecPer10Min, 600000000L); /* 00:00:00 PST Jan. 1, 2005 */ et.tm_usec = 0; et.tm_sec = 0; et.tm_min = 0; et.tm_hour = 0; et.tm_mday = 1; et.tm_month = 0; et.tm_year = 2005; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; usecs = PR_ImplodeTime(&et); for (day = 0; day < 4 * 365 + 1; day++) { for (hour = 0; hour < 24; hour++) { for (min = 0; min < 60; min += 10) { LL_ADD(usecs, usecs, usecPer10Min); PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1); et2 = et; et2.tm_usec += 600000000L; PR_NormalizeTime(&et2, PR_LocalTimeParameters); if (!ExplodedTimeIsEqual(&et1, &et2)) { printf("ERROR: componentwise comparison failed\n"); PrintExplodedTime(&et1); printf("\n"); PrintExplodedTime(&et2); printf("\n"); return 1; } if (LL_NE(usecs, PR_ImplodeTime(&et1))) { printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n"); PrintExplodedTime(&et1); printf("\n"); failed_already=1; return 1; } testParseTimeString(usecs); if (!dstInEffect && et1.tm_params.tp_dst_offset) { dstInEffect = 1; if (debug_mode) { printf("DST changeover from "); PrintExplodedTime(&et); printf(" to "); PrintExplodedTime(&et1); printf(".\n"); } } else if (dstInEffect && !et1.tm_params.tp_dst_offset) { dstInEffect = 0; if (debug_mode) { printf("DST changeover from "); PrintExplodedTime(&et); printf(" to "); PrintExplodedTime(&et1); printf(".\n"); } } et = et1; } } } if (debug_mode) printf("Test passed\n"); } /* Same stress test, but with PR_LocalTimeParameters and going backward */ { PRExplodedTime et, et1, et2; PRInt64 usecPer10Min; int day, hour, min; PRTime usecs; int dstInEffect = 0; if (debug_mode) { printf("\n"); printf("*******************************************************\n"); printf("** **\n"); printf("** Stress test Local Time **\n"); printf("** Starting from midnight Jan. 1, 2009 PST, **\n"); printf("** going back four years in 10-minute increment **\n"); printf("** **\n"); printf("*******************************************************\n\n"); } LL_I2L(usecPer10Min, 600000000L); /* 00:00:00 PST Jan. 1, 2009 */ et.tm_usec = 0; et.tm_sec = 0; et.tm_min = 0; et.tm_hour = 0; et.tm_mday = 1; et.tm_month = 0; et.tm_year = 2009; et.tm_params.tp_gmt_offset = -8 * 3600; et.tm_params.tp_dst_offset = 0; usecs = PR_ImplodeTime(&et); for (day = 0; day < 4 * 365 + 1; day++) { for (hour = 0; hour < 24; hour++) { for (min = 0; min < 60; min += 10) { LL_SUB(usecs, usecs, usecPer10Min); PR_ExplodeTime(usecs, PR_LocalTimeParameters, &et1); et2 = et; et2.tm_usec -= 600000000L; PR_NormalizeTime(&et2, PR_LocalTimeParameters); if (!ExplodedTimeIsEqual(&et1, &et2)) { printf("ERROR: componentwise comparison failed\n"); PrintExplodedTime(&et1); printf("\n"); PrintExplodedTime(&et2); printf("\n"); return 1; } if (LL_NE(usecs, PR_ImplodeTime(&et1))) { printf("ERROR: PR_ExplodeTime and PR_ImplodeTime are not inverse\n"); PrintExplodedTime(&et1); printf("\n"); failed_already=1; return 1; } testParseTimeString(usecs); if (!dstInEffect && et1.tm_params.tp_dst_offset) { dstInEffect = 1; if (debug_mode) { printf("DST changeover from "); PrintExplodedTime(&et); printf(" to "); PrintExplodedTime(&et1); printf(".\n"); } } else if (dstInEffect && !et1.tm_params.tp_dst_offset) { dstInEffect = 0; if (debug_mode) { printf("DST changeover from "); PrintExplodedTime(&et); printf(" to "); PrintExplodedTime(&et1); printf(".\n"); } } et = et1; } } } } if (failed_already) return 1; else return 0; } nspr-4.11/nspr/pr/tests/tmoacc.c0000644000000000000000000002303112623070344014726 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include #include #include "plerror.h" #include "plgetopt.h" #define BASE_PORT 9867 #define DEFAULT_THREADS 1 #define DEFAULT_BACKLOG 10 #define DEFAULT_TIMEOUT 10 #define RANDOM_RANGE 100 /* should be significantly smaller than RAND_MAX */ typedef enum {running, stopped} Status; typedef struct Shared { PRLock *ml; PRCondVar *cv; PRBool passed; PRBool random; PRFileDesc *debug; PRIntervalTime timeout; PRFileDesc *listenSock; Status status; } Shared; static PRIntervalTime Timeout(const Shared *shared) { PRIntervalTime timeout = shared->timeout; if (shared->random) { PRIntervalTime half = timeout >> 1; /* one half of the interval */ PRIntervalTime quarter = half >> 1; /* one quarter of the interval */ /* something in [0..timeout / 2) */ PRUint32 random = (rand() % RANDOM_RANGE) * half / RANDOM_RANGE; timeout = (3 * quarter) + random; /* [75..125)% */ } return timeout; } /* Timeout */ static void Accept(void *arg) { PRStatus rv; char *buffer = NULL; PRNetAddr clientAddr; Shared *shared = (Shared*)arg; PRInt32 recv_length = 0, flags = 0; PRFileDesc *clientSock; PRIntn toread, byte, bytes, loop = 0; struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor; do { PRUint32 checksum = 0; if (NULL != shared->debug) PR_fprintf(shared->debug, "[%d]accepting ... ", loop++); clientSock = PR_Accept( shared->listenSock, &clientAddr, Timeout(shared)); if (clientSock != NULL) { if (NULL != shared->debug) PR_fprintf(shared->debug, "reading length ... "); bytes = PR_Recv( clientSock, &descriptor, sizeof(descriptor), flags, Timeout(shared)); if (sizeof(descriptor) == bytes) { /* and, before doing something stupid ... */ descriptor.length = PR_ntohl(descriptor.length); descriptor.checksum = PR_ntohl(descriptor.checksum); if (NULL != shared->debug) PR_fprintf(shared->debug, "%d bytes ... ", descriptor.length); toread = descriptor.length; if (recv_length < descriptor.length) { if (NULL != buffer) PR_DELETE(buffer); buffer = (char*)PR_MALLOC(descriptor.length); recv_length = descriptor.length; } for (toread = descriptor.length; toread > 0; toread -= bytes) { bytes = PR_Recv( clientSock, &buffer[descriptor.length - toread], toread, flags, Timeout(shared)); if (-1 == bytes) { if (NULL != shared->debug) PR_fprintf(shared->debug, "read data failed..."); bytes = 0; } } } else if (NULL != shared->debug) { PR_fprintf(shared->debug, "read desciptor failed..."); descriptor.length = -1; } if (NULL != shared->debug) PR_fprintf(shared->debug, "closing"); rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH); if ((PR_FAILURE == rv) && (NULL != shared->debug)) { PR_fprintf(shared->debug, " failed"); shared->passed = PR_FALSE; } rv = PR_Close(clientSock); if (PR_FAILURE == rv) if (NULL != shared->debug) { PR_fprintf(shared->debug, " failed"); shared->passed = PR_FALSE; } if (descriptor.length > 0) { for (byte = 0; byte < descriptor.length; ++byte) { PRUint32 overflow = checksum & 0x80000000; checksum = (checksum << 1); if (0x00000000 != overflow) checksum += 1; checksum += buffer[byte]; } if ((descriptor.checksum != checksum) && (NULL != shared->debug)) { PR_fprintf(shared->debug, " ... data mismatch"); shared->passed = PR_FALSE; } } else if (0 == descriptor.length) { PR_Lock(shared->ml); shared->status = stopped; PR_NotifyCondVar(shared->cv); PR_Unlock(shared->ml); } if (NULL != shared->debug) PR_fprintf(shared->debug, "\n"); } else { if (PR_PENDING_INTERRUPT_ERROR != PR_GetError()) { if (NULL != shared->debug) PL_PrintError("Accept"); shared->passed = PR_FALSE; } } } while (running == shared->status); if (NULL != buffer) PR_DELETE(buffer); } /* Accept */ PRIntn Tmoacc(PRIntn argc, char **argv) { PRStatus rv; PRIntn exitStatus; PRIntn index; Shared *shared; PLOptStatus os; PRThread **thread; PRNetAddr listenAddr; PRSocketOptionData sockOpt; PRIntn timeout = DEFAULT_TIMEOUT; PRIntn threads = DEFAULT_THREADS; PRIntn backlog = DEFAULT_BACKLOG; PRThreadScope thread_scope = PR_LOCAL_THREAD; PLOptState *opt = PL_CreateOptState(argc, argv, "dGb:t:T:R"); shared = PR_NEWZAP(Shared); shared->debug = NULL; shared->passed = PR_TRUE; shared->random = PR_TRUE; shared->status = running; shared->ml = PR_NewLock(); shared->cv = PR_NewCondVar(shared->ml); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ shared->debug = PR_GetSpecialFD(PR_StandardError); break; case 'G': /* use global threads */ thread_scope = PR_GLOBAL_THREAD; break; case 'b': /* size of listen backlog */ backlog = atoi(opt->value); break; case 't': /* number of threads doing accept */ threads = atoi(opt->value); break; case 'T': /* timeout used for network operations */ timeout = atoi(opt->value); break; case 'R': /* randomize the timeout values */ shared->random = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); if (0 == threads) threads = DEFAULT_THREADS; if (0 == backlog) backlog = DEFAULT_BACKLOG; if (0 == timeout) timeout = DEFAULT_TIMEOUT; PR_STDIO_INIT(); memset(&listenAddr, 0, sizeof(listenAddr)); rv = PR_InitializeNetAddr(PR_IpAddrAny, BASE_PORT, &listenAddr); PR_ASSERT(PR_SUCCESS == rv); shared->timeout = PR_SecondsToInterval(timeout); /* First bind to the socket */ shared->listenSock = PR_NewTCPSocket(); if (shared->listenSock) { sockOpt.option = PR_SockOpt_Reuseaddr; sockOpt.value.reuse_addr = PR_TRUE; rv = PR_SetSocketOption(shared->listenSock, &sockOpt); PR_ASSERT(PR_SUCCESS == rv); rv = PR_Bind(shared->listenSock, &listenAddr); if (rv != PR_FAILURE) { rv = PR_Listen(shared->listenSock, threads + backlog); if (PR_SUCCESS == rv) { thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*)); for (index = 0; index < threads; ++index) { thread[index] = PR_CreateThread( PR_USER_THREAD, Accept, shared, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); PR_ASSERT(NULL != thread[index]); } PR_Lock(shared->ml); while (shared->status == running) PR_WaitCondVar(shared->cv, PR_INTERVAL_NO_TIMEOUT); PR_Unlock(shared->ml); for (index = 0; index < threads; ++index) { rv = PR_Interrupt(thread[index]); PR_ASSERT(PR_SUCCESS== rv); rv = PR_JoinThread(thread[index]); PR_ASSERT(PR_SUCCESS== rv); } PR_DELETE(thread); } else { if (shared->debug) PL_PrintError("Listen"); shared->passed = PR_FALSE; } } else { if (shared->debug) PL_PrintError("Bind"); shared->passed = PR_FALSE; } PR_Close(shared->listenSock); } else { if (shared->debug) PL_PrintError("Create"); shared->passed = PR_FALSE; } PR_DestroyCondVar(shared->cv); PR_DestroyLock(shared->ml); PR_fprintf( PR_GetSpecialFD(PR_StandardError), "%s\n", ((shared->passed) ? "PASSED" : "FAILED")); exitStatus = (shared->passed) ? 0 : 1; PR_DELETE(shared); return exitStatus; } int main(int argc, char **argv) { return (PR_VersionCheck(PR_VERSION)) ? PR_Initialize(Tmoacc, argc, argv, 4) : -1; } /* main */ /* tmoacc */ nspr-4.11/nspr/pr/tests/tmocon.c0000644000000000000000000003044612623070344014767 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*********************************************************************** ** ** Name: tmocon.c ** ** Description: test client socket connection. ** ** Modification History: ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. ** The debug mode will print all of the printfs associated with this test. ** The regress mode will be the default mode. Since the regress tool limits ** the output to a one line status:PASS or FAIL,all of the printf statements ** have been handled with an if (debug_mode) statement. ***********************************************************************/ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "nspr.h" #include "pprio.h" #include "plerror.h" #include "plgetopt.h" #include #include #include /* for getcwd */ #if defined(XP_UNIX) || defined (XP_OS2) || defined(XP_BEOS) #include #elif defined(XP_PC) #include #endif #ifdef WINCE #include char *getcwd(char *buf, size_t size) { wchar_t wpath[MAX_PATH]; _wgetcwd(wpath, MAX_PATH); WideCharToMultiByte(CP_ACP, 0, wpath, -1, buf, size, 0, 0); } #endif #define BASE_PORT 9867 #define DEFAULT_DALLY 1 #define DEFAULT_THREADS 1 #define DEFAULT_TIMEOUT 10 #define DEFAULT_MESSAGES 100 #define DEFAULT_MESSAGESIZE 100 static PRFileDesc *debug_out = NULL; typedef struct Shared { PRBool random; PRBool failed; PRBool intermittant; PRIntn debug; PRInt32 messages; PRIntervalTime dally; PRIntervalTime timeout; PRInt32 message_length; PRNetAddr serverAddress; } Shared; static PRIntervalTime Timeout(const Shared *shared) { PRIntervalTime timeout = shared->timeout; if (shared->random) { PRIntervalTime quarter = timeout >> 2; /* one quarter of the interval */ PRUint32 random = rand() % quarter; /* something in[0..timeout / 4) */ timeout = (((3 * quarter) + random) >> 2) + quarter; /* [75..125)% */ } return timeout; } /* Timeout */ static void CauseTimeout(const Shared *shared) { if (shared->intermittant) PR_Sleep(Timeout(shared)); } /* CauseTimeout */ static PRStatus MakeReceiver(Shared *shared) { PRStatus rv = PR_FAILURE; if (PR_IsNetAddrType(&shared->serverAddress, PR_IpAddrLoopback)) { char *argv[3]; char path[1024 + sizeof("/tmoacc")]; getcwd(path, sizeof(path)); (void)strcat(path, "/tmoacc"); #ifdef XP_PC (void)strcat(path, ".exe"); #endif argv[0] = path; if (shared->debug > 0) { argv[1] = "-d"; argv[2] = NULL; } else argv[1] = NULL; if (shared->debug > 1) PR_fprintf(debug_out, " creating accept process %s ...", path); fflush(stdout); rv = PR_CreateProcessDetached(path, argv, NULL, NULL); if (PR_SUCCESS == rv) { if (shared->debug > 1) PR_fprintf(debug_out, " wait 5 seconds"); if (shared->debug > 1) PR_fprintf(debug_out, " before connecting to accept process ..."); fflush(stdout); PR_Sleep(PR_SecondsToInterval(5)); return rv; } shared->failed = PR_TRUE; if (shared->debug > 0) PL_FPrintError(debug_out, "PR_CreateProcessDetached failed"); } return rv; } /* MakeReceiver */ static void Connect(void *arg) { PRStatus rv; char *buffer = NULL; PRFileDesc *clientSock; Shared *shared = (Shared*)arg; PRInt32 loop, bytes, flags = 0; struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor; debug_out = (0 == shared->debug) ? NULL : PR_GetSpecialFD(PR_StandardError); buffer = (char*)PR_MALLOC(shared->message_length); for (bytes = 0; bytes < shared->message_length; ++bytes) buffer[bytes] = (char)bytes; descriptor.checksum = 0; for (bytes = 0; bytes < shared->message_length; ++bytes) { PRUint32 overflow = descriptor.checksum & 0x80000000; descriptor.checksum = (descriptor.checksum << 1); if (0x00000000 != overflow) descriptor.checksum += 1; descriptor.checksum += buffer[bytes]; } descriptor.checksum = PR_htonl(descriptor.checksum); for (loop = 0; loop < shared->messages; ++loop) { if (shared->debug > 1) PR_fprintf(debug_out, "[%d]socket ... ", loop); clientSock = PR_NewTCPSocket(); if (clientSock) { /* * We need to slow down the rate of generating connect requests, * otherwise the listen backlog queue on the accept side may * become full and we will get connection refused or timeout * error. */ PR_Sleep(shared->dally); if (shared->debug > 1) { char buf[128]; PR_NetAddrToString(&shared->serverAddress, buf, sizeof(buf)); PR_fprintf(debug_out, "connecting to %s ... ", buf); } rv = PR_Connect( clientSock, &shared->serverAddress, Timeout(shared)); if (PR_SUCCESS == rv) { PRInt32 descriptor_length = (loop < (shared->messages - 1)) ? shared->message_length : 0; descriptor.length = PR_htonl(descriptor_length); if (shared->debug > 1) PR_fprintf( debug_out, "sending %d bytes ... ", descriptor_length); CauseTimeout(shared); /* might cause server to timeout */ bytes = PR_Send( clientSock, &descriptor, sizeof(descriptor), flags, Timeout(shared)); if (bytes != sizeof(descriptor)) { shared->failed = PR_TRUE; if (shared->debug > 0) PL_FPrintError(debug_out, "PR_Send failed"); } if (0 != descriptor_length) { CauseTimeout(shared); bytes = PR_Send( clientSock, buffer, descriptor_length, flags, Timeout(shared)); if (bytes != descriptor_length) { shared->failed = PR_TRUE; if (shared->debug > 0) PL_FPrintError(debug_out, "PR_Send failed"); } } if (shared->debug > 1) PR_fprintf(debug_out, "closing ... "); rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH); rv = PR_Close(clientSock); if (shared->debug > 1) { if (PR_SUCCESS == rv) PR_fprintf(debug_out, "\n"); else PL_FPrintError(debug_out, "shutdown failed"); } } else { if (shared->debug > 1) PL_FPrintError(debug_out, "connect failed"); PR_Close(clientSock); if ((loop == 0) && (PR_GetError() == PR_CONNECT_REFUSED_ERROR)) { if (MakeReceiver(shared) == PR_FAILURE) break; } else { if (shared->debug > 1) PR_fprintf(debug_out, " exiting\n"); break; } } } else { shared->failed = PR_TRUE; if (shared->debug > 0) PL_FPrintError(debug_out, "create socket"); break; } } PR_DELETE(buffer); } /* Connect */ int Tmocon(int argc, char **argv) { /* * USAGE * -d turn on debugging output (default = off) * -v turn on verbose output (default = off) * -h dns name of host serving the connection (default = self) * -i dally intermittantly to cause timeouts (default = off) * -m number of messages to send (default = 100) * -s size of each message (default = 100) * -t number of threads sending (default = 1) * -G use global threads (default = local) * -T timeout on I/O operations (seconds) (default = 10) * -D dally between connect requests (seconds)(default = 0) * -R randomize the dally types around 'T' (default = no) */ PRStatus rv; int exitStatus; PLOptStatus os; Shared *shared = NULL; PRThread **thread = NULL; PRIntn index, threads = DEFAULT_THREADS; PRThreadScope thread_scope = PR_LOCAL_THREAD; PRInt32 dally = DEFAULT_DALLY, timeout = DEFAULT_TIMEOUT; PLOptState *opt = PL_CreateOptState(argc, argv, "divGRh:m:s:t:T:D:"); shared = PR_NEWZAP(Shared); shared->debug = 0; shared->failed = PR_FALSE; shared->random = PR_FALSE; shared->messages = DEFAULT_MESSAGES; shared->message_length = DEFAULT_MESSAGESIZE; PR_STDIO_INIT(); memset(&shared->serverAddress, 0, sizeof(shared->serverAddress)); rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &shared->serverAddress); PR_ASSERT(PR_SUCCESS == rv); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': if (0 == shared->debug) shared->debug = 1; break; case 'v': if (0 == shared->debug) shared->debug = 2; break; case 'i': shared->intermittant = PR_TRUE; break; case 'R': shared->random = PR_TRUE; break; case 'G': thread_scope = PR_GLOBAL_THREAD; break; case 'h': /* the value for backlock */ { PRIntn es = 0; PRHostEnt host; char buffer[1024]; (void)PR_GetHostByName( opt->value, buffer, sizeof(buffer), &host); es = PR_EnumerateHostEnt( es, &host, BASE_PORT, &shared->serverAddress); PR_ASSERT(es > 0); } break; case 'm': /* number of messages to send */ shared->messages = atoi(opt->value); break; case 't': /* number of threads sending */ threads = atoi(opt->value); break; case 'D': /* dally time between transmissions */ dally = atoi(opt->value); break; case 'T': /* timeout on I/O operations */ timeout = atoi(opt->value); break; case 's': /* total size of each message */ shared->message_length = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); if (0 == timeout) timeout = DEFAULT_TIMEOUT; if (0 == threads) threads = DEFAULT_THREADS; if (0 == shared->messages) shared->messages = DEFAULT_MESSAGES; if (0 == shared->message_length) shared->message_length = DEFAULT_MESSAGESIZE; shared->dally = PR_SecondsToInterval(dally); shared->timeout = PR_SecondsToInterval(timeout); thread = (PRThread**)PR_CALLOC(threads * sizeof(PRThread*)); for (index = 0; index < threads; ++index) thread[index] = PR_CreateThread( PR_USER_THREAD, Connect, shared, PR_PRIORITY_NORMAL, thread_scope, PR_JOINABLE_THREAD, 0); for (index = 0; index < threads; ++index) rv = PR_JoinThread(thread[index]); PR_DELETE(thread); PR_fprintf( PR_GetSpecialFD(PR_StandardError), "%s\n", ((shared->failed) ? "FAILED" : "PASSED")); exitStatus = (shared->failed) ? 1 : 0; PR_DELETE(shared); return exitStatus; } int main(int argc, char **argv) { return (PR_VersionCheck(PR_VERSION)) ? PR_Initialize(Tmocon, argc, argv, 4) : -1; } /* main */ /* tmocon.c */ nspr-4.11/nspr/pr/tests/tpd.c0000644000000000000000000001677012623070344014263 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: tpd.c ** Description: Exercising the thread private data bailywick. */ #include "prmem.h" #include "prinit.h" #include "prlog.h" #include "prprf.h" #include "prthread.h" #include "prtypes.h" #include "private/pprio.h" #include "plgetopt.h" static PRUintn key[128]; static PRIntn debug = 0; static PRBool failed = PR_FALSE; static PRBool should = PR_TRUE; static PRBool did = PR_TRUE; static PRFileDesc *fout = NULL; static void PrintProgress(PRIntn line) { failed = failed || (should && !did); failed = failed || (!should && did); if (debug > 0) { #if defined(WIN16) printf( "@ line %d destructor should%s have been called and was%s\n", line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT")); #else PR_fprintf( fout, "@ line %d destructor should%s have been called and was%s\n", line, ((should) ? "" : " NOT"), ((did) ? "" : " NOT")); #endif } } /* PrintProgress */ static void MyAssert(const char *expr, const char *file, PRIntn line) { if (debug > 0) (void)PR_fprintf(fout, "'%s' in file: %s: %d\n", expr, file, line); } /* MyAssert */ #define MY_ASSERT(_expr) \ ((_expr)?((void)0):MyAssert(# _expr,__FILE__,__LINE__)) static void PR_CALLBACK Destructor(void *data) { MY_ASSERT(NULL != data); if (should) did = PR_TRUE; else failed = PR_TRUE; /* * We don't actually free the storage since it's actually allocated * on the stack. Normally, this would not be the case and this is * the opportunity to free whatever. PR_Free(data); */ } /* Destructor */ static void PR_CALLBACK Thread(void *null) { void *pd; PRStatus rv; PRUintn keys; char *key_string[] = { "Key #0", "Key #1", "Key #2", "Key #3", "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"}; did = should = PR_FALSE; for (keys = 0; keys < 8; ++keys) { pd = PR_GetThreadPrivate(key[keys]); MY_ASSERT(NULL == pd); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 4; keys < 8; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_FAILURE == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = PR_SetThreadPrivate(key[keys], "EXTENSION"); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 8; keys < 127; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } /* put in keys and leave them there for thread exit */ did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; } /* Thread */ static PRIntn PR_CALLBACK Tpd(PRIntn argc, char **argv) { void *pd; PRStatus rv; PRUintn keys; PRThread *thread; char *key_string[] = { "Key #0", "Key #1", "Key #2", "Key #3", "Bogus #5", "Bogus #6", "Bogus #7", "Bogus #8"}; fout = PR_STDOUT; did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = PR_NewThreadPrivateIndex(&key[keys], Destructor); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 8; ++keys) { pd = PR_GetThreadPrivate(key[keys]); MY_ASSERT(NULL == pd); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); for (keys = 4; keys < 8; ++keys) key[keys] = 4096; /* set to invalid value */ did = should = PR_FALSE; for (keys = 4; keys < 8; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_FAILURE == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], key_string[keys]); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 0; keys < 4; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = PR_NewThreadPrivateIndex(&key[keys], Destructor); MY_ASSERT(PR_SUCCESS == rv); rv = PR_SetThreadPrivate(key[keys], "EXTENSION"); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = PR_FALSE; should = PR_TRUE; for (keys = 8; keys < 127; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } PrintProgress(__LINE__); did = should = PR_FALSE; for (keys = 8; keys < 127; ++keys) { rv = PR_SetThreadPrivate(key[keys], NULL); MY_ASSERT(PR_SUCCESS == rv); } thread = PR_CreateThread( PR_USER_THREAD, Thread, NULL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); (void)PR_JoinThread(thread); PrintProgress(__LINE__); #if defined(WIN16) printf( "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED")); #else (void)PR_fprintf( fout, "%s\n",((PR_TRUE == failed) ? "FAILED" : "PASSED")); #endif return 0; } /* Tpd */ int main(int argc, char **argv) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dl:r:"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); PR_STDIO_INIT(); return PR_Initialize(Tpd, argc, argv, 0); } /* main */ /* tpd.c */ nspr-4.11/nspr/pr/tests/udpsrv.c0000644000000000000000000003716312623070344015016 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /******************************************************************* ** udpsrc.c -- Test basic function of UDP server ** ** udpsrv operates on the same machine with program udpclt. ** udpsrv is the server side of a udp sockets application. ** udpclt is the client side of a udp sockets application. ** ** The test is designed to assist developers in porting/debugging ** the UDP socket functions of NSPR. ** ** This test is not a stress test. ** ** main() starts two threads: UDP_Server() and UDP_Client(); ** main() uses PR_JoinThread() to wait for the threads to complete. ** ** UDP_Server() does repeated recvfrom()s from a socket. ** He detects an EOF condition set by UDP_Client(). For each ** packet received by UDP_Server(), he checks its content for ** expected content, then sends the packet back to UDP_Client(). ** ** UDP_Client() sends packets to UDP_Server() using sendto() ** he recieves packets back from the server via recvfrom(). ** After he sends enough packets containing UDP_AMOUNT_TO_WRITE ** bytes of data, he sends an EOF message. ** ** The test issues a pass/fail message at end. ** ** Notes: ** The variable "_debug_on" can be set to 1 to cause diagnostic ** messages related to client/server synchronization. Useful when ** the test hangs. ** ** Error messages are written to stdout. ** ******************************************************************** */ /* --- include files --- */ #include "nspr.h" #include "prpriv.h" #include "plgetopt.h" #include "prttools.h" #include #include #include #include #ifdef XP_PC #define mode_t int #endif #define UDP_BUF_SIZE 4096 #define UDP_DGRAM_SIZE 128 #define UDP_AMOUNT_TO_WRITE (PRInt32)((UDP_DGRAM_SIZE * 1000l) +1) #define NUM_UDP_CLIENTS 1 #define NUM_UDP_DATAGRAMS_PER_CLIENT 5 #define UDP_SERVER_PORT 9050 #define UDP_CLIENT_PORT 9053 #define MY_INADDR PR_INADDR_ANY #define PEER_INADDR PR_INADDR_LOOPBACK #define UDP_TIMEOUT 400000 /* #define UDP_TIMEOUT PR_INTERVAL_NO_TIMEOUT */ /* --- static data --- */ static PRIntn _debug_on = 0; static PRBool passed = PR_TRUE; static PRUint32 cltBytesRead = 0; static PRUint32 srvBytesRead = 0; static PRFileDesc *output = NULL; /* --- static function declarations --- */ #define DPRINTF(arg) if (_debug_on) PR_fprintf(output, arg) /******************************************************************* ** ListNetAddr() -- Display the Net Address on stdout ** ** Description: displays the component parts of a PRNetAddr struct ** ** Arguments: address of PRNetAddr structure to display ** ** Returns: void ** ** Notes: ** ******************************************************************** */ void ListNetAddr( char *msg, PRNetAddr *na ) { char mbuf[256]; sprintf( mbuf, "ListNetAddr: %s family: %d, port: %d, ip: %8.8X\n", msg, na->inet.family, PR_ntohs( na->inet.port), PR_ntohl(na->inet.ip) ); #if 0 DPRINTF( mbuf ); #endif } /* --- end ListNetAddr() --- */ /******************************************************************** ** UDP_Server() -- Test a UDP server application ** ** Description: The Server side of a UDP Client/Server application. ** ** Arguments: none ** ** Returns: void ** ** Notes: ** ** ******************************************************************** */ static void PR_CALLBACK UDP_Server( void *arg ) { static char svrBuf[UDP_BUF_SIZE]; PRFileDesc *svrSock; PRInt32 rv; PRNetAddr netaddr; PRBool bound = PR_FALSE; PRBool endOfInput = PR_FALSE; PRInt32 numBytes = UDP_DGRAM_SIZE; DPRINTF("udpsrv: UDP_Server(): starting\n" ); /* --- Create the socket --- */ DPRINTF("udpsrv: UDP_Server(): Creating UDP Socket\n" ); svrSock = PR_NewUDPSocket(); if ( svrSock == NULL ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): PR_NewUDPSocket() returned NULL\n" ); return; } /* --- Initialize the sockaddr_in structure --- */ memset( &netaddr, 0, sizeof( netaddr )); netaddr.inet.family = PR_AF_INET; netaddr.inet.port = PR_htons( UDP_SERVER_PORT ); netaddr.inet.ip = PR_htonl( MY_INADDR ); /* --- Bind the socket --- */ while ( !bound ) { DPRINTF("udpsrv: UDP_Server(): Binding socket\n" ); rv = PR_Bind( svrSock, &netaddr ); if ( rv < 0 ) { if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR ) { if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \ PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n"); PR_Sleep( PR_MillisecondsToInterval( 2000 )); continue; } else { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): \ PR_Bind(): failed: %ld with error: %ld\n", rv, PR_GetError() ); PR_Close( svrSock ); return; } } else bound = PR_TRUE; } ListNetAddr( "UDP_Server: after bind", &netaddr ); /* --- Recv the socket --- */ while( !endOfInput ) { DPRINTF("udpsrv: UDP_Server(): RecvFrom() socket\n" ); rv = PR_RecvFrom( svrSock, svrBuf, numBytes, 0, &netaddr, UDP_TIMEOUT ); if ( rv == -1 ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): PR_RecvFrom(): failed with error: %ld\n", PR_GetError() ); PR_Close( svrSock ); return; } ListNetAddr( "UDP_Server after RecvFrom", &netaddr ); srvBytesRead += rv; if ( svrBuf[0] == 'E' ) { DPRINTF("udpsrv: UDP_Server(): EOF on input detected\n" ); endOfInput = PR_TRUE; } /* --- Send the socket --- */ DPRINTF("udpsrv: UDP_Server(): SendTo(): socket\n" ); rv = PR_SendTo( svrSock, svrBuf, rv, 0, &netaddr, PR_INTERVAL_NO_TIMEOUT ); if ( rv == -1 ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): PR_SendTo(): failed with error: %ld\n", PR_GetError() ); PR_Close( svrSock ); return; } ListNetAddr( "UDP_Server after SendTo", &netaddr ); } /* --- Close the socket --- */ DPRINTF("udpsrv: UDP_Server(): Closing socket\n" ); rv = PR_Close( svrSock ); if ( rv != PR_SUCCESS ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Server(): PR_Close(): failed to close socket\n" ); return; } DPRINTF("udpsrv: UDP_Server(): Normal end\n" ); } /* --- end UDP_Server() --- */ static char cltBuf[UDP_BUF_SIZE]; static char cltBufin[UDP_BUF_SIZE]; /******************************************************************** ** UDP_Client() -- Test a UDP client application ** ** Description: ** ** Arguments: ** ** ** Returns: ** 0 -- Successful execution ** 1 -- Test failed. ** ** Notes: ** ** ******************************************************************** */ static void PR_CALLBACK UDP_Client( void *arg ) { PRFileDesc *cltSock; PRInt32 rv; PRBool bound = PR_FALSE; PRNetAddr netaddr; PRNetAddr netaddrx; PRBool endOfInput = PR_FALSE; PRInt32 numBytes = UDP_DGRAM_SIZE; PRInt32 writeThisMany = UDP_AMOUNT_TO_WRITE; int i; DPRINTF("udpsrv: UDP_Client(): starting\n" ); /* --- Create the socket --- */ cltSock = PR_NewUDPSocket(); if ( cltSock == NULL ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): PR_NewUDPSocket() returned NULL\n" ); return; } /* --- Initialize the sockaddr_in structure --- */ memset( &netaddr, 0, sizeof( netaddr )); netaddr.inet.family = PR_AF_INET; netaddr.inet.ip = PR_htonl( MY_INADDR ); netaddr.inet.port = PR_htons( UDP_CLIENT_PORT ); /* --- Initialize the write buffer --- */ for ( i = 0; i < UDP_BUF_SIZE ; i++ ) cltBuf[i] = i; /* --- Bind the socket --- */ while ( !bound ) { DPRINTF("udpsrv: UDP_Client(): Binding socket\n" ); rv = PR_Bind( cltSock, &netaddr ); if ( rv < 0 ) { if ( PR_GetError() == PR_ADDRESS_IN_USE_ERROR ) { if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): PR_Bind(): reports: PR_ADDRESS_IN_USE_ERROR\n"); PR_Sleep( PR_MillisecondsToInterval( 2000 )); continue; } else { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): PR_Bind(): failed: %ld with error: %ld\n", rv, PR_GetError() ); PR_Close( cltSock ); return; } } else bound = PR_TRUE; } ListNetAddr( "UDP_Client after Bind", &netaddr ); /* --- Initialize the sockaddr_in structure --- */ memset( &netaddr, 0, sizeof( netaddr )); netaddr.inet.family = PR_AF_INET; netaddr.inet.ip = PR_htonl( PEER_INADDR ); netaddr.inet.port = PR_htons( UDP_SERVER_PORT ); /* --- send and receive packets until no more data left */ while( !endOfInput ) { /* ** Signal EOF in the data stream on the last packet */ if ( writeThisMany <= UDP_DGRAM_SIZE ) { DPRINTF("udpsrv: UDP_Client(): Send EOF packet\n" ); cltBuf[0] = 'E'; endOfInput = PR_TRUE; } /* --- SendTo the socket --- */ if ( writeThisMany > UDP_DGRAM_SIZE ) numBytes = UDP_DGRAM_SIZE; else numBytes = writeThisMany; writeThisMany -= numBytes; { char mbuf[256]; sprintf( mbuf, "udpsrv: UDP_Client(): write_this_many: %d, numbytes: %d\n", writeThisMany, numBytes ); DPRINTF( mbuf ); } DPRINTF("udpsrv: UDP_Client(): SendTo(): socket\n" ); rv = PR_SendTo( cltSock, cltBuf, numBytes, 0, &netaddr, UDP_TIMEOUT ); if ( rv == -1 ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): PR_SendTo(): failed with error: %ld\n", PR_GetError() ); PR_Close( cltSock ); return; } ListNetAddr( "UDP_Client after SendTo", &netaddr ); /* --- RecvFrom the socket --- */ memset( cltBufin, 0, UDP_BUF_SIZE ); DPRINTF("udpsrv: UDP_Client(): RecvFrom(): socket\n" ); rv = PR_RecvFrom( cltSock, cltBufin, numBytes, 0, &netaddrx, UDP_TIMEOUT ); if ( rv == -1 ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): PR_RecvFrom(): failed with error: %ld\n", PR_GetError() ); PR_Close( cltSock ); return; } ListNetAddr( "UDP_Client after RecvFrom()", &netaddr ); cltBytesRead += rv; /* --- verify buffer --- */ for ( i = 0; i < rv ; i++ ) { if ( cltBufin[i] != i ) { /* --- special case, end of input --- */ if ( endOfInput && i == 0 && cltBufin[0] == 'E' ) continue; passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): return data mismatch\n" ); PR_Close( cltSock ); return; } } if (debug_mode) PR_fprintf(output, "."); } /* --- Close the socket --- */ DPRINTF("udpsrv: UDP_Server(): Closing socket\n" ); rv = PR_Close( cltSock ); if ( rv != PR_SUCCESS ) { passed = PR_FALSE; if (debug_mode) PR_fprintf(output, "udpsrv: UDP_Client(): PR_Close(): failed to close socket\n" ); return; } DPRINTF("udpsrv: UDP_Client(): ending\n" ); } /* --- end UDP_Client() --- */ /******************************************************************** ** main() -- udpsrv ** ** arguments: ** ** Returns: ** 0 -- Successful execution ** 1 -- Test failed. ** ** Description: ** ** Standard test case setup. ** ** Calls the function UDP_Server() ** ******************************************************************** */ int main(int argc, char **argv) { PRThread *srv, *clt; /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d -v */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dv"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = 1; break; case 'v': /* verbose mode */ _debug_on = 1; break; default: break; } } PL_DestroyOptState(opt); PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); PR_STDIO_INIT(); output = PR_STDERR; PR_SetConcurrency(4); /* ** Create the Server thread */ DPRINTF( "udpsrv: Creating Server Thread\n" ); srv = PR_CreateThread( PR_USER_THREAD, UDP_Server, (void *) 0, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0 ); if ( srv == NULL ) { if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" ); passed = PR_FALSE; } /* ** Give the Server time to Start */ DPRINTF( "udpsrv: Pausing to allow Server to start\n" ); PR_Sleep( PR_MillisecondsToInterval(200) ); /* ** Create the Client thread */ DPRINTF( "udpsrv: Creating Client Thread\n" ); clt = PR_CreateThread( PR_USER_THREAD, UDP_Client, (void *) 0, PR_PRIORITY_LOW, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0 ); if ( clt == NULL ) { if (debug_mode) PR_fprintf(output, "udpsrv: Cannot create server thread\n" ); passed = PR_FALSE; } /* ** */ DPRINTF("udpsrv: Waiting to join Server & Client Threads\n" ); PR_JoinThread( srv ); PR_JoinThread( clt ); /* ** Evaluate test results */ if (debug_mode) PR_fprintf(output, "\n\nudpsrv: main(): cltBytesRead(%ld), \ srvBytesRead(%ld), expected(%ld)\n", cltBytesRead, srvBytesRead, UDP_AMOUNT_TO_WRITE ); if ( cltBytesRead != srvBytesRead || cltBytesRead != UDP_AMOUNT_TO_WRITE ) { passed = PR_FALSE; } PR_Cleanup(); if ( passed ) return 0; else return 1; } /* --- end main() --- */ nspr-4.11/nspr/pr/tests/ut_ttools.h0000644000000000000000000000060012623070344015516 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Used in Regress Tool */ #define NOSTATUS 2 #define PASS 1 #define FAIL 0 PRIntn debug_mode=0; nspr-4.11/nspr/pr/tests/vercheck.c0000644000000000000000000000534612623070344015263 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * File: vercheck.c * * Description: * This test tests the PR_VersionCheck() function. The * compatible_version and incompatible_version arrays * need to be updated for each patch or release. * * Tested areas: library version compatibility check. */ #include "prinit.h" #include #include /* * This release (4.10.10) is backward compatible with the * 4.0.x, 4.1.x, 4.2.x, 4.3.x, 4.4.x, 4.5.x, 4.6.x, 4.7.x, * 4.8.x, 4.9.x, and 4.10.x releases. * It, of course, is compatible with itself. */ static char *compatible_version[] = { "4.0", "4.0.1", "4.1", "4.1.1", "4.1.2", "4.1.3", "4.2", "4.2.1", "4.2.2", "4.3", "4.4", "4.4.1", "4.5", "4.5.1", "4.6", "4.6.1", "4.6.2", "4.6.3", "4.6.4", "4.6.5", "4.6.6", "4.6.7", "4.6.8", "4.7", "4.7.1", "4.7.2", "4.7.3", "4.7.4", "4.7.5", "4.7.6", "4.8", "4.8.1", "4.8.2", "4.8.3", "4.8.4", "4.8.5", "4.8.6", "4.8.7", "4.8.8", "4.8.9", "4.9", "4.9.1", "4.9.2", "4.9.3", "4.9.4", "4.9.5", "4.9.6", "4.10", "4.10.1", "4.10.2", "4.10.3", "4.10.4", "4.10.5", "4.10.6", "4.10.7", "4.10.8", "4.10.9", "4.10.10", PR_VERSION }; /* * This release is not backward compatible with the old * NSPR 2.1 and 3.x releases. * * Any release is incompatible with future releases and * patches. */ static char *incompatible_version[] = { "2.1 19980529", "3.0", "3.0.1", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.5", "3.5.1", "4.11.1", "4.12", "4.12.1", "10.0", "11.1", "12.14.20" }; int main(int argc, char **argv) { int idx; int num_compatible = sizeof(compatible_version) / sizeof(char *); int num_incompatible = sizeof(incompatible_version) / sizeof(char *); printf("NSPR release %s:\n", PR_VERSION); for (idx = 0; idx < num_compatible; idx++) { if (PR_VersionCheck(compatible_version[idx]) == PR_FALSE) { fprintf(stderr, "Should be compatible with version %s\n", compatible_version[idx]); exit(1); } printf("Compatible with version %s\n", compatible_version[idx]); } for (idx = 0; idx < num_incompatible; idx++) { if (PR_VersionCheck(incompatible_version[idx]) == PR_TRUE) { fprintf(stderr, "Should be incompatible with version %s\n", incompatible_version[idx]); exit(1); } printf("Incompatible with version %s\n", incompatible_version[idx]); } printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/version.c0000644000000000000000000000545012623070344015152 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prprf.h" #include "prlink.h" #include "prvrsion.h" #include "plerror.h" #include "plgetopt.h" PR_IMPORT(const PRVersionDescription *) libVersionPoint(void); int main(int argc, char **argv) { PRIntn rv = 1; PLOptStatus os; PRIntn verbosity = 0; PRLibrary *runtime = NULL; const char *library_name = NULL; const PRVersionDescription *version_info; char buffer[100]; PRExplodedTime exploded; PLOptState *opt = PL_CreateOptState(argc, argv, "d"); PRFileDesc *err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* fully qualified library name */ library_name = opt->value; break; case 'd': /* verbodity */ verbosity += 1; break; default: PR_fprintf(err, "Usage: version [-d] {fully qualified library name}\n"); return 2; /* but not a lot else */ } } PL_DestroyOptState(opt); if (NULL != library_name) { runtime = PR_LoadLibrary(library_name); if (NULL == runtime) { PL_FPrintError(err, "PR_LoadLibrary"); return 3; } else { versionEntryPointType versionPoint = (versionEntryPointType) PR_FindSymbol(runtime, "libVersionPoint"); if (NULL == versionPoint) { PL_FPrintError(err, "PR_FindSymbol"); return 4; } version_info = versionPoint(); } } else version_info = libVersionPoint(); /* NSPR's version info */ (void)PR_fprintf(err, "Runtime library version information\n"); PR_ExplodeTime( version_info->buildTime, PR_GMTParameters, &exploded); (void)PR_FormatTime( buffer, sizeof(buffer), "%d %b %Y %H:%M:%S", &exploded); (void)PR_fprintf(err, " Build time: %s GMT\n", buffer); (void)PR_fprintf( err, " Build time: %s\n", version_info->buildTimeString); (void)PR_fprintf( err, " %s V%u.%u.%u (%s%s%s)\n", version_info->description, version_info->vMajor, version_info->vMinor, version_info->vPatch, (version_info->beta ? " beta " : ""), (version_info->debug ? " debug " : ""), (version_info->special ? " special" : "")); (void)PR_fprintf(err, " filename: %s\n", version_info->filename); (void)PR_fprintf(err, " security: %s\n", version_info->security); (void)PR_fprintf(err, " copyright: %s\n", version_info->copyright); (void)PR_fprintf(err, " comment: %s\n", version_info->comment); rv = 0; return rv; } /* version.c */ nspr-4.11/nspr/pr/tests/writev.c0000644000000000000000000001506112623070344015004 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" #include "plgetopt.h" #include #include #ifndef IOV_MAX #define IOV_MAX 16 #endif #define BASE_PORT 9867 int PR_CALLBACK Writev(int argc, char **argv) { PRStatus rv; PRNetAddr serverAddr; PRFileDesc *clientSock, *debug = NULL; char *buffer = NULL; PRIOVec *iov = NULL; PRBool passed = PR_TRUE; PRIntervalTime timein, elapsed, timeout; PRIntervalTime tmo_min = 0x7fffffff, tmo_max = 0, tmo_elapsed = 0; PRInt32 tmo_counted = 0, iov_index, loop, bytes, number_fragments; PRInt32 message_length = 100, fragment_length = 100, messages = 100; struct Descriptor { PRInt32 length; PRUint32 checksum; } descriptor; /* * USAGE * -h dns name of host serving the connection (default = self) * -m number of messages to send (default = 100) * -s size of each message (default = 100) * -f size of each message fragment (default = 100) */ PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dh:m:s:f:"); PR_STDIO_INIT(); rv = PR_InitializeNetAddr(PR_IpAddrLoopback, BASE_PORT, &serverAddr); PR_ASSERT(PR_SUCCESS == rv); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'h': /* the remote host */ { PRIntn es = 0; PRHostEnt host; char buffer[1024]; (void)PR_GetHostByName(opt->value, buffer, sizeof(buffer), &host); es = PR_EnumerateHostEnt(es, &host, BASE_PORT, &serverAddr); PR_ASSERT(es > 0); } break; case 'd': /* debug mode */ debug = PR_GetSpecialFD(PR_StandardError); break; case 'm': /* number of messages to send */ messages = atoi(opt->value); break; case 's': /* total size of each message */ message_length = atoi(opt->value); break; case 'f': /* size of each message fragment */ fragment_length = atoi(opt->value); break; default: break; } } PL_DestroyOptState(opt); buffer = (char*)malloc(message_length); number_fragments = (message_length + fragment_length - 1) / fragment_length + 1; while (IOV_MAX < number_fragments) { fragment_length = message_length / (IOV_MAX - 2); number_fragments = (message_length + fragment_length - 1) / fragment_length + 1; if (NULL != debug) PR_fprintf(debug, "Too many fragments - reset fragment length to %ld\n", fragment_length); } iov = (PRIOVec*)malloc(number_fragments * sizeof(PRIOVec)); iov[0].iov_base = (char*)&descriptor; iov[0].iov_len = sizeof(descriptor); for (iov_index = 1; iov_index < number_fragments; ++iov_index) { iov[iov_index].iov_base = buffer + (iov_index - 1) * fragment_length; iov[iov_index].iov_len = fragment_length; } for (bytes = 0; bytes < message_length; ++bytes) buffer[bytes] = (char)bytes; timeout = PR_SecondsToInterval(1); for (loop = 0; loop < messages; ++loop) { if (NULL != debug) PR_fprintf(debug, "[%d]socket ... ", loop); clientSock = PR_NewTCPSocket(); if (clientSock) { timein = PR_IntervalNow(); if (NULL != debug) PR_fprintf(debug, "connecting ... "); rv = PR_Connect(clientSock, &serverAddr, timeout); if (PR_SUCCESS == rv) { descriptor.checksum = 0; descriptor.length = (loop < (messages - 1)) ? message_length : 0; if (0 == descriptor.length) number_fragments = 1; else for (iov_index = 0; iov_index < descriptor.length; ++iov_index) { PRUint32 overflow = descriptor.checksum & 0x80000000; descriptor.checksum = (descriptor.checksum << 1); if (0x00000000 != overflow) descriptor.checksum += 1; descriptor.checksum += buffer[iov_index]; } if (NULL != debug) PR_fprintf( debug, "sending %d bytes ... ", descriptor.length); /* then, at the last moment ... */ descriptor.length = PR_ntohl(descriptor.length); descriptor.checksum = PR_ntohl(descriptor.checksum); bytes = PR_Writev(clientSock, iov, number_fragments, timeout); if (NULL != debug) PR_fprintf(debug, "closing ... "); rv = PR_Shutdown(clientSock, PR_SHUTDOWN_BOTH); rv = PR_Close(clientSock); if (NULL != debug) PR_fprintf( debug, "%s\n", ((PR_SUCCESS == rv) ? "good" : "bad")); elapsed = PR_IntervalNow() - timein; if (elapsed < tmo_min) tmo_min = elapsed; else if (elapsed > tmo_max) tmo_max = elapsed; tmo_elapsed += elapsed; tmo_counted += 1; } else { if (NULL != debug) PR_fprintf( debug, "failed - retrying (%d, %d)\n", PR_GetError(), PR_GetOSError()); PR_Close(clientSock); } } else if (NULL != debug) { PR_fprintf(debug, "unable to create client socket\n"); passed = PR_FALSE; } } if (NULL != debug) { if (0 == tmo_counted) { PR_fprintf(debug, "No connection made\n"); } else { PR_fprintf( debug, "\nTimings: %d [%d] %d (microseconds)\n", PR_IntervalToMicroseconds(tmo_min), PR_IntervalToMicroseconds(tmo_elapsed / tmo_counted), PR_IntervalToMicroseconds(tmo_max)); } } PR_DELETE(buffer); PR_DELETE(iov); PR_fprintf( PR_GetSpecialFD(PR_StandardError), "%s\n", (passed) ? "PASSED" : "FAILED"); return (passed) ? 0 : 1; } int main(int argc, char **argv) { return (PR_VersionCheck(PR_VERSION)) ? PR_Initialize(Writev, argc, argv, 4) : -1; } /* main */ /* writev.c */ nspr-4.11/nspr/pr/tests/xnotify.c0000644000000000000000000002365212623070344015171 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "plerror.h" #include "plgetopt.h" #include "prinit.h" #include "prprf.h" #include "prio.h" #include "prcvar.h" #include "prmon.h" #include "prcmon.h" #include "prlock.h" #include "prerror.h" #include "prinit.h" #include "prinrval.h" #include "prthread.h" static PRLock *ml = NULL; static PRIntervalTime base; static PRFileDesc *err = NULL; typedef struct CMonShared { PRInt32 o1, o2; } CMonShared; typedef struct MonShared { PRMonitor *o1, *o2; } MonShared; typedef struct LockShared { PRLock *o1, *o2; PRCondVar *cv1, *cv2; } LockShared; static void LogNow(const char *msg, PRStatus rv) { PRIntervalTime now = PR_IntervalNow(); PR_Lock(ml); PR_fprintf(err, "%6ld: %s", (now - base), msg); if (PR_FAILURE == rv) PL_FPrintError(err, " "); else PR_fprintf(err, "\n"); PR_Unlock(ml); } /* LogNow */ static void Help(void) { PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n"); PR_fprintf(err, "\t-d debug mode (default: FALSE)\n"); PR_fprintf(err, "\t-l test with locks (default: FALSE)\n"); PR_fprintf(err, "\t-m tests with monitors (default: FALSE)\n"); PR_fprintf(err, "\t-c tests with cmonitors (default: FALSE)\n"); PR_fprintf(err, "\t-h help\n"); } /* Help */ static void PR_CALLBACK T2CMon(void *arg) { PRStatus rv; CMonShared *shared = (CMonShared*)arg; PR_CEnterMonitor(&shared->o1); LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); else LogNow("T2 wait failed on o1", rv); rv = PR_CNotify(&shared->o1); if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); else LogNow("T2 notify on o1 failed", rv); PR_CExitMonitor(&shared->o1); } /* T2CMon */ static void PR_CALLBACK T3CMon(void *arg) { PRStatus rv; CMonShared *shared = (CMonShared*)arg; PR_CEnterMonitor(&shared->o2); LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); else LogNow("T3 wait failed on o2", rv); rv = PR_CNotify(&shared->o2); LogNow("T3 notify on o2", rv); PR_CExitMonitor(&shared->o2); } /* T3CMon */ static CMonShared sharedCM; static void T1CMon(void) { PRStatus rv; PRThread *t2, *t3; PR_fprintf(err, "\n**********************************\n"); PR_fprintf(err, " CACHED MONITORS\n"); PR_fprintf(err, "**********************************\n"); base = PR_IntervalNow(); PR_CEnterMonitor(&sharedCM.o1); LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3)); if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); else LogNow("T1 wait on o1 failed", rv); PR_CExitMonitor(&sharedCM.o1); LogNow("T1 creating T2", PR_SUCCESS); t2 = PR_CreateThread( PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); LogNow("T1 creating T3", PR_SUCCESS); t3 = PR_CreateThread( PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_CEnterMonitor(&sharedCM.o2); LogNow("T1 waiting forever on o2", PR_SUCCESS); rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT); if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); else LogNow("T1 wait on o2 failed", rv); PR_CExitMonitor(&sharedCM.o2); (void)PR_JoinThread(t2); (void)PR_JoinThread(t3); } /* T1CMon */ static void PR_CALLBACK T2Mon(void *arg) { PRStatus rv; MonShared *shared = (MonShared*)arg; PR_EnterMonitor(shared->o1); LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); rv = PR_Wait(shared->o1, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); else LogNow("T2 wait failed on o1", rv); rv = PR_Notify(shared->o1); if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); else LogNow("T2 notify on o1 failed", rv); PR_ExitMonitor(shared->o1); } /* T2Mon */ static void PR_CALLBACK T3Mon(void *arg) { PRStatus rv; MonShared *shared = (MonShared*)arg; PR_EnterMonitor(shared->o2); LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); rv = PR_Wait(shared->o2, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); else LogNow("T3 wait failed on o2", rv); rv = PR_Notify(shared->o2); LogNow("T3 notify on o2", rv); PR_ExitMonitor(shared->o2); } /* T3Mon */ static MonShared sharedM; static void T1Mon(void) { PRStatus rv; PRThread *t2, *t3; PR_fprintf(err, "\n**********************************\n"); PR_fprintf(err, " MONITORS\n"); PR_fprintf(err, "**********************************\n"); sharedM.o1 = PR_NewMonitor(); sharedM.o2 = PR_NewMonitor(); base = PR_IntervalNow(); PR_EnterMonitor(sharedM.o1); LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3)); if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); else LogNow("T1 wait on o1 failed", rv); PR_ExitMonitor(sharedM.o1); LogNow("T1 creating T2", PR_SUCCESS); t2 = PR_CreateThread( PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); LogNow("T1 creating T3", PR_SUCCESS); t3 = PR_CreateThread( PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_EnterMonitor(sharedM.o2); LogNow("T1 waiting forever on o2", PR_SUCCESS); rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT); if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); else LogNow("T1 wait on o2 failed", rv); PR_ExitMonitor(sharedM.o2); (void)PR_JoinThread(t2); (void)PR_JoinThread(t3); PR_DestroyMonitor(sharedM.o1); PR_DestroyMonitor(sharedM.o2); } /* T1Mon */ static void PR_CALLBACK T2Lock(void *arg) { PRStatus rv; LockShared *shared = (LockShared*)arg; PR_Lock(shared->o1); LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); else LogNow("T2 wait failed on o1", rv); rv = PR_NotifyCondVar(shared->cv1); if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); else LogNow("T2 notify on o1 failed", rv); PR_Unlock(shared->o1); } /* T2Lock */ static void PR_CALLBACK T3Lock(void *arg) { PRStatus rv; LockShared *shared = (LockShared*)arg; PR_Lock(shared->o2); LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5)); if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); else LogNow("T3 wait failed on o2", rv); rv = PR_NotifyCondVar(shared->cv2); LogNow("T3 notify on o2", rv); PR_Unlock(shared->o2); } /* T3Lock */ /* ** Make shared' a static variable for Win16 */ static LockShared sharedL; static void T1Lock(void) { PRStatus rv; PRThread *t2, *t3; sharedL.o1 = PR_NewLock(); sharedL.o2 = PR_NewLock(); sharedL.cv1 = PR_NewCondVar(sharedL.o1); sharedL.cv2 = PR_NewCondVar(sharedL.o2); PR_fprintf(err, "\n**********************************\n"); PR_fprintf(err, " LOCKS\n"); PR_fprintf(err, "**********************************\n"); base = PR_IntervalNow(); PR_Lock(sharedL.o1); LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3)); if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); else LogNow("T1 wait on o1 failed", rv); PR_Unlock(sharedL.o1); LogNow("T1 creating T2", PR_SUCCESS); t2 = PR_CreateThread( PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); LogNow("T1 creating T3", PR_SUCCESS); t3 = PR_CreateThread( PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); PR_Lock(sharedL.o2); LogNow("T1 waiting forever on o2", PR_SUCCESS); rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT); if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); else LogNow("T1 wait on o2 failed", rv); PR_Unlock(sharedL.o2); (void)PR_JoinThread(t2); (void)PR_JoinThread(t3); PR_DestroyLock(sharedL.o1); PR_DestroyLock(sharedL.o2); PR_DestroyCondVar(sharedL.cv1); PR_DestroyCondVar(sharedL.cv2); } /* T1Lock */ static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) { PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc"); PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE; err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode (noop) */ break; case 'l': /* locks */ locks = PR_TRUE; break; case 'm': /* monitors */ monitors = PR_TRUE; break; case 'c': /* cached monitors */ cmonitors = PR_TRUE; break; case 'h': /* needs guidance */ default: Help(); return 2; } } PL_DestroyOptState(opt); ml = PR_NewLock(); if (locks) T1Lock(); if (monitors) T1Mon(); if (cmonitors) T1CMon(); PR_DestroyLock(ml); PR_fprintf(err, "Done!\n"); return 0; } /* main */ int main(int argc, char **argv) { PRIntn rv; PR_STDIO_INIT(); rv = PR_Initialize(RealMain, argc, argv, 0); return rv; } /* main */ /* xnotify.c */ nspr-4.11/nspr/pr/tests/y2k.c0000644000000000000000000010505412623070344014173 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * file: y2k.c * description: Test for y2k compliance for NSPR. * * Sep 1999. lth. Added "Sun" specified dates to the test data. */ /*********************************************************************** ** Includes ***********************************************************************/ /* Used to get the command line option */ #include "plgetopt.h" #include "prinit.h" #include "prtime.h" #include "prprf.h" #include "prlog.h" #include #include #include #define PRINT_DETAILS int failed_already=0; PRBool debug_mode = PR_FALSE; static char *dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???" }; static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" }; PRLogModuleInfo *lm; static void PrintExplodedTime(const PRExplodedTime *et) { PRInt32 totalOffset; PRInt32 hourOffset, minOffset; const char *sign; /* Print day of the week, month, day, hour, minute, and second */ printf("%s %s %2ld %02ld:%02ld:%02ld ", dayOfWeek[et->tm_wday], month[et->tm_month], et->tm_mday, et->tm_hour, et->tm_min, et->tm_sec); /* Print year */ printf("%hd ", et->tm_year); /* Print time zone */ totalOffset = et->tm_params.tp_gmt_offset + et->tm_params.tp_dst_offset; if (totalOffset == 0) { printf("UTC "); } else { sign = "+"; if (totalOffset < 0) { totalOffset = -totalOffset; sign = "-"; } hourOffset = totalOffset / 3600; minOffset = (totalOffset % 3600) / 60; printf("%s%02ld%02ld ", sign, hourOffset, minOffset); } #ifdef PRINT_DETAILS printf("{%d, %d, %d, %d, %d, %d, %d, %d, %d, { %d, %d}}\n",et->tm_usec, et->tm_sec, et->tm_min, et->tm_hour, et->tm_mday, et->tm_month, et->tm_year, et->tm_wday, et->tm_yday, et->tm_params.tp_gmt_offset, et->tm_params.tp_dst_offset); #endif } static int ExplodedTimeIsEqual(const PRExplodedTime *et1, const PRExplodedTime *et2) { if (et1->tm_usec == et2->tm_usec && et1->tm_sec == et2->tm_sec && et1->tm_min == et2->tm_min && et1->tm_hour == et2->tm_hour && et1->tm_mday == et2->tm_mday && et1->tm_month == et2->tm_month && et1->tm_year == et2->tm_year && et1->tm_wday == et2->tm_wday && et1->tm_yday == et2->tm_yday && et1->tm_params.tp_gmt_offset == et2->tm_params.tp_gmt_offset && et1->tm_params.tp_dst_offset == et2->tm_params.tp_dst_offset) { return 1; } else { return 0; } } /* * TEST 1: TestExplodeImplodeTime * Description: * For each given timestamp T (a PRTime value), call PR_ExplodeTime * with GMT, US Pacific, and local time parameters. Compare the * resulting calendar (exploded) time values with the expected * values. * * Note: the expected local time values depend on the local time * zone. The local time values stored in this test are for the US * Pacific Time Zone. If you are running this test in a different * time zone, you need to modify the values in the localt array. * An example is provided below. * * Call PR_ImplodeTime for each of the exploded values and compare * the resulting PRTime values with the original input. * * This test is run for the values of time T corresponding to the * following dates: * - 12/31/99 - before 2000 * - 01/01/00 - after 2000 * - Leap year - Feb 29, 2000 * - March 1st, 2001 (after 1 year) * - March 1st, 2005 (after second leap year) * - 09/09/99 (used by some programs as an end of file marker) * * Call PR_Now, convert to calendar time using PR_ExplodeTime and * manually check the result for correctness. The time should match * the system clock. * * Tested functions: PR_Now, PR_ExplodeTime, PR_ImplodeTime, * PR_LocalTimeParameters, PR_GMTParameters. */ static PRTime prt[] = { LL_INIT(220405, 2133125120), /* 946634400000000 */ LL_INIT(220425, 2633779200), /* 946720800000000 */ LL_INIT(221612, 2107598848), /* 951818400000000 */ LL_INIT(228975, 663398400), /* 983440800000000 */ LL_INIT(258365, 1974568960), /* 1109671200000000 */ LL_INIT(218132, 1393788928), /* 936871200000000 */ /* Sun's dates follow */ LL_INIT( 213062, 4077979648 ), /* Dec 31 1998 10:00:00 */ LL_INIT( 218152, 1894443008 ), /* Sep 10 1999 10:00:00 */ LL_INIT( 221592, 1606944768 ), /* Feb 28 2000 10:00:00 */ LL_INIT( 227768, 688924672 ), /* Dec 31 2000 10:00:00 */ LL_INIT( 227788, 1189578752 ), /* Jan 1 2001 10:00:00 */ }; static PRExplodedTime gmt[] = { { 0, 0, 0, 10, 31, 11, 1999, 5, 364, {0, 0}}, /* 1999/12/31 10:00:00 GMT */ { 0, 0, 0, 10, 1, 0, 2000, 6, 0, {0, 0}}, /* 2000/01/01 10:00:00 GMT */ { 0, 0, 0, 10, 29, 1, 2000, 2, 59, {0, 0}}, /* 2000/02/29 10:00:00 GMT */ { 0, 0, 0, 10, 1, 2, 2001, 4, 59, {0, 0}}, /* 2001/3/1 10:00:00 GMT */ { 0, 0, 0, 10, 1, 2, 2005, 2, 59, {0, 0}}, /* 2005/3/1 10:00:00 GMT */ { 0, 0, 0, 10, 9, 8, 1999, 4, 251, {0, 0}}, /* 1999/9/9 10:00:00 GMT */ /* Sun's dates follow */ { 0, 0, 0, 10, 31, 11, 1998, 4, 364, {0, 0}}, /* 12/31/1998 10:00:00 GMT */ { 0, 0, 0, 10, 10, 8, 1999, 5, 252, {0, 0}}, /* 9/10/1999 10:00:00 GMT */ { 0, 0, 0, 10, 28, 1, 2000, 1, 58, {0, 0}}, /* 2/28/2000 10:00:00 GMT */ { 0, 0, 0, 10, 31, 11, 2000, 0, 365, {0, 0}}, /* 12/31/2000 10:00:00 GMT */ { 0, 0, 0, 10, 1, 0, 2001, 1, 0, {0, 0}} /* 1/1/2001 10:00:00 GMT */ }; static PRExplodedTime uspt[] = { { 0, 0, 0, 2, 31, 11, 1999, 5, 364, {-28800, 0}}, /* 1999/12/31 2:00:00 PST */ { 0, 0, 0, 2, 1, 0, 2000, 6, 0, {-28800, 0}}, /* 2000/01/01 2:00:00 PST */ { 0, 0, 0, 2, 29, 1, 2000, 2, 59, {-28800, 0}}, /* 2000/02/29 2:00:00 PST */ { 0, 0, 0, 2, 1, 2, 2001, 4, 59, {-28800, 0}}, /* 2001/3/1 2:00:00 PST */ { 0, 0, 0, 2, 1, 2, 2005, 2, 59, {-28800, 0}}, /* 2005/3/1 2:00:00 PST */ { 0, 0, 0, 3, 9, 8, 1999, 4, 251, {-28800, 3600}}, /* 1999/9/9 3:00:00 PDT */ /* Sun's dates follow */ { 0, 0, 0, 2, 31, 11, 1998, 4, 364, {-28800, 0}}, /* 12/31/1998 00:00:00 GMT */ { 0, 0, 0, 3, 10, 8, 1999, 5, 252, {-28800, 3600}}, /* 9/10/1999 00:00:00 GMT */ { 0, 0, 0, 2, 28, 1, 2000, 1, 58, {-28800, 0}}, /* 2/28/2000 00:00:00 GMT */ { 0, 0, 0, 2, 31, 11, 2000, 0, 365, {-28800, 0}}, /* 12/31/2000 00:00:00 GMT */ { 0, 0, 0, 2, 1, 0, 2001, 1, 0, {-28800, 0}} /* 1/1/2001 00:00:00 GMT */ }; /* * This test assumes that we are in US Pacific Time Zone. * If you are running this test in a different time zone, * you need to modify the localt array and fill in the * expected results. The localt array for US Eastern Time * Zone is provided as an example. */ static PRExplodedTime localt[] = { { 0, 0, 0, 2, 31, 11, 1999, 5, 364, {-28800, 0}}, /* 1999/12/31 2:00:00 PST */ { 0, 0, 0, 2, 1, 0, 2000, 6, 0, {-28800, 0}}, /* 2000/01/01 2:00:00 PST */ { 0, 0, 0, 2, 29, 1, 2000, 2, 59, {-28800, 0}}, /* 2000/02/29 2:00:00 PST */ { 0, 0, 0, 2, 1, 2, 2001, 4, 59, {-28800, 0}}, /* 2001/3/1 2:00:00 PST */ { 0, 0, 0, 2, 1, 2, 2005, 2, 59, {-28800, 0}}, /* 2005/3/1 2:00:00 PST */ { 0, 0, 0, 3, 9, 8, 1999, 4, 251, {-28800, 3600}}, /* 1999/9/9 3:00:00 PDT */ /* Sun's dates follow */ { 0, 0, 0, 2, 31, 11, 1998, 4, 364, {-28800, 0}}, /* 12/31/1998 00:00:00 GMT */ { 0, 0, 0, 3, 10, 8, 1999, 5, 252, {-28800, 3600}}, /* 9/10/1999 00:00:00 GMT */ { 0, 0, 0, 2, 28, 1, 2000, 1, 58, {-28800, 0}}, /* 2/28/2000 00:00:00 GMT */ { 0, 0, 0, 2, 31, 11, 2000, 0, 365, {-28800, 0}}, /* 12/31/2000 00:00:00 GMT */ { 0, 0, 0, 2, 1, 0, 2001, 1, 0, {-28800, 0}} /* 1/1/2001 00:00:00 GMT */ }; #ifdef US_EASTERN_TIME static PRExplodedTime localt[] = { { 0, 0, 0, 5, 31, 11, 1999, 5, 364, {-18000, 0}}, /* 1999/12/31 2:00:00 EST */ { 0, 0, 0, 5, 1, 0, 2000, 6, 0, {-18000, 0}}, /* 2000/01/01 2:00:00 EST */ { 0, 0, 0, 5, 29, 1, 2000, 2, 59, {-18000, 0}}, /* 2000/02/29 2:00:00 EST */ { 0, 0, 0, 5, 1, 2, 2001, 4, 59, {-18000, 0}}, /* 2001/3/1 2:00:00 EST */ { 0, 0, 0, 5, 1, 2, 2005, 2, 59, {-18000, 0}}, /* 2005/3/1 2:00:00 EST */ { 0, 0, 0, 6, 9, 8, 1999, 4, 251, {-18000, 3600}}, /* 1999/9/9 3:00:00 EDT */ /* Sun's dates follow */ { 0, 0, 0, 5, 31, 11, 1998, 4, 364, {-18000 0}}, /* 12/31/1998 00:00:00 GMT */ { 0, 0, 0, 6, 10, 8, 1999, 5, 252, {-18000 3600}}, /* 9/10/1999 00:00:00 GMT */ { 0, 0, 0, 5, 28, 1, 2000, 1, 58, {-18000 0}}, /* 2/28/2000 00:00:00 GMT */ { 0, 0, 0, 5, 31, 11, 2000, 0, 365, {-18000 0}}, /* 12/31/2000 00:00:00 GMT */ { 0, 0, 0, 5, 1, 0, 2001, 1, 0, {-18000 0}} /* 1/1/2001 00:00:00 GMT */ }; #endif static PRStatus TestExplodeImplodeTime(void) { PRTime prt_tmp; PRTime now; int idx; int array_size = sizeof(prt) / sizeof(PRTime); PRExplodedTime et_tmp; char buf[1024]; for (idx = 0; idx < array_size; idx++) { PR_snprintf(buf, sizeof(buf), "%lld", prt[idx]); if (debug_mode) printf("Time stamp %s\n", buf); PR_ExplodeTime(prt[idx], PR_GMTParameters, &et_tmp); if (!ExplodedTimeIsEqual(&et_tmp, &gmt[idx])) { fprintf(stderr, "GMT not equal\n"); PrintExplodedTime(&et_tmp); PrintExplodedTime(&gmt[idx]); exit(1); } prt_tmp = PR_ImplodeTime(&et_tmp); if (LL_NE(prt_tmp, prt[idx])) { fprintf(stderr, "PRTime not equal\n"); exit(1); } if (debug_mode) { printf("GMT: "); PrintExplodedTime(&et_tmp); printf("\n"); } PR_ExplodeTime(prt[idx], PR_USPacificTimeParameters, &et_tmp); if (!ExplodedTimeIsEqual(&et_tmp, &uspt[idx])) { fprintf(stderr, "US Pacific Time not equal\n"); PrintExplodedTime(&et_tmp); PrintExplodedTime(&uspt[idx]); exit(1); } prt_tmp = PR_ImplodeTime(&et_tmp); if (LL_NE(prt_tmp, prt[idx])) { fprintf(stderr, "PRTime not equal\n"); exit(1); } if (debug_mode) { printf("US Pacific Time: "); PrintExplodedTime(&et_tmp); printf("\n"); } PR_ExplodeTime(prt[idx], PR_LocalTimeParameters, &et_tmp); if (!ExplodedTimeIsEqual(&et_tmp, &localt[idx])) { fprintf(stderr, "not equal\n"); PrintExplodedTime(&et_tmp); PrintExplodedTime(&localt[idx]); exit(1); } prt_tmp = PR_ImplodeTime(&et_tmp); if (LL_NE(prt_tmp, prt[idx])) { fprintf(stderr, "not equal\n"); exit(1); } if (debug_mode) { printf("Local time:"); PrintExplodedTime(&et_tmp); printf("\n\n"); } } now = PR_Now(); PR_ExplodeTime(now, PR_GMTParameters, &et_tmp); printf("Current GMT is "); PrintExplodedTime(&et_tmp); printf("\n"); prt_tmp = PR_ImplodeTime(&et_tmp); if (LL_NE(prt_tmp, now)) { fprintf(stderr, "not equal\n"); exit(1); } PR_ExplodeTime(now, PR_USPacificTimeParameters, &et_tmp); printf("Current US Pacific Time is "); PrintExplodedTime(&et_tmp); printf("\n"); prt_tmp = PR_ImplodeTime(&et_tmp); if (LL_NE(prt_tmp, now)) { fprintf(stderr, "not equal\n"); exit(1); } PR_ExplodeTime(now, PR_LocalTimeParameters, &et_tmp); printf("Current local time is "); PrintExplodedTime(&et_tmp); printf("\n"); prt_tmp = PR_ImplodeTime(&et_tmp); if (LL_NE(prt_tmp, now)) { fprintf(stderr, "not equal\n"); exit(1); } printf("Please verify the results\n\n"); if (debug_mode) printf("Test 1 passed\n"); return PR_SUCCESS; } /* End of Test 1: TestExplodeImplodeTime */ /* * Test 2: Normalize Time */ /* * time increment for addition to PRExplodeTime */ typedef struct time_increment { PRInt32 ti_usec; PRInt32 ti_sec; PRInt32 ti_min; PRInt32 ti_hour; } time_increment_t; /* * Data for testing PR_Normalize * Add the increment to base_time, normalize it to GMT and US Pacific * Time zone. */ typedef struct normalize_test_data { PRExplodedTime base_time; time_increment_t increment; PRExplodedTime expected_gmt_time; PRExplodedTime expected_uspt_time; } normalize_test_data_t; /* * Test data - the base time values cover dates of interest including y2k - 1, * y2k + 1, y2k leap year, y2k leap date + 1year, * y2k leap date + 4 years */ normalize_test_data_t normalize_test_array[] = { /*usec sec min hour mday mo year wday yday {gmtoff, dstoff }*/ /* Fri 12/31/1999 19:32:48 PST */ {{0, 48, 32, 19, 31, 11, 1999, 5, 364, { -28800, 0}}, {0, 0, 30, 20}, {0, 48, 2, 0, 2, 0, 2000, 0, 1, { 0, 0}}, /*Sun Jan 2 00:02:48 UTC 2000*/ {0, 48, 2, 16, 1, 0, 2000, 6, 0, { -28800, 0}},/* Sat Jan 1 16:02:48 PST 2000*/ }, /* Fri 99-12-31 23:59:02 GMT */ {{0, 2, 59, 23, 31, 11, 1999, 5, 364, { 0, 0}}, {0, 0, 45, 0}, {0, 2, 44, 0, 1, 0, 2000, 6, 0, { 0, 0}},/* Sat Jan 1 00:44:02 UTC 2000*/ {0, 2, 44, 16, 31, 11, 1999, 5, 364, { -28800, 0}}/*Fri Dec 31 16:44:02 PST 1999*/ }, /* 99-12-25 12:00:00 GMT */ {{0, 0, 0, 12, 25, 11, 1999, 6, 358, { 0, 0}}, {0, 0, 0, 364 * 24}, {0, 0, 0, 12, 23, 11, 2000, 6, 357, { 0, 0}},/*Sat Dec 23 12:00:00 2000 UTC*/ {0, 0, 0, 4, 23, 11, 2000, 6, 357, { -28800, 0}}/*Sat Dec 23 04:00:00 2000 -0800*/ }, /* 00-01-1 00:00:00 PST */ {{0, 0, 0, 0, 1, 0, 2000, 6, 0, { -28800, 0}}, {0, 0, 0, 48}, {0, 0, 0, 8, 3, 0, 2000, 1, 2, { 0, 0}},/*Mon Jan 3 08:00:00 2000 UTC*/ {0, 0, 0, 0, 3, 0, 2000, 1, 2, { -28800, 0}}/*Mon Jan 3 00:00:00 2000 -0800*/ }, /* 00-01-10 12:00:00 PST */ {{0, 0, 0, 12, 10, 0, 2000, 1, 9, { -28800, 0}}, {0, 0, 0, 364 * 5 * 24}, {0, 0, 0, 20, 3, 0, 2005, 1, 2, { 0, 0}},/*Mon Jan 3 20:00:00 2005 UTC */ {0, 0, 0, 12, 3, 0, 2005, 1, 2, { -28800, 0}}/*Mon Jan 3 12:00:00 2005 -0800*/ }, /* 00-02-28 15:39 GMT */ {{0, 0, 39, 15, 28, 1, 2000, 1, 58, { 0, 0}}, {0, 0, 0, 24}, {0, 0, 39, 15, 29, 1, 2000, 2, 59, { 0, 0}}, /*Tue Feb 29 15:39:00 2000 UTC*/ {0, 0, 39, 7, 29, 1, 2000, 2, 59, { -28800, 0}}/*Tue Feb 29 07:39:00 2000 -0800*/ }, /* 01-03-01 12:00 PST */ {{0, 0, 0, 12, 3, 0, 2001, 3, 2, { -28800, 0}},/*Wed Jan 3 12:00:00 -0800 2001*/ {0, 30, 30,45}, {0, 30, 30, 17, 5, 0, 2001, 5, 4, { 0, 0}}, /*Fri Jan 5 17:30:30 2001 UTC*/ {0, 30, 30, 9, 5, 0, 2001, 5, 4, { -28800, 0}} /*Fri Jan 5 09:30:30 2001 -0800*/ }, /* 2004-04-26 12:00 GMT */ {{0, 0, 0, 20, 3, 0, 2001, 3, 2, { 0, 0}}, {0, 0, 30,0}, {0, 0, 30, 20, 3, 0, 2001, 3, 2, { 0, 0}},/*Wed Jan 3 20:30:00 2001 UTC*/ {0, 0, 30, 12, 3, 0, 2001, 3, 2, { -28800, 0}}/*Wed Jan 3 12:30:00 2001 -0800*/ }, /* 99-09-09 00:00 GMT */ {{0, 0, 0, 0, 9, 8, 1999, 4, 251, { 0, 0}}, {0, 0, 0, 12}, {0, 0, 0, 12, 9, 8, 1999, 4, 251, { 0, 0}},/*Thu Sep 9 12:00:00 1999 UTC*/ {0, 0, 0, 5, 9, 8, 1999, 4, 251, { -28800, 3600}}/*Thu Sep 9 05:00:00 1999 -0700*/ } }; void add_time_increment(PRExplodedTime *et1, time_increment_t *it) { et1->tm_usec += it->ti_usec; et1->tm_sec += it->ti_sec; et1->tm_min += it->ti_min; et1->tm_hour += it->ti_hour; } /* ** TestNormalizeTime() -- Test PR_NormalizeTime() ** For each data item, add the time increment to the base_time and then ** normalize it for GMT and local time zones. This test assumes that ** the local time zone is the Pacific Time Zone. The normalized values ** should match the expected values in the data item. ** */ PRStatus TestNormalizeTime(void) { int idx, count; normalize_test_data_t *itemp; time_increment_t *itp; count = sizeof(normalize_test_array)/sizeof(normalize_test_array[0]); for (idx = 0; idx < count; idx++) { itemp = &normalize_test_array[idx]; if (debug_mode) { printf("%2d. %15s",idx +1,"Base time: "); PrintExplodedTime(&itemp->base_time); printf("\n"); } itp = &itemp->increment; if (debug_mode) { printf("%20s %2d hrs %2d min %3d sec\n","Add",itp->ti_hour, itp->ti_min, itp->ti_sec); } add_time_increment(&itemp->base_time, &itemp->increment); PR_NormalizeTime(&itemp->base_time, PR_LocalTimeParameters); if (debug_mode) { printf("%19s","PST time: "); PrintExplodedTime(&itemp->base_time); printf("\n"); } if (!ExplodedTimeIsEqual(&itemp->base_time, &itemp->expected_uspt_time)) { printf("PR_NormalizeTime failed\n"); if (debug_mode) PrintExplodedTime(&itemp->expected_uspt_time); return PR_FAILURE; } PR_NormalizeTime(&itemp->base_time, PR_GMTParameters); if (debug_mode) { printf("%19s","GMT time: "); PrintExplodedTime(&itemp->base_time); printf("\n"); } if (!ExplodedTimeIsEqual(&itemp->base_time, &itemp->expected_gmt_time)) { printf("PR_NormalizeTime failed\n"); return PR_FAILURE; } } return PR_SUCCESS; } /* ** ParseTest. Structure defining a string time and a matching exploded time ** */ typedef struct ParseTest { char *sDate; /* string to be converted using PR_ParseTimeString() */ PRExplodedTime et; /* expected result of the conversion */ } ParseTest; static ParseTest parseArray[] = { /* |<----- expected result ------------------------------------------->| */ /* "string to test" usec sec min hour day mo year wday julian {gmtoff, dstoff }*/ { "Thursday 1 Jan 1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "1 Jan 1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "1-Jan-1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "01-Jan-1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "January 1, 1970", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "January 1, 1970 00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "January 01, 1970 00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "January 01 1970 00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "January 01 1970 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "01-01-1970", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "01/01/1970", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "01/01/70", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "01/01/70 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "70/01/01 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "70/1/1 00:00:", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "00:00 Thursday, January 1, 1970",{ 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "1-Jan-70 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "70-01-01 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, { "70/01/01 00:00:00", { 000000, 00, 00, 00, 1, 0, 1970, 4, 0, {-28800, 0 }}}, /* 31-Dec-1969 */ { "Wed 31 Dec 1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}}, { "31 Dec 1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}}, { "12/31/69 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}}, { "12/31/1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}}, { "12-31-69 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}}, { "12-31-1969 00:00:00", { 000000, 00, 00, 00, 31, 11, 1969, 3, 364, {-28800, 0 }}}, { "69-12-31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}}, { "69/12/31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2069, 2, 364, {-28800, 0 }}}, /* "Sun". 31-Dec-1998 (?) */ { "Thu 31 Dec 1998 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, { "12/31/98 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, { "12/31/1998 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, { "12-31-98 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, { "12-31-1998 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, { "98-12-31 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, { "98/12/31 00:00:00", { 00000, 00, 00, 00, 31, 11, 1998, 4, 364, {-28800, 0 }}}, /* 09-Sep-1999. Interesting because of its use as an eof marker? */ { "09 Sep 1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "9/9/99 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "9/9/1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "9-9-99 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "9-9-1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "09-09-99 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "09-09-1999 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, { "99-09-09 00:00:00", { 000000, 00, 00, 00, 9, 8, 1999, 4, 251, {-28800, 3600 }}}, /* "Sun". 10-Sep-1999. Because Sun said so. */ { "10 Sep 1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "9/10/99 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "9/10/1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "9-10-99 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "9-10-1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "09-10-99 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "09-10-1999 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, { "99-09-10 00:00:00", { 000000, 00, 00, 00, 10, 8, 1999, 5, 252, {-28800, 3600 }}}, /* 31-Dec-1999 */ { "31 Dec 1999 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, { "12/31/99 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, { "12/31/1999 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, { "12-31-99 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, { "12-31-1999 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, { "99-12-31 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, { "99/12/31 00:00:00", { 000000, 00, 00, 00, 31, 11, 1999, 5, 364, {-28800, 0 }}}, /* 01-Jan-2000 */ { "01 Jan 2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, { "1/1/00 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, { "1/1/2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, { "1-1-00 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, { "1-1-2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, { "01-01-00 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, { "Saturday 01-01-2000 00:00:00", { 000000, 00, 00, 00, 1, 0, 2000, 6, 0, {-28800, 0 }}}, /* "Sun". 28-Feb-2000 */ { "28 Feb 2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, { "2/28/00 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, { "2/28/2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, { "2-28-00 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, { "2-28-2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, { "02-28-00 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, { "02-28-2000 00:00:00", { 000000, 00, 00, 00, 28, 1, 2000, 1, 58, {-28800, 0 }}}, /* 29-Feb-2000 */ { "29 Feb 2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, { "2/29/00 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, { "2/29/2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, { "2-29-00 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, { "2-29-2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, { "02-29-00 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, { "02-29-2000 00:00:00", { 000000, 00, 00, 00, 29, 1, 2000, 2, 59, {-28800, 0 }}}, /* 01-Mar-2000 */ { "01 Mar 2000 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}}, { "3/1/00 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}}, { "3/1/2000 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}}, { "3-1-00 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}}, { "03-01-00 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}}, { "03-01-2000 00:00:00", { 000000, 00, 00, 00, 1, 2, 2000, 3, 60, {-28800, 0 }}}, /* "Sun". 31-Dec-2000 */ { "31 Dec 2000 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, { "12/31/00 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, { "12/31/2000 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, { "12-31-00 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, { "12-31-2000 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, { "00-12-31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, { "00/12/31 00:00:00", { 000000, 00, 00, 00, 31, 11, 2000, 0, 365, {-28800, 0 }}}, /* "Sun". 01-Jan-2001 */ { "01 Jan 2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, { "1/1/01 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, { "1/1/2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, { "1-1-01 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, { "1-1-2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, { "01-01-01 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, { "Saturday 01-01-2001 00:00:00", { 000000, 00, 00, 00, 1, 0, 2001, 1, 0, {-28800, 0 }}}, /* 01-Mar-2001 */ { "01 Mar 2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, { "3/1/01 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, { "3/1/2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, { "3-1-01 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, { "3-1-2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, { "03-01-01 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, { "03-01-2001 00:00:00", { 000000, 00, 00, 00, 1, 2, 2001, 4, 59, {-28800, 0 }}}, /* 29-Feb-2004 */ { "29 Feb 2004 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}}, { "2/29/04 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}}, { "2/29/2004 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}}, { "2-29-04 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}}, { "2-29-2004 00:00:00", { 000000, 00, 00, 00, 29, 1, 2004, 0, 59, {-28800, 0 }}}, /* 01-Mar-2004 */ { "01 Mar 2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, { "3/1/04 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, { "3/1/2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, { "3-1-04 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, { "3-1-2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, { "03-01-04 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, { "03-01-2004 00:00:00", { 000000, 00, 00, 00, 1, 2, 2004, 1, 60, {-28800, 0 }}}, /* 01-Mar-2005 */ { "01 Mar 2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, { "3/1/05 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, { "3/1/2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, { "3-1-05 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, { "3-1-2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, { "03-01-05 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, { "03-01-2005 00:00:00", { 000000, 00, 00, 00, 1, 2, 2005, 2, 59, {-28800, 0 }}}, /* last element. string must be null */ { NULL } }; /* end array of ParseTest */ /* ** TestParseTime() -- Test PR_ParseTimeString() for y2k compliance ** ** TestParseTime() loops thru the array parseArray. For each element in ** the array, he calls PR_ParseTimeString() with sDate as the conversion ** argument. The result (ct) is then converted to a PRExplodedTime structure ** and compared with the exploded time value (parseArray[n].et) in the ** array element; if equal, the element passes the test. ** ** The array parseArray[] contains entries that are interesting to the ** y2k problem. ** ** */ static PRStatus TestParseTime( void ) { ParseTest *ptp = parseArray; PRTime ct; PRExplodedTime cet; char *sp = ptp->sDate; PRStatus rc; PRStatus rv = PR_SUCCESS; while ( sp != NULL) { rc = PR_ParseTimeString( sp, PR_FALSE, &ct ); if ( PR_FAILURE == rc ) { printf("TestParseTime(): PR_ParseTimeString() failed to convert: %s\n", sp ); rv = PR_FAILURE; failed_already = 1; } else { PR_ExplodeTime( ct, PR_LocalTimeParameters , &cet ); if ( !ExplodedTimeIsEqual( &cet, &ptp->et )) { printf("TestParseTime(): Exploded time compare failed: %s\n", sp ); if ( debug_mode ) { PrintExplodedTime( &cet ); printf("\n"); PrintExplodedTime( &ptp->et ); printf("\n"); } rv = PR_FAILURE; failed_already = 1; } } /* point to next element in array, keep going */ ptp++; sp = ptp->sDate; } /* end while() */ return( rv ); } /* end TestParseTime() */ int main(int argc, char** argv) { /* The command line argument: -d is used to determine if the test is being run in debug mode. The regress tool requires only one line output:PASS or FAIL. All of the printfs associated with this test has been handled with a if (debug_mode) test. Usage: test_name -d */ PLOptStatus os; PLOptState *opt; PR_STDIO_INIT(); opt = PL_CreateOptState(argc, argv, "d"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; default: break; } } PL_DestroyOptState(opt); /* main test */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); lm = PR_NewLogModule("test"); if ( PR_FAILURE == TestExplodeImplodeTime()) { PR_LOG( lm, PR_LOG_ERROR, ("TestExplodeImplodeTime() failed")); } else printf("Test 1: Calendar Time Test passed\n"); if ( PR_FAILURE == TestNormalizeTime()) { PR_LOG( lm, PR_LOG_ERROR, ("TestNormalizeTime() failed")); } else printf("Test 2: Normalize Time Test passed\n"); if ( PR_FAILURE == TestParseTime()) { PR_LOG( lm, PR_LOG_ERROR, ("TestParseTime() failed")); } else printf("Test 3: Parse Time Test passed\n"); if (failed_already) return 1; else return 0; } /* end main() y2k.c */ nspr-4.11/nspr/pr/tests/y2ktmo.c0000644000000000000000000004073612623070344014720 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Test: y2ktmo * * Description: * This test tests the interval time facilities in NSPR for Y2K * compliance. All the functions that take a timeout argument * are tested: PR_Sleep, socket I/O (PR_Accept is taken as a * representative), PR_Poll, PR_WaitCondVar, PR_Wait, and * PR_CWait. A thread of each thread scope (local, global, and * global bound) is created to call each of these functions. * The test should be started at the specified number of seconds * (called the lead time) before a Y2K rollover test date. The * timeout values for these threads will span over the rollover * date by at least the specified number of seconds. For * example, if the lead time is 5 seconds, the test should * be started at time (D - 5), where D is a rollover date, and * the threads will time out at or after time (D + 5). The * timeout values for the threads are spaced one second apart. * * When a thread times out, it calls PR_IntervalNow() to verify * that it did wait for the specified time. In addition, it * calls a platform-native function to verify the actual elapsed * time again, to rule out the possibility that PR_IntervalNow() * is broken. We allow the actual elapsed time to deviate from * the specified timeout by a certain tolerance (in milliseconds). */ #include "nspr.h" #include "plgetopt.h" #include #include #include #if defined(XP_UNIX) #include /* for gettimeofday */ #endif #if defined(WIN32) #if defined(WINCE) #include #else #include #include /* for _ftime */ #endif #endif #define DEFAULT_LEAD_TIME_SECS 5 #define DEFAULT_TOLERANCE_MSECS 500 static PRBool debug_mode = PR_FALSE; static PRInt32 lead_time_secs = DEFAULT_LEAD_TIME_SECS; static PRInt32 tolerance_msecs = DEFAULT_TOLERANCE_MSECS; static PRIntervalTime start_time; static PRIntervalTime tolerance; #if defined(XP_UNIX) static struct timeval start_time_tv; #endif #if defined(WIN32) #if defined(WINCE) static DWORD start_time_tick; #else static struct _timeb start_time_tb; #endif #endif static void SleepThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif if (PR_Sleep(timeout) == PR_FAILURE) { fprintf(stderr, "PR_Sleep failed\n"); exit(1); } elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (debug_mode) { fprintf(stderr, "Sleep thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } } static void AcceptThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif PRFileDesc *sock; PRNetAddr addr; PRFileDesc *accepted; sock = PR_NewTCPSocket(); if (sock == NULL) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_ANY); if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } accepted = PR_Accept(sock, NULL, timeout); if (accepted != NULL || PR_GetError() != PR_IO_TIMEOUT_ERROR) { fprintf(stderr, "PR_Accept did not time out\n"); exit(1); } elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (debug_mode) { fprintf(stderr, "Accept thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } } static void PollThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif PRFileDesc *sock; PRNetAddr addr; PRPollDesc pd; PRIntn rv; sock = PR_NewTCPSocket(); if (sock == NULL) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } memset(&addr, 0, sizeof(addr)); addr.inet.family = PR_AF_INET; addr.inet.port = 0; addr.inet.ip = PR_htonl(PR_INADDR_ANY); if (PR_Bind(sock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } if (PR_Listen(sock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } pd.fd = sock; pd.in_flags = PR_POLL_READ; rv = PR_Poll(&pd, 1, timeout); if (rv != 0) { fprintf(stderr, "PR_Poll did not time out\n"); exit(1); } elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (debug_mode) { fprintf(stderr, "Poll thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } } static void WaitCondVarThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif PRLock *ml; PRCondVar *cv; ml = PR_NewLock(); if (ml == NULL) { fprintf(stderr, "PR_NewLock failed\n"); exit(1); } cv = PR_NewCondVar(ml); if (cv == NULL) { fprintf(stderr, "PR_NewCondVar failed\n"); exit(1); } PR_Lock(ml); PR_WaitCondVar(cv, timeout); PR_Unlock(ml); elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif PR_DestroyCondVar(cv); PR_DestroyLock(ml); if (debug_mode) { fprintf(stderr, "wait cond var thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } } static void WaitMonitorThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif PRMonitor *mon; mon = PR_NewMonitor(); if (mon == NULL) { fprintf(stderr, "PR_NewMonitor failed\n"); exit(1); } PR_EnterMonitor(mon); PR_Wait(mon, timeout); PR_ExitMonitor(mon); elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif PR_DestroyMonitor(mon); if (debug_mode) { fprintf(stderr, "wait monitor thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } } static void WaitCMonitorThread(void *arg) { PRIntervalTime timeout = (PRIntervalTime) arg; PRIntervalTime elapsed; #if defined(XP_UNIX) || defined(WIN32) PRInt32 timeout_msecs = PR_IntervalToMilliseconds(timeout); PRInt32 elapsed_msecs; #endif #if defined(XP_UNIX) struct timeval end_time_tv; #endif #if defined(WIN32) && !defined(WINCE) struct _timeb end_time_tb; #endif int dummy; PR_CEnterMonitor(&dummy); PR_CWait(&dummy, timeout); PR_CExitMonitor(&dummy); elapsed = (PRIntervalTime)(PR_IntervalNow() - start_time); if (elapsed + tolerance < timeout || elapsed > timeout + tolerance) { fprintf(stderr, "timeout wrong\n"); exit(1); } #if defined(XP_UNIX) gettimeofday(&end_time_tv, NULL); elapsed_msecs = 1000*(end_time_tv.tv_sec - start_time_tv.tv_sec) + (end_time_tv.tv_usec - start_time_tv.tv_usec)/1000; #endif #if defined(WIN32) #if defined(WINCE) elapsed_msecs = GetTickCount() - start_time_tick; #else _ftime(&end_time_tb); elapsed_msecs = 1000*(end_time_tb.time - start_time_tb.time) + (end_time_tb.millitm - start_time_tb.millitm); #endif #endif #if defined(XP_UNIX) || defined(WIN32) if (elapsed_msecs + tolerance_msecs < timeout_msecs || elapsed_msecs > timeout_msecs + tolerance_msecs) { fprintf(stderr, "timeout wrong\n"); exit(1); } #endif if (debug_mode) { fprintf(stderr, "wait cached monitor thread (scope %d) done\n", PR_GetThreadScope(PR_GetCurrentThread())); } } typedef void (*NSPRThreadFunc)(void*); static NSPRThreadFunc threadFuncs[] = { SleepThread, AcceptThread, PollThread, WaitCondVarThread, WaitMonitorThread, WaitCMonitorThread}; static PRThreadScope threadScopes[] = { PR_LOCAL_THREAD, PR_GLOBAL_THREAD, PR_GLOBAL_BOUND_THREAD}; static void Help(void) { fprintf(stderr, "y2ktmo test program usage:\n"); fprintf(stderr, "\t-d debug mode (FALSE)\n"); fprintf(stderr, "\t-l lead time (%d)\n", DEFAULT_LEAD_TIME_SECS); fprintf(stderr, "\t-t tolerance (%d)\n", DEFAULT_TOLERANCE_MSECS); fprintf(stderr, "\t-h this message\n"); } /* Help */ int main(int argc, char **argv) { PRThread **threads; int num_thread_funcs = sizeof(threadFuncs)/sizeof(NSPRThreadFunc); int num_thread_scopes = sizeof(threadScopes)/sizeof(PRThreadScope); int i, j; int idx; PRInt32 secs; PLOptStatus os; PLOptState *opt = PL_CreateOptState(argc, argv, "dl:t:h"); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 'd': /* debug mode */ debug_mode = PR_TRUE; break; case 'l': /* lead time */ lead_time_secs = atoi(opt->value); break; case 't': /* tolerance */ tolerance_msecs = atoi(opt->value); break; case 'h': default: Help(); return 2; } } PL_DestroyOptState(opt); if (debug_mode) { fprintf(stderr, "lead time: %d secs\n", lead_time_secs); fprintf(stderr, "tolerance: %d msecs\n", tolerance_msecs); } start_time = PR_IntervalNow(); #if defined(XP_UNIX) gettimeofday(&start_time_tv, NULL); #endif #if defined(WIN32) #ifdef WINCE start_time_tick = GetTickCount(); #else _ftime(&start_time_tb); #endif #endif tolerance = PR_MillisecondsToInterval(tolerance_msecs); threads = PR_Malloc( num_thread_scopes * num_thread_funcs * sizeof(PRThread*)); if (threads == NULL) { fprintf(stderr, "PR_Malloc failed\n"); exit(1); } /* start to time out 5 seconds after a rollover date */ secs = lead_time_secs + 5; idx = 0; for (i = 0; i < num_thread_scopes; i++) { for (j = 0; j < num_thread_funcs; j++) { threads[idx] = PR_CreateThread(PR_USER_THREAD, threadFuncs[j], (void*)PR_SecondsToInterval(secs), PR_PRIORITY_NORMAL, threadScopes[i], PR_JOINABLE_THREAD, 0); if (threads[idx] == NULL) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } secs++; idx++; } } for (idx = 0; idx < num_thread_scopes*num_thread_funcs; idx++) { if (PR_JoinThread(threads[idx]) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } } PR_Free(threads); printf("PASS\n"); return 0; } nspr-4.11/nspr/pr/tests/yield.c0000644000000000000000000000262512623070344014574 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include "prthread.h" #include "prinit.h" #ifndef XP_OS2 #include "private/pprmisc.h" #include #else #include "primpl.h" #include #endif #define THREADS 10 void threadmain(void *_id) { int id = (int)_id; int index; printf("thread %d alive\n", id); for (index=0; index<10; index++) { printf("thread %d yielding\n", id); PR_Sleep(0); printf("thread %d awake\n", id); } printf("thread %d dead\n", id); } int main(int argc, char **argv) { int index; PRThread *a[THREADS]; PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 5); PR_STDIO_INIT(); for (index=0; index int main(int argc, char **argv) { printf("PASS\n"); return 0; } #else /* XP_UNIX */ #include "nspr.h" #include "private/pprio.h" #include #include #include #include #include static void ClientThread(void *arg) { PRFileDesc *sock; PRNetAddr addr; PRUint16 port = (PRUint16) arg; char buf[1024]; PRInt32 nbytes; sock = PR_NewTCPSocket(); if (NULL == sock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (PR_InitializeNetAddr(PR_IpAddrLoopback, port, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } if (PR_Connect(sock, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { fprintf(stderr, "PR_Connect failed\n"); exit(1); } /* * Sleep 5 seconds to force the server thread to get EAGAIN. */ if (PR_Sleep(PR_SecondsToInterval(5)) == PR_FAILURE) { fprintf(stderr, "PR_Sleep failed\n"); exit(1); } /* * Then start reading. */ while ((nbytes = PR_Read(sock, buf, sizeof(buf))) > 0) { /* empty loop body */ } if (-1 == nbytes) { fprintf(stderr, "PR_Read failed\n"); exit(1); } if (PR_Close(sock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } } int main() { PRFileDesc *listenSock; PRFileDesc *acceptSock; int osfd; PRThread *clientThread; PRNetAddr addr; char buf[1024]; PRInt32 nbytes; PRIOVec iov; #ifdef SYMBIAN int loopcount=0; #endif memset(buf, 0, sizeof(buf)); /* Initialize the buffer. */ listenSock = PR_NewTCPSocket(); if (NULL == listenSock) { fprintf(stderr, "PR_NewTCPSocket failed\n"); exit(1); } if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) { fprintf(stderr, "PR_InitializeNetAddr failed\n"); exit(1); } if (PR_Bind(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_Bind failed\n"); exit(1); } /* Find out what port number we are bound to. */ if (PR_GetSockName(listenSock, &addr) == PR_FAILURE) { fprintf(stderr, "PR_GetSockName failed\n"); exit(1); } if (PR_Listen(listenSock, 5) == PR_FAILURE) { fprintf(stderr, "PR_Listen failed\n"); exit(1); } /* * First test PR_Writev. */ clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == clientThread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == acceptSock) { fprintf(stderr, "PR_Accept failed\n"); exit(1); } osfd = PR_FileDesc2NativeHandle(acceptSock); while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) { /* empty loop body */ #ifdef SYMBIAN if (loopcount++>64) break; #endif } if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) { fprintf(stderr, "write failed\n"); exit(1); } iov.iov_base = buf; iov.iov_len = 0; printf("calling PR_Writev with a zero-length buffer\n"); fflush(stdout); nbytes = PR_Writev(acceptSock, &iov, 1, PR_INTERVAL_NO_TIMEOUT); if (nbytes != 0) { fprintf(stderr, "PR_Writev should return 0 but returns %d\n", nbytes); exit(1); } if (PR_Close(acceptSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_JoinThread(clientThread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } /* * Then test PR_Write. */ clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == clientThread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } #ifdef SYMBIAN loopcount = 0; #endif acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == acceptSock) { fprintf(stderr, "PR_Accept failed\n"); exit(1); } osfd = PR_FileDesc2NativeHandle(acceptSock); while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) { /* empty loop body */ #ifdef SYMBIAN if (loopcount++>64) break; #endif } if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) { fprintf(stderr, "write failed\n"); exit(1); } printf("calling PR_Write with a zero-length buffer\n"); fflush(stdout); nbytes = PR_Write(acceptSock, buf, 0); if (nbytes != 0) { fprintf(stderr, "PR_Write should return 0 but returns %d\n", nbytes); exit(1); } if (PR_Close(acceptSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_JoinThread(clientThread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } /* * Finally test PR_Send. */ clientThread = PR_CreateThread(PR_USER_THREAD, ClientThread, (void *) PR_ntohs(PR_NetAddrInetPort(&addr)), PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); if (NULL == clientThread) { fprintf(stderr, "PR_CreateThread failed\n"); exit(1); } #ifdef SYMBIAN loopcount = 0; #endif acceptSock = PR_Accept(listenSock, NULL, PR_INTERVAL_NO_TIMEOUT); if (NULL == acceptSock) { fprintf(stderr, "PR_Accept failed\n"); exit(1); } osfd = PR_FileDesc2NativeHandle(acceptSock); while ((nbytes = write(osfd, buf, sizeof(buf))) != -1) { /* empty loop body */ #ifdef SYMBIAN if (loopcount++>64) break; #endif } if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) { fprintf(stderr, "write failed\n"); exit(1); } printf("calling PR_Send with a zero-length buffer\n"); fflush(stdout); nbytes = PR_Send(acceptSock, buf, 0, 0, PR_INTERVAL_NO_TIMEOUT); if (nbytes != 0) { fprintf(stderr, "PR_Send should return 0 but returns %d\n", nbytes); exit(1); } if (PR_Close(acceptSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } if (PR_JoinThread(clientThread) == PR_FAILURE) { fprintf(stderr, "PR_JoinThread failed\n"); exit(1); } if (PR_Close(listenSock) == PR_FAILURE) { fprintf(stderr, "PR_Close failed\n"); exit(1); } printf("PASS\n"); return 0; } #endif /* XP_UNIX */ nspr-4.11/nspr/tools/.cvsignore0000644000000000000000000000001112623070344014662 0ustar 00000000000000Makefile nspr-4.11/nspr/tools/Makefile.in0000644000000000000000000001022512623070344014737 0ustar 00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #! gmake MOD_DEPTH = .. topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ include $(MOD_DEPTH)/config/autoconf.mk include $(topsrcdir)/config/config.mk ifeq ($(OS_TARGET), WIN16) OS_CFLAGS = $(OS_EXE_CFLAGS) endif DIRS = CSRCS = \ httpget.c \ tail.c \ $(NULL) ifeq (,$(filter-out WINNT OS2,$(OS_ARCH))) PROG_SUFFIX = .exe else PROG_SUFFIX = endif PROGS = $(addprefix $(OBJDIR)/, $(CSRCS:.c=$(PROG_SUFFIX))) TARGETS = $(PROGS) INCLUDES = -I$(dist_includedir) NSPR_VERSION = 3 # Setting the variables LDOPTS and LIBPR. We first initialize # them to the default values, then adjust them for some platforms. LDOPTS = -L$(dist_libdir) LIBPR = -lnspr$(NSPR_VERSION) LIBPLC = -lplc$(NSPR_VERSION) ifeq ($(OS_ARCH), WINNT) ifeq ($(OS_TARGET), WIN16) LIBPR = $(dist_libdir)/nspr$(NSPR_VERSION).lib LIBPLC= $(dist_libdir)/plc$(NSPR_VERSION).lib else LDOPTS = -NOLOGO -DEBUG -INCREMENTAL:NO LIBPR = $(dist_libdir)/libnspr$(NSPR_VERSION).$(LIB_SUFFIX) LIBPLC= $(dist_libdir)/libplc$(NSPR_VERSION).$(LIB_SUFFIX) endif endif ifeq ($(OS_ARCH),OS2) LDOPTS += -Zomf -Zlinker /PM:VIO endif ifneq ($(OS_ARCH), WINNT) PWD = $(shell pwd) endif ifeq ($(OS_ARCH), IRIX) LDOPTS += -rpath $(PWD)/$(dist_libdir) endif ifeq ($(OS_ARCH), OSF1) LDOPTS += -rpath $(PWD)/$(dist_libdir) -lpthread endif ifeq ($(OS_ARCH), HP-UX) LDOPTS += -Wl,+s,+b,$(PWD)/$(dist_libdir) endif # AIX ifeq ($(OS_ARCH),AIX) LDOPTS += -blibpath:$(PWD)/$(dist_libdir):/usr/lib:/lib LIBPR = -lnspr$(NSPR_VERSION)_shr LIBPLC = -lplc$(NSPR_VERSION)_shr endif # Solaris ifeq ($(OS_ARCH), SunOS) ifdef NS_USE_GCC LDOPTS += -Xlinker -R -Xlinker $(PWD)/$(dist_libdir) else LDOPTS += -R $(PWD)/$(dist_libdir) endif # SunOS 5.5 needs to link with -lpthread, even though we already # linked with this system library when we built libnspr.so. ifeq ($(OS_RELEASE), 5.5) ifdef USE_PTHREADS EXTRA_LIBS = -lpthread endif endif endif # SunOS ifeq ($(OS_ARCH), SCOOS) # SCO Unix needs to link against -lsocket again even though we # already linked with these system libraries when we built libnspr.so. EXTRA_LIBS = -lsocket # This hardcodes in the executable programs the directory to find # libnspr.so etc. at program startup. Equivalent to the -R or -rpath # option for ld on other platforms. export LD_RUN_PATH = $(PWD)/$(dist_libdir) endif ##################################################### # # The rules # ##################################################### include $(topsrcdir)/config/rules.mk AIX_PRE_4_2 = 0 ifeq ($(OS_ARCH),AIX) ifneq ($(OS_RELEASE),4.2) ifneq ($(USE_PTHREADS), 1) #AIX_PRE_4_2 = 1 endif endif endif ifeq ($(AIX_PRE_4_2),1) # AIX releases prior to 4.2 need a special two-step linking hack # in order to both override the system select() and be able to # get at the original system select(). # # We use a pattern rule in ns/nspr20/config/rules.mk to generate # the .$(OBJ_SUFFIX) file from the .c source file, then do the # two-step linking hack below. $(OBJDIR)/%: $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) rm -f $@ $(AIX_TMP) $(CC) $(AIX_LINK_OPTS) -o $(AIX_TMP) $< $(dist_libdir)/libnspr$(NSPR_VERSION).a $(CC) -o $@ $(AIX_TMP) $(AIX_WRAP) rm -f $(AIX_TMP) else # All platforms that are not AIX pre-4.2. $(OBJDIR)/%$(PROG_SUFFIX): $(OBJDIR)/%.$(OBJ_SUFFIX) @$(MAKE_OBJDIR) ifeq ($(OS_ARCH), WINNT) ifeq ($(OS_TARGET),WIN16) echo system windows >w16link echo option map >>w16link echo option stack=10K >>w16link echo option heapsize=32K >>w16link echo debug $(DEBUGTYPE) all >>w16link echo name $@ >>w16link echo file >>w16link echo $< >>w16link echo library >>w16link echo $(LIBPR), >>w16link echo $(LIBPLC), >>w16link echo winsock.lib >>w16link wlink @w16link. else link $(LDOPTS) $< $(LIBPR) $(LIBPLC) ws2_32.lib -out:$@ endif else ifeq ($(OS_ARCH),OS2) $(LINK) $(LDOPTS) $< $(LIBPR) $(LIBPLC) $(OS_LIBS) $(EXTRA_LIBS) -o $@ else $(CC) $(XCFLAGS) $< $(LDOPTS) $(LIBPR) $(LIBPLC) $(EXTRA_LIBS) -o $@ endif endif endif export:: $(TARGETS) clean:: rm -f $(TARGETS) nspr-4.11/nspr/tools/httpget.c0000644000000000000000000002457512623070344014532 0ustar 00000000000000/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Author: Wan-Teh Chang * * Given an HTTP URL, httpget uses the GET method to fetch the file. * The fetched file is written to stdout by default, or can be * saved in an output file. * * This is a single-threaded program. */ #include "prio.h" #include "prnetdb.h" #include "prlog.h" #include "prerror.h" #include "prprf.h" #include "prinit.h" #include #include #include /* for atoi */ #define FCOPY_BUFFER_SIZE (16 * 1024) #define INPUT_BUFFER_SIZE 1024 #define LINE_SIZE 512 #define HOST_SIZE 256 #define PORT_SIZE 32 #define PATH_SIZE 512 /* * A buffer for storing the excess input data for ReadLine. * The data in the buffer starts from (including) the element pointed to * by inputHead, and ends just before (not including) the element pointed * to by inputTail. The buffer is empty if inputHead == inputTail. */ static char inputBuf[INPUT_BUFFER_SIZE]; /* * inputBufEnd points just past the end of inputBuf */ static char *inputBufEnd = inputBuf + sizeof(inputBuf); static char *inputHead = inputBuf; static char *inputTail = inputBuf; static PRBool endOfStream = PR_FALSE; /* * ReadLine -- * * Read in a line of text, terminated by CRLF or LF, from fd into buf. * The terminating CRLF or LF is included (always as '\n'). The text * in buf is terminated by a null byte. The excess bytes are stored in * inputBuf for use in the next ReadLine call or FetchFile call. * Returns the number of bytes in buf. 0 means end of stream. Returns * -1 if read fails. */ PRInt32 ReadLine(PRFileDesc *fd, char *buf, PRUint32 bufSize) { char *dst = buf; char *bufEnd = buf + bufSize; /* just past the end of buf */ PRBool lineFound = PR_FALSE; char *crPtr = NULL; /* points to the CR ('\r') character */ PRInt32 nRead; loop: PR_ASSERT(inputBuf <= inputHead && inputHead <= inputTail && inputTail <= inputBufEnd); while (lineFound == PR_FALSE && inputHead != inputTail && dst < bufEnd - 1) { if (*inputHead == '\r') { crPtr = dst; } else if (*inputHead == '\n') { lineFound = PR_TRUE; if (crPtr == dst - 1) { dst--; } } *(dst++) = *(inputHead++); } if (lineFound == PR_TRUE || dst == bufEnd - 1 || endOfStream == PR_TRUE) { *dst = '\0'; return dst - buf; } /* * The input buffer should be empty now */ PR_ASSERT(inputHead == inputTail); nRead = PR_Read(fd, inputBuf, sizeof(inputBuf)); if (nRead == -1) { *dst = '\0'; return -1; } else if (nRead == 0) { endOfStream = PR_TRUE; *dst = '\0'; return dst - buf; } inputHead = inputBuf; inputTail = inputBuf + nRead; goto loop; } PRInt32 DrainInputBuffer(char *buf, PRUint32 bufSize) { PRInt32 nBytes = inputTail - inputHead; if (nBytes == 0) { if (endOfStream) { return -1; } else { return 0; } } if ((PRInt32) bufSize < nBytes) { nBytes = bufSize; } memcpy(buf, inputHead, nBytes); inputHead += nBytes; return nBytes; } PRStatus FetchFile(PRFileDesc *in, PRFileDesc *out) { char buf[FCOPY_BUFFER_SIZE]; PRInt32 nBytes; while ((nBytes = DrainInputBuffer(buf, sizeof(buf))) > 0) { if (PR_Write(out, buf, nBytes) != nBytes) { fprintf(stderr, "httpget: cannot write to file\n"); return PR_FAILURE; } } if (nBytes < 0) { /* Input buffer is empty and end of stream */ return PR_SUCCESS; } while ((nBytes = PR_Read(in, buf, sizeof(buf))) > 0) { if (PR_Write(out, buf, nBytes) != nBytes) { fprintf(stderr, "httpget: cannot write to file\n"); return PR_FAILURE; } } if (nBytes < 0) { fprintf(stderr, "httpget: cannot read from socket\n"); return PR_FAILURE; } return PR_SUCCESS; } PRStatus FastFetchFile(PRFileDesc *in, PRFileDesc *out, PRUint32 size) { PRInt32 nBytes; PRFileMap *outfMap; void *addr; char *start; PRUint32 rem; PRUint32 bytesToRead; PRStatus rv; PRInt64 sz64; LL_UI2L(sz64, size); outfMap = PR_CreateFileMap(out, sz64, PR_PROT_READWRITE); PR_ASSERT(outfMap); addr = PR_MemMap(outfMap, LL_ZERO, size); if (addr == NULL) { fprintf(stderr, "cannot memory-map file: (%d, %d)\n", PR_GetError(), PR_GetOSError()); PR_CloseFileMap(outfMap); return PR_FAILURE; } start = (char *) addr; rem = size; while ((nBytes = DrainInputBuffer(start, rem)) > 0) { start += nBytes; rem -= nBytes; } if (nBytes < 0) { /* Input buffer is empty and end of stream */ return PR_SUCCESS; } bytesToRead = (rem < FCOPY_BUFFER_SIZE) ? rem : FCOPY_BUFFER_SIZE; while (rem > 0 && (nBytes = PR_Read(in, start, bytesToRead)) > 0) { start += nBytes; rem -= nBytes; bytesToRead = (rem < FCOPY_BUFFER_SIZE) ? rem : FCOPY_BUFFER_SIZE; } if (nBytes < 0) { fprintf(stderr, "httpget: cannot read from socket\n"); return PR_FAILURE; } rv = PR_MemUnmap(addr, size); PR_ASSERT(rv == PR_SUCCESS); rv = PR_CloseFileMap(outfMap); PR_ASSERT(rv == PR_SUCCESS); return PR_SUCCESS; } PRStatus ParseURL(char *url, char *host, PRUint32 hostSize, char *port, PRUint32 portSize, char *path, PRUint32 pathSize) { char *start, *end; char *dst; char *hostEnd; char *portEnd; char *pathEnd; if (strncmp(url, "http", 4)) { fprintf(stderr, "httpget: the protocol must be http\n"); return PR_FAILURE; } if (strncmp(url + 4, "://", 3) || url[7] == '\0') { fprintf(stderr, "httpget: malformed URL: %s\n", url); return PR_FAILURE; } start = end = url + 7; dst = host; hostEnd = host + hostSize; while (*end && *end != ':' && *end != '/') { if (dst == hostEnd - 1) { fprintf(stderr, "httpget: host name too long\n"); return PR_FAILURE; } *(dst++) = *(end++); } *dst = '\0'; if (*end == '\0') { PR_snprintf(port, portSize, "%d", 80); PR_snprintf(path, pathSize, "%s", "/"); return PR_SUCCESS; } if (*end == ':') { end++; dst = port; portEnd = port + portSize; while (*end && *end != '/') { if (dst == portEnd - 1) { fprintf(stderr, "httpget: port number too long\n"); return PR_FAILURE; } *(dst++) = *(end++); } *dst = '\0'; if (*end == '\0') { PR_snprintf(path, pathSize, "%s", "/"); return PR_SUCCESS; } } else { PR_snprintf(port, portSize, "%d", 80); } dst = path; pathEnd = path + pathSize; while (*end) { if (dst == pathEnd - 1) { fprintf(stderr, "httpget: file pathname too long\n"); return PR_FAILURE; } *(dst++) = *(end++); } *dst = '\0'; return PR_SUCCESS; } void PrintUsage(void) { fprintf(stderr, "usage: httpget url\n" " httpget -o outputfile url\n" " httpget url -o outputfile\n"); } int main(int argc, char **argv) { PRHostEnt hostentry; char buf[PR_NETDB_BUF_SIZE]; PRNetAddr addr; PRFileDesc *socket = NULL, *file = NULL; PRIntn cmdSize; char host[HOST_SIZE]; char port[PORT_SIZE]; char path[PATH_SIZE]; char line[LINE_SIZE]; int exitStatus = 0; PRBool endOfHeader = PR_FALSE; char *url; char *fileName = NULL; PRUint32 fileSize; if (argc != 2 && argc != 4) { PrintUsage(); exit(1); } if (argc == 2) { /* * case 1: httpget url */ url = argv[1]; } else { if (strcmp(argv[1], "-o") == 0) { /* * case 2: httpget -o outputfile url */ fileName = argv[2]; url = argv[3]; } else { /* * case 3: httpget url -o outputfile */ url = argv[1]; if (strcmp(argv[2], "-o") != 0) { PrintUsage(); exit(1); } fileName = argv[3]; } } if (ParseURL(url, host, sizeof(host), port, sizeof(port), path, sizeof(path)) == PR_FAILURE) { exit(1); } if (PR_GetHostByName(host, buf, sizeof(buf), &hostentry) == PR_FAILURE) { fprintf(stderr, "httpget: unknown host name: %s\n", host); exit(1); } addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons((short) atoi(port)); addr.inet.ip = *((PRUint32 *) hostentry.h_addr_list[0]); socket = PR_NewTCPSocket(); if (socket == NULL) { fprintf(stderr, "httpget: cannot create new tcp socket\n"); exit(1); } if (PR_Connect(socket, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) { fprintf(stderr, "httpget: cannot connect to http server\n"); exitStatus = 1; goto done; } if (fileName == NULL) { file = PR_STDOUT; } else { file = PR_Open(fileName, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 00777); if (file == NULL) { fprintf(stderr, "httpget: cannot open file %s: (%d, %d)\n", fileName, PR_GetError(), PR_GetOSError()); exitStatus = 1; goto done; } } cmdSize = PR_snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n\r\n", path); PR_ASSERT(cmdSize == (PRIntn) strlen("GET HTTP/1.0\r\n\r\n") + (PRIntn) strlen(path)); if (PR_Write(socket, buf, cmdSize) != cmdSize) { fprintf(stderr, "httpget: cannot write to http server\n"); exitStatus = 1; goto done; } if (ReadLine(socket, line, sizeof(line)) <= 0) { fprintf(stderr, "httpget: cannot read line from http server\n"); exitStatus = 1; goto done; } /* HTTP response: 200 == OK */ if (strstr(line, "200") == NULL) { fprintf(stderr, "httpget: %s\n", line); exitStatus = 1; goto done; } while (ReadLine(socket, line, sizeof(line)) > 0) { if (line[0] == '\n') { endOfHeader = PR_TRUE; break; } if (strncmp(line, "Content-Length", 14) == 0 || strncmp(line, "Content-length", 14) == 0) { char *p = line + 14; while (*p == ' ' || *p == '\t') { p++; } if (*p != ':') { continue; } p++; while (*p == ' ' || *p == '\t') { p++; } fileSize = 0; while ('0' <= *p && *p <= '9') { fileSize = 10 * fileSize + (*p - '0'); p++; } } } if (endOfHeader == PR_FALSE) { fprintf(stderr, "httpget: cannot read line from http server\n"); exitStatus = 1; goto done; } if (fileName == NULL || fileSize == 0) { FetchFile(socket, file); } else { FastFetchFile(socket, file, fileSize); } done: if (socket) PR_Close(socket); if (file) PR_Close(file); PR_Cleanup(); return exitStatus; } nspr-4.11/nspr/tools/tail.c0000644000000000000000000000647712623070344014005 0ustar 00000000000000/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "prio.h" #include "prprf.h" #include "prinit.h" #include "prthread.h" #include "prinrval.h" #include "plerror.h" #include "plgetopt.h" #include #define BUFFER_SIZE 500 static PRFileDesc *out = NULL, *err = NULL; static void Help(void) { PR_fprintf(err, "Usage: tail [-n ] [-f] [-h] \n"); PR_fprintf(err, "\t-t Dally time in milliseconds\n"); PR_fprintf(err, "\t-n Number of bytes before \n"); PR_fprintf(err, "\t-f Follow the \n"); PR_fprintf(err, "\t-h This message and nothing else\n"); } /* Help */ PRIntn main(PRIntn argc, char **argv) { PRIntn rv = 0; PLOptStatus os; PRStatus status; PRFileDesc *file; PRFileInfo fileInfo; PRIntervalTime dally; char buffer[BUFFER_SIZE]; PRBool follow = PR_FALSE; const char *filename = NULL; PRUint32 position = 0, seek = 0, time = 0; PLOptState *opt = PL_CreateOptState(argc, argv, "hfn:"); out = PR_GetSpecialFD(PR_StandardOutput); err = PR_GetSpecialFD(PR_StandardError); while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { if (PL_OPT_BAD == os) continue; switch (opt->option) { case 0: /* it's the filename */ filename = opt->value; break; case 'n': /* bytes before end of file */ seek = atoi(opt->value); break; case 't': /* dally time */ time = atoi(opt->value); break; case 'f': /* follow the end of file */ follow = PR_TRUE; break; case 'h': /* user wants some guidance */ Help(); /* so give him an earful */ return 2; /* but not a lot else */ break; default: break; } } PL_DestroyOptState(opt); if (0 == time) time = 1000; dally = PR_MillisecondsToInterval(time); if (NULL == filename) { (void)PR_fprintf(out, "Input file not specified\n"); rv = 1; goto done; } file = PR_Open(filename, PR_RDONLY, 0); if (NULL == file) { PL_FPrintError(err, "File cannot be opened for reading"); return 1; } status = PR_GetOpenFileInfo(file, &fileInfo); if (PR_FAILURE == status) { PL_FPrintError(err, "Cannot acquire status of file"); rv = 1; goto done; } if (seek > 0) { if (seek > fileInfo.size) seek = 0; position = PR_Seek(file, (fileInfo.size - seek), PR_SEEK_SET); if (-1 == (PRInt32)position) PL_FPrintError(err, "Cannot seek to starting position"); } do { while (position < fileInfo.size) { PRInt32 read, bytes = fileInfo.size - position; if (bytes > sizeof(buffer)) bytes = sizeof(buffer); read = PR_Read(file, buffer, bytes); if (read != bytes) PL_FPrintError(err, "Cannot read to eof"); position += read; PR_Write(out, buffer, read); } if (follow) { PR_Sleep(dally); status = PR_GetOpenFileInfo(file, &fileInfo); if (PR_FAILURE == status) { PL_FPrintError(err, "Cannot acquire status of file"); rv = 1; goto done; } } } while (follow); done: PR_Close(file); return rv; } /* main */ /* tail.c */