diff options
171 files changed, 6880 insertions, 994 deletions
@@ -1,3 +1,435 @@ +1997-08-10 18:48 Ulrich Drepper <drepper@cygnus.com> + + * Makeconfig: Define build-programs to no if not set and $(config-os) + is none. + * Makerules (+depfiles): Don't add $(others) if not build-programs. + * Rules (others): Don't depend on $(install-bin), $(install-rootbin) + and $(install-sbin) if not build-programs. + * Makefile (subdirs): Remove login. + * sysdeps/mach/hurd/Subdirs: Add login. + * sysdeps/unix/Subdirs: Add login. + + * sysdeps/generic/sys/mman.h: Test feature macros before defining + non-POSIX things. Add MAP_FAILED. + * sysdeps/unix/bsd/osf/sys/mman.h: Likewise. + * sysdeps/unix/bsd/sun/sunos4/sys/mman.h: Likewise. + * sysdeps/unix/bsd/ultrix4/sys/mman.h: Likewise. + * sysdeps/unix/sysv/irix4/sys/mman.h: Likewise. + * sysdeps/unix/sysv/linux/sys/mman.h: Rewrite to not use kernel header + but bits/mman.h. Test feature macros before definitions non-POSIX + functions. + * sysdeps/unix/sysv/linux/alpha/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/i386/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/m68k/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/mips/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/powerpc/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/sparc64/bits/mman.h: New file. + * sysdeps/unix/sysv/linux/alpha/Dist: Add bits/mman.h. + * sysdeps/unix/sysv/linux/i386/Dist: Likewise. + * sysdeps/unix/sysv/linux/m68k/Dist: Likewise. + * sysdeps/unix/sysv/linux/mips/Dist: Likewise. + * sysdeps/unix/sysv/linux/powerpc/Dist: Likewise. + * sysdeps/unix/sysv/linux/sparc/Dist: Likewise. + * sysdeps/unix/sysv/linux/sparc64/Dist: New file. Likewise. + + * catgets/open_catalog.c (__open_catalog): Compare result of mmap + with MAP_FAILED and not -1. + * elf/dl-load.c (_dl_map_object_from_fd): Likewise. + * elf/dl-minimal.c (malloc): Likewise. + * elf/dl-misc.c (_dl_sysdep_read_whole_file): Likewise. + * locale/loadlocale.c (_nl_load_locale): Likewise. + * locale/programs/localedef.c: Likewise. + * malloc/malloc.c (mmap_chunk): Likewise. + (new_heap): Likewise. + * string/stratcliff.c: Likewise. + * string/tester.c: Add tests for stpcpy. + + * gmon/gmon.c (__monstartup): Use calloc instead of malloc+memset. + + * gmon/sys/gmon.h: Add prototype for write_profiling. + + * elf/dl-profile.c: Add decsriptions and implement reading of + existing data in profiling file. + * gmon/sys/gmon_out.h (GMON_SHOBJ_VERSION): New macro for shared + lib profiling data. + + * sysdeps/stub/bits/libc-lock.h (__libc_once_define): Add new first + parameter for class. + + * inet/inet_ntoa.c: Make once control variable static. + Correctly handle case where key cannot be retrieved. + * inet/Makefile (tests): Add tst-ntoa. + * inet/tst-ntoa.c: New file. + + * manual/time.texi: Document localtime_r, gmtime_r, asctime_r, and + ctime_r. + Mention that tzname values must not be changed. + + * manual/users.texi: Document UTMP/WTMP handling functions. + Mainly written by Mark Kettenis. + + * math/libm-test.c (cbrt_test): Add test for number with aboslute + value < 1.0. + + * nss/nss_files/files-XXX.c (internal_setent): If opening of file + failed with EGAIN return NSS_STATUS_TRYAGAIN. + * nss/nss_files/files-alias.c (internal_setent): Likewise. + + * sysdeps/generic/bits/utmp.h: Pretty print. + + * sysdeps/i386/i586/strcpy.S: New file. Much faster implementation. + * sysdeps/i386/i586/stpcpy.S: New file. + * sysdeps/i386/i686/Implies: Don't fall back on i586 versions since + these are less efficient than i486/i386 versions. + + * sysdeps/libm-i387/e_rem_pio2.c: Add empty file to prevent the + version from libm-ieee754 be compiled since the later is not needed. + * sysdeps/libm-i387/e_rem_pio2f.c: Likewise. + * sysdeps/libm-i387/e_rem_pio2l.c: Likewise. + * sysdeps/libm-i387/k_rem_pio2.c: Likewise. + * sysdeps/libm-i387/k_rem_pio2f.c: Likewise. + * sysdeps/libm-i387/k_rem_pio2l.c: Likewise. + * sysdeps/m68k/fpu/e_rem_pio2.c: Likewise. + * sysdeps/m68k/fpu/e_rem_pio2f.c: Likewise. + * sysdeps/m68k/fpu/e_rem_pio2l.c: Likewise. + * sysdeps/m68k/fpu/k_rem_pio2.c: Likewise. + * sysdeps/m68k/fpu/k_rem_pio2f.c: Likewise. + * sysdeps/m68k/fpu/k_rem_pio2l.c: Likewise. + + * sysdeps/libm-i387/s_cbrt.S: Fix several bugs. + * sysdeps/libm-i387/s_cbrtf.S: Likewise. + * sysdeps/libm-i387/s_cbrtl.S: Likewise. + + * sysdeps/unix/sysv/linux/if_index.c (if_indextoname): Correct + little bug. + + * sysdeps/unix/sysv/linux/bits/socket.h (struct msghdr): Make field + msg_iovlen of type int. + + * time/tzfile.c: Change return type of __tzstring to char *. + * time/tzset.c: Likewise. Change definition of __tzstring. + + * time/tzset.c: Interpret no DST information in user provided time + zone specification as it is meant: no DST. + Patch by Paul Eggert <eggert@twinsun.com>. + +1997-07-20 03:01 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/elf/dl-load.c (add_name_to_object): New procedure. + (_dl_map_object_from_fd): Use add_name_to_object. + (_dl_map_object): If an object's SONAME is used to resolve a + dependency, add it to the list of the object's names. + + * inet/getnameinfo.c: Make `domain' non-const. + + * sysdeps/unix/sysv/linux/powerpc/kernel_termios.c: Clean up. + + * math/test-fenv.c (feenv_nomask_test): Don't execute if + FE_NOMASK_ENV is not defined, or if fesetenv(FE_NOMASK_ENV) + sets errno to ENOSYS. + + * sysdeps/powerpc/dl-machine.h: Print proper error message on + unknown reloc type (rather than using assert). + + * sysdeps/unix/sysv/linux/powerpc/profil-counter.h: New file. + * sysdeps/unix/sysv/linux/powerpc/profil.c: Deleted. + +1997-07-16 12:47 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/powerpc/bits/fenv.h (feraiseexcept): New optimising macro. + (feclearexcept): New optimising macro. + (FE_NOMASK_ENV): Change to procedure so it can enable exceptions. + (FE_ENABLED_ENV): Add. + (FE_NONIEEE_ENV): Add. + * sysdeps/powerpc/bits/fenv_const.c: Add __fe_enabled_env, + __fe_nonieee_env; delete __fe_nomask_env. + * sysdeps/powerpc/bits/fe_nomask.c: New file (stub warning until it + gets implemented in the kernel). + + * sysdeps/powerpc/fraiseenv.c: Deal with chips that don't have + FE_INVALID_SOFTWARE implemented. Use macros for bit names for clarity. + * sysdeps/powerpc/fsetexcptflag.c: Likewise. + + * io/ftw.c: Don't compare holes in structures. + * sysdeps/unix/sysv/linux/sys/sysmacros.h: Cast the result of the + macros to `int', because otherwise it might be `long long' which + the calling code is probably not expecting. + + * sysdeps/libm-ieee754/s_lround.c [NO_LONG_DOUBLE]: Fix a few bugs, + document the existence of some more. + + * sysdeps/powerpc/s_llrint.c: New file. + * sysdeps/powerpc/s_lrint.c: New file. + * sysdeps/powerpc/s_llround.c: New file. + * sysdeps/powerpc/s_lround.c: New file. + + * sysdeps/powerpc/s_sqrt.c: New file. + * sysdeps/powerpc/s_sqrtf.c: New file. + * sysdeps/powerpc/w_sqrt.s: New empty file. + * sysdeps/powerpc/w_sqrtf.s: New empty file. + * sysdeps/powerpc/t_sqrt.c: New file. + * sysdeps/powerpc/test-arithf.c: New file. + * sysdeps/powerpc/Makefile [subdir=math]: Add t_sqrt to support + routines. Add test-arithf to test programs. + + * sysdeps/powerpc/bits/mathdef.h: Add FP_ILOGB0, FP_ILOGBNAN. + + * sysdeps/powerpc/strcmp.s: Simplify drastically. Now much neater, + and possibly faster (or possibly slower, depending on input). + +1997-06-08 22:55 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/powerpc/fenvbits.h: Correct FE_DFL_ENV and FE_NOMASK_ENV + macros. + * sysdeps/powerpc/s_rint.c: New file. + +1997-05-22 08:47 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/powerpc/Makefile [subdir=math]: Add q_* routines. + * sysdeps/powerpc/Dist: Add quad_float.h. + * sysdeps/powerpc/q_dtoq.c: New file. + * sysdeps/powerpc/q_itoq.c: New file. + * sysdeps/powerpc/q_lltoq.c: New file. + * sysdeps/powerpc/q_neg.c: New file. + * sysdeps/powerpc/q_qtoi.c: New file. + * sysdeps/powerpc/q_qtoll.c: New file. + * sysdeps/powerpc/q_qtos.c: New file. + * sysdeps/powerpc/q_qtou.c: New file. + * sysdeps/powerpc/q_qtoull.c: New file. + * sysdeps/powerpc/q_stoq.c: New file. + * sysdeps/powerpc/q_ulltoq.c: New file. + * sysdeps/powerpc/q_utoq.c: New file. + * sysdeps/powerpc/quad_float.h: New file. + * sysdeps/powerpc/test-arith.c: New file. + + * sysdeps/powerpc/fpu_control.h: Fix _FPU_GETCW. + * sysdeps/powerpc/fegetround.c: Use mcrfs to be faster and not + require a stack frame. + * sysdeps/powerpc/bits/fenv.h: Include inline macro for fegetround. + +1997-05-18 05:55 Geoff Keating <geoffk@ozemail.com.au> + + * sysdeps/powerpc/fenv_libc.h (fegetenv_register, + fesetenv_register): Add 'volatile'. + (set_fpscr_bit, reset_fpscr_bit): New macros, FPSCR_* + constants to use with them. + * sysdeps/powerpc/s_copysign.S: New file. + * sysdeps/powerpc/s_copysignf.s: New file. + * sysdeps/powerpc/s_fabs.S: New file. + * sysdeps/powerpc/s_fabsf.s: New file. + * sysdeps/powerpc/s_isnan.c: New file. + * sysdeps/powerpc/s_isnanf.s: New file. + * sysdeps/powerpc/s_rintf.c: New file. + + * sysdeps/powerpc/fenvbits.h: Make FE_INVALID the summary + bit in the FPSCR, not the enable bit. + * sysdeps/powerpc/fraiseexcpt.c: Consequent change to the above. + * sysdeps/powerpc/fclrexcpt.c: Correct. + * sysdeps/powerpc/fsetexcptflag.c: Correct. + * sysdeps/powerpc/ftestexcpt.c: Is now much simpler. + * sysdeps/powerpc/fgetexcptflg.c: Simplify. + + * sysdeps/powerpc/strlen.s: Schedule better, save 3 clocks :-). + + * sysdeps/powerpc/dl-machine.h (elf_machine_rela): Add comment + explaining some reentrancy issues with lazy PLT entries. + +1997-08-09 13:04 Mark Kettenis <kettenis@phys.uva.nl> + + * login/logout.c (logout): utmpname returns -1 on error. + + * login/libutil.map: Remove updwtmp. + + * login/getutline.c: Rename getutline to __getutline and make + getutline a weak alias. Make getutxline a weak alias for + __getutline. + * login/getutid.c: Rename getutid to __getutid and make getutid a + weak alias. Make getutxid a weak alias for __getutid. + * libc.map: Add getutxid, getutxline. + + * login/utmpname.c (__utmpname): Reset backend right after backend + endutent call. + * login/utmp_file.c: Reordered functions. Remove unecessary + header files. + (getutent_r_file, pututline_file): Do not call setutent_file. At this + point the file is guaranteed to be open (assert!). + (getutid_r_file, getutline_r_file): Remove check for validity of file + descriptor. At this point the file is guaranteed to be open. + (getutent_r_file, internal_getut_r, getutline_r_file, pututline_file, + updwtmp_file): Do not wait when unlocking file. + * login/utmp_daemon.c: General cleanup and a bit of reordering. + (getutent_r_daemon, pututline_daemon): Do not call setutent_daemon. + At this point the socket is guaranteed to be open (assert!). + (getutid_r_daemon, getutline_r_daemon): Do not check if daemon_sock is + valid. At this point the socket is guaranteed to be open (assert!). + * login/getutline_r.c: Remove unnecessary header files. + (__getutline_r): Do not call backend setutent. + * login/getutid_r.c: Remove unnecessary header files. + (__getutid_r): Do not call backend setutent. + * login/getutent_r.c: Remove unneccesary header files. + (__libc_utmp_unknown_functions): Added getutid_r_unknown, + getutline_r_unknown. + (setutent_unknown): Only set file backend if setutent for the file + backend was successful. + (getutent_r_unknown, pututline_unknown): Call setutent_unknown instead + of __setutent. Report failure if no backend was selected. + (getutid_r_unknown): New function. + (getutline_r_unknown): New function. + (__endutent): Reset backend. This makes sure all backends are checked + on the next setutent call. + +1997-08-08 20:20 Thorsten Kukuk <kukuk@vt.uni-paderborn.de> + + * nis_cache.c: Replace dummy functions. + + * libc.map: Add xdr_sizeof symbol. + + * sunrpc/Makefile: Add xdr_sizeof to routines. + * sunrpc/rpc/xdr.h: Add xdr_sizeof prototype. + * sunrpc/xdr_sizeof.c: New, from tirpc 2.3. + +1997-08-08 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/bits/libc-lock.h (__libc_once): Define correctly. + +1997-08-07 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/hurd/profil.c (fetch_samples): Put parens in the + right place. + +1997-08-06 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/hurd/profil.c (fetch_samples): Do arithmetic on + PC's in long long to avoid overflow. + +1997-08-07 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/bits/libc-lock.h (__libc_once, __libc_once_define): + New macros. + +1997-08-06 Andreas Jaeger <aj@arthur.rhein-neckar.de> + + * nis/Makefile (headers): Remove bits/nislib.h. + +1997-08-06 14:54 Ulrich Drepper <drepper@cygnus.com> + + * sysdeps/mach/hurd/Subdirs: Add login. + +1997-08-06 14:23 Klaus Espenlaub <kespenla@hydra.informatik.uni-ulm.de> + + * db/hash/hash.c (init_hash): Don't use stat() if it doesn't provide + the preferred block size. + + * login/programs/database.c (store_state_entry): Don't compile if + there is no ut_type field. + (store_state_entry, store_process_entry): Use the ut_tv field + for timestamps if supported. + + * login/programs/utmpdump.c (print_entry): Always use ut_tv field. + + * login/programs/xtmp.c: Fix numerous xtmp/utmp typos. Use the ut_tv + field for timestamps if supported. + + * login/programs/xtmp.h: Fix xtmp/utmp typo. + + * sysdeps/posix/defs.c (stdstream): Change (PTR) to (void *). + + * sysdeps/stub/connect.c (connect): Change to __connect, add alias. + * sysdeps/stub/send.c (send): Likewise. + * sysdeps/stub/s_exp2f.c: Emit correct stub_warning(). + * sysdeps/stub/statfs.c: Move stub_warning() to the usual place. + * sysdeps/stub/init-first.c: Add definition of __libc_pid. + +1997-08-05 13:28 Philip Blundell <pb@spring.nexus.co.uk> + + * sysdeps/standalone/arm/bits/errno.h: Add EISDIR, EOPNOTSUPP; + tidy up formatting. + + * Makefile (subdirs): Remove `login'. + * sysdeps/unix/Subdirs: New file; build `login' subdirectory + for Unix systems. + +1997-08-05 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * sysdeps/generic/bits/utmpx.h: New file. + + * sysdeps/mach/hurd/Dist: Add some files. + * sysdeps/mips/Dist: Likewise. + * sysdeps/mips/mips64/Dist: Likewise. + * sysdeps/sparc/Dist: Likewise. + * sysdeps/unix/sysv/linux/mips/Dist: Likewise. + * sysdeps/unix/sysv/linux/sparc/Dist: Likewise. + * sysdeps/mips/mipsel/Dist: New file. + * sysdeps/sparc64/elf/Dist: New file. + * sysdeps/unix/sysv/linux/sparc64/Dist: New file. + +1997-08-05 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * libc.map: Add missing symbols. + +1997-08-05 Andreas Jaeger <aj@arthur.rhein-neckar.de> + + * manual/socket.texi: Correct typos. + + * manual/math.texi: Correct typos. + + * manual/time.texi (Formatting Date and Time): Likewise. + +1997-08-04 13:06 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * gmon/gmon.c (write_gmon): New function; guts from _mcleanup. + (_mcleanup): Use write_gmon. + (write_profiling): This function can be safely called at any time + to write a current histogram without interfering with ongoing + profiling. + + * sysdeps/mach/hurd/profil.c (fetch_samples): Initialize NSAMPLES. + +1997-08-01 17:53 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/hurd/profil.c (fetch_samples): Sample buffer need + not be vm_deallocated; it's a stack buffer. + (profil_vm_deallocate): Delete prototype. + (#include <../mach/RPC_vm_deallocate_rpc.c>): Drop this + inclusion. + * sysdeps/mach/hurd/Makefile + ($(common-objpfx)hurd/../mach/RPC_vm_deallocate_rpc.c): Delete + this rule. + + * sysdeps/mach/hurd/profil.c (fetch_samples): New function, guts + from profile_waiter. + (profile_waiter): Use fetch_samples. + (profil): When turning off profiling, fetch the last bunch of + samples before disabling PC sampling. + (fetch_samples): Add prototype. + +1997-07-30 12:53 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/hurd/Makefile: Give normal rules for the mach RPC + source included by profil.c instead of trying to use + before-compile grot. + +1997-07-23 15:04 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu> + + * sysdeps/mach/hurd/profil.c (profile_waiter): Do vm_deallocate + after releasing lock. Use special RPC stubs and avoid assert, + thus making this function entirely independent of the threadvar + mechanism and of cthreads. + (lock): Convert to be a spin lock instead of a mutex, so that the + waiter thread need not use cthreads. Use a fork prepare hook + instead of _hurd_fork_locks to make sure we are clean before + forking. + (fork_profil_child): Renamed from fork_profil. + (profil_reply_port): New variable. + (profil_vm_deallocate, profil_task_get_sampled_pcs): Special RPC + stubs made by special hacks. + * sysdeps/mach/hurd/Makefile (before-compile): Add the mach RPC + source files that profil.c needs if we are in the gmon directory. + + * mach/setup-thread.c (__mach_setup_thread): Delete avoidance of a + cthreads bug that hasn't existed for two years. + 1997-08-04 15:29 Ulrich Drepper <drepper@cygnus.com> * locale/programs/localedef.c (main): Set bit in avail for those @@ -44,7 +476,7 @@ * sysdeps/unix/sysv/linux/bits/socket.h: Likewise. * sysdeps/unix/sysv/linux/mips/bits/socket.h: Likewise. - * stdio-common/printf_fp.c (__printf_fp): Correct rouding of number + * stdio-common/printf_fp.c (__printf_fp): Correct rounding of numbers 1.0 < x < 8.0. * stdio-common/tfformat.c: Add new tests for above bug. @@ -192,7 +624,7 @@ * csu/defs.awk: Fix regexp for end and align. Patch by Klaus Espenlaub <kespenla@hydra.informatik.uni-ulm.de>. - * locale/programs/localedef.c (print_escaped): New function. + * locale/programs/locale.c (print_escaped): New function. (show_info): Use print_escaped if strings can control unprintable characters. Patch by Jochen Hein <jochen.hein@delphi.central.de>. @@ -710,7 +1142,7 @@ * time/africa: Update from tzdata1997g. * time/asia: Likewise. - * time/australia: Likewise. + * time/australasia: Likewise. * time/europe: Likewise. * time/iso3166.tab: Likewise. * time/zone.tab: Likewise. @@ -960,7 +1392,7 @@ * login/programs/utmpd.c: (main): Change handling of errors in opening the database. * login/programs/database.c: - (open_database, synchronize_dtatabase, initialize_database): + (open_database, synchronize_database, initialize_database): Properly handle errors. (get_mtime): Use fstat instead of stat. All callers changed. @@ -1127,7 +1559,7 @@ * libio/strops.c: Correctly handle _IO_write_end. * nss/libnss_files.map: Add __nss_netgroup_parseline. - * nss/nss_files/files-netgroup.c (_nss_netgroup_parseline): Don't + * nss/nss_files/files-netgrp.c (_nss_netgroup_parseline): Don't panic if setnetgrent wasn't called before, return error. Patch by Thorsten Kukuk <kukuk@uni-paderborn.de>. @@ -3325,7 +3757,7 @@ * libc.map: Add more symbols. - * Mwkerules (load-map-file): Currectly handle missing map file. + * Makerules (load-map-file): Currectly handle missing map file. 1997-06-15 17:00 Philip Blundell <Philip.Blundell@pobox.com> @@ -3584,8 +4016,8 @@ 1997-06-12 12:45 Ulrich Drepper <drepper@cygnus.com> * sysdeps/i386/fpu/__math.h (__M_SQRT2): Define here since we - cannot rely on M_SQRT2 being defined. (log1p): Use __M_SQRT2 not - M_SQRT2. + cannot rely on M_SQRT2 being defined. + (log1p): Use __M_SQRT2 not M_SQRT2. * math/math.h (_Mldbl): Define even if M_* constants are not defined. Reported by corsepiu@faw.uni-ulm.de. @@ -618,7 +618,13 @@ invalid. I.e., an emulated FPU is for the libc as good as a real one. glibc 2.x? [A20] {AJ} There's only support for glibc 2.0 in gcc 2.7.2.2 or later. -For 2.7.2.2 you should use the following patch and configure for + +gcc 2.7.2.2 has also a nasty bug. It installs its own version of +assert.h into /usr/<machine>/include that is not compatible with +glibc. Please remove this file - otherwise you get lots of problems +with configure. + +For 2.7.2.2 you should also use the following patch and configure for e.g. i486-linux. ----------------------------------------------------------------------- --- configure Tue Feb 11 15:57:17 1997 diff --git a/Makeconfig b/Makeconfig index 4d6e2e6c54..37839bc972 100644 --- a/Makeconfig +++ b/Makeconfig @@ -149,6 +149,17 @@ ifeq ($(origin prefix),undefined) # ifndef would override explicit empty value. prefix = /usr/local endif +# Decide whether we shall build the programs or not. We always do this +# unless the user tells us (in configparms) or we are building for a +# standalone target. +ifndef build-programs +ifneq ($(config-os),none) +build-programs=yes +else +build-programs=no +endif +endif + # Common prefix for machine-dependent installation directories. ifeq ($(origin exec_prefix),undefined) exec_prefix = $(prefix) @@ -53,7 +53,7 @@ endif # These are the subdirectories containing the library source. subdirs = csu assert ctype db locale intl catgets math setjmp signal stdlib \ stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd \ - posix io termios resource misc login socket sysvipc gmon gnulib \ + posix io termios resource misc socket sysvipc gmon gnulib \ wctype manual shadow md5-crypt nss $(sysdep-subdirs) po argp \ $(add-ons) $(binfmt-subdir) export subdirs := $(subdirs) # Benign, useless in GNU make before 3.63. @@ -426,9 +426,15 @@ extra-libs-left := $(extra-libs) include $(patsubst %,$(..)extra-lib.mk,$(extra-libs)) endif +ifeq ($(build-programs),yes) +depfiles := $(strip $(sources:.c=.d) \ $(patsubst %.o,%.d,$(filter %.o,$(extra-objs:.so=.o))) \ $(addsuffix .d,$(others) $(tests) $(test-srcs))) +else ++depfiles := $(strip $(sources:.c=.d) \ + $(patsubst %.o,%.d,$(filter %.o,$(extra-objs:.so=.o))) \ + $(addsuffix .d,$(tests) $(test-srcs))) +endif +depfiles := $(addprefix $(objpfx),\ $(filter-out $(addsuffix .d,$(omit-deps)),\ $(+depfiles))) @@ -1,6 +1,6 @@ Open jobs for finishing GNU libc: --------------------------------- -Status: April 1997 +Status: August 1997 If you have time and talent to take over any of the jobs below please contact <bug-glibc@prep.ai.mit.edu> @@ -37,14 +37,6 @@ contact <bug-glibc@prep.ai.mit.edu> for the current status (of course better use a mirror of prep). -[ 5] Write wordexp() function; this is described in POSIX.2, the - header <wordexp.h> already exists. - - Implementation idea: use some functions from bash. - -**** Somebody is working on this. Help may or may not be appreciated. - - [ 6] Write `long double' versions of the math functions. This should be done in collaboration with the NetBSD and FreeBSD people. @@ -115,3 +107,7 @@ contact <bug-glibc@prep.ai.mit.edu> int foo __P ((int, int, int, int)); Blargh! + +[16] Write an nss_hesiod module. The Hesiod daemon from the MIT Athena + project should be available. The goal is to avoid the ugly NIS + emulation interface and contacting the daemon directly. @@ -38,9 +38,14 @@ export subdir := $(subdir) .PHONY: all all: objs lib others +ifeq ($(build-programs),yes) others: $(addprefix $(objpfx),$(extra-objs) \ $(install-lib) $(install-bin) \ $(install-rootsbin) $(install-sbin)) +else +others: $(addprefix $(objpfx),$(extra-objs) \ + $(install-lib)) +endif ifneq "$(findstring env,$(origin headers))" "" headers := @@ -81,19 +86,32 @@ common-generated := $(common-generated) dummy.o dummy.c empty.c empty.o # This makes all the auxiliary and test programs. .PHONY: others tests +ifeq ($(build-programs),yes) others: $(addprefix $(objpfx),$(others) $(extra-objs)) +else +others: $(addprefix $(objpfx),$(extra-objs)) +endif ifeq ($(cross-compiling),yes) tests: $(addprefix $(objpfx),$(tests) $(test-srcs)) else tests: $(tests:%=$(objpfx)%.out) endif +ifeq ($(build-programs),yes) ifneq "$(strip $(others) $(tests) $(test-srcs))" "" $(addprefix $(objpfx),$(others) $(tests) $(test-srcs)): %: %.o \ $(sort $(filter $(common-objpfx)libc%,$(link-libc))) \ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) $(+link) endif +else +ifneq "$(strip $(tests) $(test-srcs))" "" +$(addprefix $(objpfx),$(tests) $(test-srcs)): %: %.o \ + $(sort $(filter $(common-objpfx)libc%,$(link-libc))) \ + $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) + $(+link) +endif +endif ifneq "$(strip $(tests) $(test-srcs))" "" # These are the implicit rules for making test outputs diff --git a/bits/utmp.h b/bits/utmp.h index b8decb0598..ccc318bfa1 100644 --- a/bits/utmp.h +++ b/bits/utmp.h @@ -17,7 +17,7 @@ Boston, MA 02111-1307, USA. */ #ifndef _UTMP_H -#error "Never use <bits/utmp.h> directly; include <utmp.h> instead." +# error "Never use <bits/utmp.h> directly; include <utmp.h> instead." #endif @@ -33,21 +33,23 @@ __BEGIN_DECLS -struct lastlog { - time_t ll_time; - char ll_line[UT_LINESIZE]; - char ll_host[UT_HOSTSIZE]; -}; +struct lastlog + { + time_t ll_time; + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; + }; -struct utmp { - char ut_line[UT_LINESIZE]; - char ut_name[UT_NAMESIZE]; - char ut_host[UT_HOSTSIZE]; - long ut_time; -}; +struct utmp + { + char ut_line[UT_LINESIZE]; + char ut_user[UT_NAMESIZE]; +#define ut_name ut_user + char ut_host[UT_HOSTSIZE]; + long int ut_time; + }; #define _HAVE_UT_HOST 1 /* We have the ut_host field. */ - __END_DECLS diff --git a/catgets/open_catalog.c b/catgets/open_catalog.c index 80d2899a36..2c1cbb4a4c 100644 --- a/catgets/open_catalog.c +++ b/catgets/open_catalog.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>. @@ -183,7 +183,7 @@ __open_catalog (__nl_catd catalog, int with_path) catalog->file_ptr = (struct catalog_obj *) __mmap (NULL, st.st_size, PROT_READ, MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0); - if (catalog->file_ptr != (struct catalog_obj *) -1) + if (catalog->file_ptr != (struct catalog_obj *) MAP_FAILED) /* Tell the world we managed to mmap the file. */ catalog->status = mmapped; else diff --git a/db/hash/hash.c b/db/hash/hash.c index 0267da8c60..4ccb992bb7 100644 --- a/db/hash/hash.c +++ b/db/hash/hash.c @@ -282,7 +282,9 @@ init_hash(hashp, file, info) const char *file; HASHINFO *info; { +#ifdef _STATBUF_ST_BLKSIZE struct stat statbuf; +#endif int nelem; nelem = 1; @@ -299,14 +301,14 @@ init_hash(hashp, file, info) memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); /* Fix bucket size to be optimal for file system */ +#ifdef _STATBUF_ST_BLKSIZE if (file != NULL) { if (stat(file, &statbuf)) return (NULL); -#if defined _STATBUF_ST_BLKSIZE hashp->BSIZE = statbuf.st_blksize; -#endif hashp->BSHIFT = __hash_log2(hashp->BSIZE); } +#endif if (info) { if (info->bsize) { diff --git a/elf/dl-load.c b/elf/dl-load.c index f7c2c53f7e..f0af29292a 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -107,27 +107,51 @@ local_strdup (const char *s) return (char *) memcpy (new, s, len); } - -/* Implement cache for search path lookup. */ -#if 0 -/* This is how generated should look like. I'll remove this once I'm - sure everything works correctly. */ -static struct r_search_path_elem rtld_search_dir1 = - { "/lib/", 5, unknown, 0, unknown, NULL }; -static struct r_search_path_elem rtld_search_dir2 = - { "/usr/lib/", 9, unknown, 0, unknown, &r ld_search_dir1 }; - -static struct r_search_path_elem *rtld_search_dirs[] = +/* Add `name' to the list of names for a particular shared object. + `name' is expected to have been allocated with malloc and will + be freed if the shared object already has this name. + Returns false if the object already had this name. */ +static int +add_name_to_object (struct link_map *l, char *name) { - &rtld_search_dir1, - &rtld_search_dir2, - NULL -}; + struct libname_list *lnp, *lastp; + struct libname_list *newname; -static struct r_search_path_elem *all_dirs = &rtld_search_dir2; -#else -# include "rtldtbl.h" -#endif + if (name == NULL) + { + /* No more memory. */ + _dl_signal_error (ENOMEM, NULL, _("could not allocate name string")); + return 0; + } + + lastp = NULL; + for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next) + if (strcmp (name, lnp->name) == 0) + { + free (name); + return 0; + } + + newname = malloc (sizeof *newname); + if (newname == NULL) + { + /* No more memory. */ + _dl_signal_error (ENOMEM, name, _("cannot allocate name record")); + free(name); + return 0; + } + /* The object should have a libname set from _dl_new_object. */ + assert (lastp != NULL); + + newname->name = name; + newname->next = NULL; + lastp->next = newname; + return 1; +} + + +/* Implement cache for search path lookup. */ +#include "rtldtbl.h" static size_t max_dirnamelen; @@ -423,9 +447,10 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, l->l_next->l_prev = l->l_prev; free (l); } - free (name); /* XXX Can this be correct? --drepper */ free (realname); _dl_signal_error (code, name, msg); + free (name); /* Hmmm. Can this leak memory? Better + than a segfault, anyway. */ } inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len, @@ -434,7 +459,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot, fixed|MAP_COPY|MAP_FILE, fd, offset); - if (mapat == (caddr_t) -1) + if (mapat == MAP_FAILED) lose (errno, "failed to map segment from shared object"); return mapat; } @@ -451,7 +476,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, mapping_size &= ~(_dl_pagesize - 1); result = __mmap (file_mapping, mapping_size, PROT_READ, MAP_COPY|MAP_FILE, fd, 0); - if (result == (void *) -1) + if (result == MAP_FAILED) lose (errno, "cannot map file data"); file_mapping = result; } @@ -467,7 +492,6 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, for (l = _dl_loaded; l; l = l->l_next) if (! strcmp (realname, l->l_name)) { - struct libname_list *lnp, *lastp; /* The object is already loaded. Just bump its reference count and return it. */ __close (fd); @@ -475,26 +499,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, /* If the name is not in the list of names for this object add it. */ free (realname); - lastp = NULL; - for (lnp = l->l_libname; lnp != NULL; lastp = lnp, lnp = lnp->next) - if (strcmp (name, lnp->name) == 0) - { - free (name); - break; - } - if (lnp == NULL) - { - struct libname_list *newname = malloc (sizeof *newname); - if (newname == NULL) - /* No more memory. */ - lose (ENOMEM, "cannot allocate name record"); - /* The object should have a libname set. */ - assert (lastp != NULL); - - newname->name = name; - newname->next = NULL; - lastp->next = newname; - } + add_name_to_object (l, name); ++l->l_opencount; return l; } @@ -701,7 +706,7 @@ _dl_map_object_from_fd (char *name, int fd, char *realname, mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED, ANONFD, 0); - if (mapat == (caddr_t) -1) + if (mapat == MAP_FAILED) lose (errno, "cannot map zero-fill pages"); } } @@ -876,6 +881,10 @@ _dl_map_object (struct link_map *loader, const char *name, int type, { /* The object is already loaded. Just bump its reference count and return it. */ + const char *soname = (const char *) (l->l_addr + + l->l_info[DT_STRTAB]->d_un.d_ptr + + l->l_info[DT_SONAME]->d_un.d_val); + add_name_to_object (l, local_strdup (soname)); ++l->l_opencount; return l; } diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index f5b256808a..486e5bc608 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -66,7 +66,7 @@ malloc (size_t n) assert (n <= _dl_pagesize); page = __mmap (0, _dl_pagesize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0); - assert (page != (caddr_t) -1); + assert (page != MAP_FAILED); if (page != alloc_end) alloc_ptr = page; alloc_end = page + _dl_pagesize; diff --git a/elf/dl-misc.c b/elf/dl-misc.c index d5b1464a6b..0894a7216b 100644 --- a/elf/dl-misc.c +++ b/elf/dl-misc.c @@ -62,7 +62,7 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) | MAP_FILE #endif , fd, 0); - if (result == (void *) -1) + if (result == MAP_FAILED) result = NULL; else *sizep = st.st_size; diff --git a/elf/dl-profile.c b/elf/dl-profile.c index 805624909b..c8028a7c5a 100644 --- a/elf/dl-profile.c +++ b/elf/dl-profile.c @@ -50,29 +50,129 @@ This approach is very different from the normal profiling. We have to use the profiling data in exactly the way they are expected to - be written to disk. */ + be written to disk. But the normal format used by gprof is not usable + to do this. It is optimized for size. It writes the tags as single + bytes but this means that the following 32/64 bit values are + unaligned. + + Therefore we use a new format. This will look like this + + 0 1 2 3 <- byte is 32 bit word + 0000 g m o n + 0004 *version* <- GMON_SHOBJ_VERSION + 0008 00 00 00 00 + 000c 00 00 00 00 + 0010 00 00 00 00 + + 0014 *tag* <- GMON_TAG_TIME_HIST + 0018 ?? ?? ?? ?? + ?? ?? ?? ?? <- 32/64 bit LowPC + 0018+A ?? ?? ?? ?? + ?? ?? ?? ?? <- 32/64 bit HighPC + 0018+2*A *histsize* + 001c+2*A *profrate* + 0020+2*A s e c o + 0024+2*A n d s \0 + 0028+2*A \0 \0 \0 \0 + 002c+2*A \0 \0 \0 + 002f+2*A s + + 0030+2*A ?? ?? ?? ?? <- Count data + ... ... + 0030+2*A+K ?? ?? ?? ?? + + 0030+2*A+K *tag* <- GMON_TAG_CG_ARC + 0034+2*A+K *lastused* + 0038+2*A+K ?? ?? ?? ?? + ?? ?? ?? ?? <- FromPC#1 + 0038+3*A+K ?? ?? ?? ?? + ?? ?? ?? ?? <- ToPC#1 + 0038+4*A+K ?? ?? ?? ?? <- Count#1 + ... ... ... + 0038+(2*(CN-1)+2)*A+(CN-1)*4+K ?? ?? ?? ?? + ?? ?? ?? ?? <- FromPC#CGN + 0038+(2*(CN-1)+3)*A+(CN-1)*4+K ?? ?? ?? ?? + ?? ?? ?? ?? <- ToPC#CGN + 0038+(2*CN+2)*A+(CN-1)*4+K ?? ?? ?? ?? <- Count#CGN + + We put (for now? no basic block information in the file since this would + introduce rase conditions among all the processes who want to write them. + + `K' is the number of count entries which is computed as + + textsize / HISTFRACTION + + `CG' in the above table is the number of call graph arcs. Normally, + the table is sparse and the profiling code writes out only the those + entries which are really used in the program run. But since we must + not extend this table (the profiling file) we'll keep them all here. + So CN can be executed in advance as + + MINARCS <= textsize*(ARCDENSITY/100) <= MAXARCS + + Now the remaining question is: how to build the data structures we can + work with from this data. We need the from set and must associate the + froms with all the associated tos. We will do this by constructing this + data structures at the program start. To do this we'll simply visit all + entries in the call graph table and add it to the appropriate list. */ extern char *_strerror_internal __P ((int, char *buf, size_t)); extern int __profile_frequency __P ((void)); - -static struct gmonparam param; - /* We define a special type to address the elements of the arc table. This is basically the `gmon_cg_arc_record' format but it includes the room for the tag and it uses real types. */ struct here_cg_arc_record { - char tag; - uintptr_t from_pc __attribute__ ((packed)); - uintptr_t self_pc __attribute__ ((packed)); - uint32_t count __attribute__ ((packed)); - }; + uintptr_t from_pc; + uintptr_t self_pc; + uint32_t count; + } __attribute__ ((packed)); static struct here_cg_arc_record *data; +/* This is the number of entry which have been incorporated in the toset. */ +static uint32_t narcs; +/* This is a pointer to the object representing the number of entries + currently in the mmaped file. At no point of time this has to be the + same as NARCS. If it is equal all entries from the file are in our + lists. */ +static uint32_t *narcsp; + +/* Description of the currently profiled object. */ +static long int state; +static volatile uint16_t *kcount; +static size_t kcountsize; + +struct here_tostruct + { + struct here_cg_arc_record volatile *here; + uint16_t link; + }; + +static uint16_t *froms; +static size_t fromssize; + +static struct here_tostruct *tos; +static size_t tossize; +static size_t tolimit; +static size_t toidx; + +static uintptr_t lowpc; +static uintptr_t highpc; +static size_t textsize; +static unsigned int hashfraction; +static unsigned int log_hashfraction; + +/* This is the information about the mmaped memory. */ +static struct gmon_hdr *addr; +static off_t expected_size; + + +/* Set up profiling data to profile object desribed by MAP. The output + file is found (or created) in OUTPUT_DIR. */ void _dl_start_profile (struct link_map *map, const char *output_dir) { @@ -82,11 +182,10 @@ _dl_start_profile (struct link_map *map, const char *output_dir) const ElfW(Phdr) *ph; ElfW(Addr) mapstart = ~((ElfW(Addr)) 0); ElfW(Addr) mapend = 0; - off_t expected_size; struct gmon_hdr gmon_hdr; struct gmon_hist_hdr hist_hdr; - struct gmon_hdr *addr; char *hist; + size_t idx; /* Compute the size of the sections which contain program code. */ for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph) @@ -104,40 +203,41 @@ _dl_start_profile (struct link_map *map, const char *output_dir) /* Now we can compute the size of the profiling data. This is done with the same formulars as in `monstartup' (see gmon.c). */ - param.state = GMON_PROF_OFF; - param.lowpc = mapstart + map->l_addr; - param.highpc = mapend + map->l_addr; - param.textsize = mapend - mapstart; - param.kcountsize = param.textsize / HISTFRACTION; - param.hashfraction = HASHFRACTION; - param.log_hashfraction = -1; + state = GMON_PROF_OFF; + lowpc = ROUNDDOWN (mapstart + map->l_addr, + HISTFRACTION * sizeof(HISTCOUNTER)); + highpc = ROUNDUP (mapend + map->l_addr, + HISTFRACTION * sizeof(HISTCOUNTER)); + textsize = highpc - lowpc; + kcountsize = textsize / HISTFRACTION; + hashfraction = HASHFRACTION; if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) /* If HASHFRACTION is a power of two, mcount can use shifting instead of integer division. Precompute shift amount. */ - param.log_hashfraction = ffs (param.hashfraction - * sizeof (*param.froms)) - 1; - param.fromssize = param.textsize / HASHFRACTION; - param.tolimit = param.textsize * ARCDENSITY / 100; - if (param.tolimit < MINARCS) - param.tolimit = MINARCS; - if (param.tolimit > MAXARCS) - param.tolimit = MAXARCS; - param.tossize = param.tolimit * sizeof (struct tostruct); + log_hashfraction = __builtin_ffs (hashfraction * sizeof (*froms)) - 1; + else + log_hashfraction = -1; + fromssize = textsize / HASHFRACTION; + tolimit = textsize * ARCDENSITY / 100; + if (tolimit < MINARCS) + tolimit = MINARCS; + if (tolimit > MAXARCS) + tolimit = MAXARCS; + tossize = tolimit * sizeof (struct here_tostruct); expected_size = (sizeof (struct gmon_hdr) - + 1 + sizeof (struct gmon_hist_hdr) - + ((1 + sizeof (struct gmon_cg_arc_record)) - * (param.fromssize / sizeof (*param.froms)))); + + 4 + sizeof (struct gmon_hist_hdr) + kcountsize + + 4 + 4 + tossize * sizeof (struct here_cg_arc_record)); /* Create the gmon_hdr we expect or write. */ memset (&gmon_hdr, '\0', sizeof (struct gmon_hdr)); memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie)); - *(int32_t *) gmon_hdr.version = GMON_VERSION; + *(int32_t *) gmon_hdr.version = GMON_SHOBJ_VERSION; /* Create the hist_hdr we expect or write. */ *(char **) hist_hdr.low_pc = (char *) mapstart; *(char **) hist_hdr.high_pc = (char *) mapend; - *(int32_t *) hist_hdr.hist_size = param.kcountsize / sizeof (HISTCOUNTER); + *(int32_t *) hist_hdr.hist_size = kcountsize / sizeof (HISTCOUNTER); *(int32_t *) hist_hdr.prof_rate = __profile_frequency (); strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen)); hist_hdr.dimen_abbrev = 's'; @@ -193,15 +293,19 @@ _dl_start_profile (struct link_map *map, const char *output_dir) { __close (fd); wrong_format: + + if (addr != NULL) + __munmap ((void *) addr, expected_size); + _dl_sysdep_error (filename, ": file is no correct profile data file for `", _dl_profile, "'\n", NULL); return; } - addr = (void *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE, - MAP_SHARED|MAP_FILE, fd, 0); - if (addr == (void *) -1) + addr = (struct gmon_hdr *) __mmap (NULL, expected_size, PROT_READ|PROT_WRITE, + MAP_SHARED|MAP_FILE, fd, 0); + if (addr == (struct gmon_hdr *) MAP_FAILED) { char buf[400]; int errnum = errno; @@ -217,54 +321,97 @@ _dl_start_profile (struct link_map *map, const char *output_dir) /* Pointer to data after the header. */ hist = (char *) (addr + 1); + kcount = (uint16_t *) ((char *) hist + sizeof (uint32_t) + + sizeof (struct gmon_hist_hdr)); /* Compute pointer to array of the arc information. */ - data = (struct here_cg_arc_record *) (hist + 1 - + sizeof (struct gmon_hist_hdr)); + data = (struct here_cg_arc_record *) ((char *) kcount + kcountsize + + 2 * sizeof (uint32_t)); + narcsp = (uint32_t *) (hist + sizeof (uint32_t) + + sizeof (struct gmon_hist_hdr) + sizeof (uint32_t)); if (st.st_size == 0) { /* Create the signature. */ - size_t cnt; - memcpy (addr, &gmon_hdr, sizeof (struct gmon_hdr)); - *hist = GMON_TAG_TIME_HIST; - memcpy (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)); + *(uint32_t *) hist = GMON_TAG_TIME_HIST; + memcpy (hist + sizeof (uint32_t), &hist_hdr, + sizeof (struct gmon_hist_hdr)); - for (cnt = 0; cnt < param.fromssize / sizeof (*param.froms); ++cnt) - data[cnt].tag = GMON_TAG_CG_ARC; + *(uint32_t *) (hist + sizeof (uint32_t) + sizeof (struct gmon_hist_hdr) + + kcountsize) = GMON_TAG_CG_ARC; } else { /* Test the signature in the file. */ if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0 - || *hist != GMON_TAG_TIME_HIST - || memcmp (hist + 1, &hist_hdr, sizeof (struct gmon_hist_hdr)) != 0) + || *(uint32_t *) hist != GMON_TAG_TIME_HIST + || memcmp (hist + sizeof (uint32_t), &hist_hdr, + sizeof (struct gmon_hist_hdr)) != 0 + || (*(uint32_t *) (hist + sizeof (uint32_t) + + sizeof (struct gmon_hist_hdr) + kcountsize) + != GMON_TAG_CG_ARC)) goto wrong_format; } + /* Allocate memory for the froms data and the pointer to the tos records. */ + froms = (uint16_t *) calloc (fromssize + tossize, 1); + if (froms == NULL) + { + __munmap ((void *) addr, expected_size); + _dl_sysdep_fatal ("Out of memory while initializing profiler", NULL); + /* NOTREACHED */ + } + + tos = (struct here_tostruct *) ((char *) froms + fromssize); + toidx = 0; + + /* Now we have to process all the arc count entries. BTW: it is + not critical whether the *NARCSP value changes meanwhile. Before + we enter a new entry in to toset we will check that everything is + available in TOS. This happens in _dl_mcount. + + Loading the entries in reverse order should help to get the most + frequently used entries at the front of the list. */ + for (idx = narcs = *narcsp; idx > 0; ) + { + size_t from_index; + size_t newtoidx; + --idx; + from_index = ((data[idx].from_pc - lowpc) + / (hashfraction * sizeof (*froms))); + newtoidx = toidx++; + tos[newtoidx].here = &data[idx]; + tos[newtoidx].link = froms[from_index]; + froms[from_index] = newtoidx; + } + /* Turn on profiling. */ - param.state = GMON_PROF_ON; + state = GMON_PROF_ON; } void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc) { - if (param.state != GMON_PROF_ON) + if (state != GMON_PROF_ON) return; - param.state = GMON_PROF_BUSY; + state = GMON_PROF_BUSY; /* Compute relative addresses. The shared object can be loaded at any address. The value of frompc could be anything. We cannot restrict it in any way, just set to a fixed value (0) in case it is outside the allowed range. These calls show up as calls from <external> in the gprof output. */ - frompc -= param.lowpc; - if (frompc >= param.textsize) + frompc -= lowpc; + if (frompc >= textsize) frompc = 0; - selfpc -= param.lowpc; + selfpc -= lowpc; + if (selfpc >= textsize) + goto done; + - param.state = GMON_PROF_ON; + done: + state = GMON_PROF_ON; } diff --git a/gmon/gmon.c b/gmon/gmon.c index 72b36f99c3..300ca30a09 100644 --- a/gmon/gmon.c +++ b/gmon/gmon.c @@ -126,13 +126,12 @@ __monstartup (lowpc, highpc) p->tolimit = MAXARCS; p->tossize = p->tolimit * sizeof(struct tostruct); - cp = malloc (p->kcountsize + p->fromssize + p->tossize); + cp = calloc (p->kcountsize + p->fromssize + p->tossize, 1); if (! cp) { ERR(_("monstartup: out of memory\n")); return; } - memset (cp, '\0', p->kcountsize + p->fromssize + p->tossize); p->tos = (struct tostruct *)cp; cp += p->tossize; p->kcount = (u_short *)cp; @@ -296,13 +295,12 @@ write_bb_counts (fd) } -void -_mcleanup () +static void +write_gmon (void) { struct gmon_hdr ghdr __attribute__ ((aligned (__alignof__ (int)))); int fd; - __moncontrol (0); fd = __open ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY, 0666); if (fd < 0) { @@ -328,8 +326,29 @@ _mcleanup () /* write basic-block execution counts: */ write_bb_counts (fd); + __close (fd); +} + + +void +__write_profiling (void) +{ + int save = _gmonparam.state; + _gmonparam.state = GMON_PROF_OFF; + if (save == GMON_PROF_ON) + write_gmon (); + _gmonparam.state = save; +} +weak_alias (__write_profiling, write_profiling) + + +void +_mcleanup (void) +{ + __moncontrol (0); + + write_gmon (); + /* free the memory. */ free (_gmonparam.tos); - - __close (fd); } diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h index 8368ca1ce3..930729e7fc 100644 --- a/gmon/sys/gmon.h +++ b/gmon/sys/gmon.h @@ -175,6 +175,10 @@ extern void monstartup __P ((u_long __lowpc, u_long __highpc)); /* Clean up profiling and write out gmon.out. */ extern void _mcleanup __P ((void)); +/* Write current profiling data to file. */ +extern void __write_profiling __P ((void)); +extern void write_profiling __P ((void)); + __END_DECLS #endif /* sys/gmon.h */ diff --git a/gmon/sys/gmon_out.h b/gmon/sys/gmon_out.h index c84f945ce8..83dd1ec83e 100644 --- a/gmon/sys/gmon_out.h +++ b/gmon/sys/gmon_out.h @@ -33,6 +33,9 @@ #define GMON_MAGIC "gmon" /* magic cookie */ #define GMON_VERSION 1 /* version number */ +/* For profiling shared object we need a new format. */ +#define GMON_SHOBJ_VERSION 0x1ffff + __BEGIN_DECLS /* diff --git a/inet/Makefile b/inet/Makefile index 9a70c316b5..18a990ef71 100644 --- a/inet/Makefile +++ b/inet/Makefile @@ -46,7 +46,7 @@ routines := htonl htons \ getaliasent_r getaliasent getaliasname getaliasname_r \ in6_addr getnameinfo if_index -tests := htontest test_ifindex +tests := htontest test_ifindex tst-ntoa # No warnings about losing BSD code. CFLAGS-rcmd.c = -w diff --git a/inet/getnameinfo.c b/inet/getnameinfo.c index e6f4cbfc94..f090f0b32e 100644 --- a/inet/getnameinfo.c +++ b/inet/getnameinfo.c @@ -80,7 +80,7 @@ struct hostent *_addr2hostname_hosts (const char *, int, int); static const char * nrl_domainname (void) { - static const char *domain = NULL; + static char *domain = NULL; static int first = 1; if (first) diff --git a/inet/inet_ntoa.c b/inet/inet_ntoa.c index 5dfec626a0..fc2c3dd9b8 100644 --- a/inet/inet_ntoa.c +++ b/inet/inet_ntoa.c @@ -43,7 +43,7 @@ static void free_key_mem (void *mem); char * inet_ntoa (struct in_addr in) { - __libc_once_define (once); + __libc_once_define (static, once); char *buffer; unsigned char *bytes; @@ -51,20 +51,22 @@ inet_ntoa (struct in_addr in) __libc_once (once, init); if (static_buf != NULL) - return static_buf; - - /* We don't use the static buffer and so we have a key. Use it to - get the thread-specific buffer. */ - buffer = __libc_getspecific (key); - if (buffer == NULL) + buffer = static_buf; + else { - /* No buffer allocated so far. */ - buffer = malloc (18); + /* We don't use the static buffer and so we have a key. Use it + to get the thread-specific buffer. */ + buffer = __libc_getspecific (key); if (buffer == NULL) - /* No more memory available. We use the static buffer. */ - buffer = local_buf; - else - __libc_setspecific (key, buffer); + { + /* No buffer allocated so far. */ + buffer = malloc (18); + if (buffer == NULL) + /* No more memory available. We use the static buffer. */ + buffer = local_buf; + else + __libc_setspecific (key, buffer); + } } bytes = (unsigned char *) ∈ @@ -91,4 +93,5 @@ static void free_key_mem (void *mem) { free (mem); + __libc_setspecific (key, NULL); } diff --git a/inet/tst-ntoa.c b/inet/tst-ntoa.c new file mode 100644 index 0000000000..9be91eb511 --- /dev/null +++ b/inet/tst-ntoa.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> +#include <netinet/in.h> + + +static int +test (unsigned int inaddr, const char *expected) +{ + struct in_addr addr; + char *res; + int fail; + + addr.s_addr = htonl (inaddr); + res = inet_ntoa (addr); + fail = strcmp (res, expected); + + printf ("%#010x -> \"%s\" -> %s%s\n", inaddr, res, + fail ? "fail, expected" : "ok", fail ? expected : ""); + + return fail; +} + + +int +main (void) +{ + int result = 0; + + result |= test (INADDR_LOOPBACK, "127.0.0.1"); + result |= test (INADDR_BROADCAST, "255.255.255.255"); + result |= test (INADDR_ANY, "0.0.0.0"); + result |= test (0xc0060746, "192.6.7.70"); + + return result; +} @@ -101,8 +101,14 @@ static int object_compare (const void *p1, const void *p2) { /* We don't need a sophisticated and useful comparison. We are only - interested in equality. */ - return memcmp (p1, p2, sizeof (struct known_object)); + interested in equality. However, we must be careful not to + accidentally compare `holes' in the structure. */ + const struct known_object *kp1 = p1, *kp2 = p2; + int cmp1; + cmp1 = memcmp(&kp1->dev, &kp2->dev, sizeof(kp1->dev)); + if (cmp1 != 0) + return cmp1; + return memcmp (&kp1->ino, &kp2->ino, sizeof (kp1->ino)); } @@ -18,7 +18,9 @@ GLIBC_2.0 { # functions with special/multiple interfaces __sigsetjmp; _setjmp; __sigaddset; __sigdelset; __sigismember; - __sysv_signal; __bsd_getpgrp; _longjmp; + __sysv_signal; __bsd_getpgrp; _longjmp; _mcount; + __divqu; __remqu; __divqs; __remqs; __divlu; __remlu; __divls; + __remls; # functions which have an additional interface since they are # are cancelable. @@ -179,7 +181,8 @@ GLIBC_2.0 { get_kernel_syms; get_myaddress; get_nprocs; get_nprocs_conf; get_phys_pages; getaddrinfo; getaliasbyname; getaliasbyname_r; getaliasent; getaliasent_r; getc; getc_unlocked; getchar; - getchar_unlocked; getcwd; getdate; getdate_r; getdelim; getdirentries; + getchar_unlocked; getcontext; + getcwd; getdate; getdate_r; getdelim; getdirentries; getdomainname; getdtablesize; getegid; getenv; geteuid; getfsent; getfsfile; getfsspec; getgid; getgrent; getgrent_r; getgrgid; getgrgid_r; getgrnam; getgrnam_r; getgroups; gethostbyaddr; @@ -193,6 +196,7 @@ GLIBC_2.0 { getprotobyname; getprotobyname_r; getprotobynumber; getprotobynumber_r; getprotoent; getprotoent_r; getpublickey; getpw; getpwent; getpwent_r; getpwnam; getpwnam_r; getpwuid; getpwuid_r; + getresgid; getresuid; getrlimit; getrpcbyname; getrpcbyname_r; getrpcbynumber; getrpcbynumber_r; getrpcent; getrpcent_r; getrpcport; getrusage; gets; getsecretkey; getservbyname; getservbyname_r; getservbyport; @@ -200,14 +204,15 @@ GLIBC_2.0 { getsockopt; getspent; getspent_r; getspnam; getspnam_r; getsubopt; gettext; gettimeofday; getttyent; getttynam; getuid; getusershell; getutent; getutent_r; getutid; getutid_r; getutline; getutline_r; - getutxent; getw; getwd; glob; glob_pattern_p; globfree; gmtime; - gmtime_r; group_member; gsignal; gtty; + getutxent; getutxid; getutxline; getw; getwd; glob; glob_pattern_p; + globfree; gmtime; gmtime_r; group_member; gsignal; gtty; # h* hasmntopt; hcreate; hcreate_r; hdestroy; hdestroy_r; herror; host2netname; hsearch; hsearch_r; hstrerror; htonl; htons; # i* + ieee_get_fp_control; ieee_set_fp_control; if_freenameindex; if_indextoname; if_nameindex; if_nametoindex; index; inet6_isipv4mapped; inet_addr; inet_aton; inet_lnaof; inet_makeaddr; inet_netof; inet_network; inet_nsap_addr; inet_nsap_ntoa; inet_ntoa; @@ -254,7 +259,7 @@ GLIBC_2.0 { msgsnd; msync; mtrace; munlock; munlockall; munmap; muntrace; # n* - nanosleep; netname2host; netname2user; nftw; nice; nl_langinfo; + nanosleep; netname2host; netname2user; nftw; nfsservctl; nice; nl_langinfo; nrand48; nrand48_r; ntohl; ntohs; # o* @@ -262,7 +267,8 @@ GLIBC_2.0 { open_memstream; opendir; openlog; # p* - parse_printf_format; passwd2des; pathconf; pause; pclose; perror; + parse_printf_format; passwd2des; pathconf; pause; pciconfig_read; + pciconfig_write; pclose; perror; personality; pipe; pmap_getmaps; pmap_getport; pmap_rmtcall; pmap_set; pmap_unset; poll; popen; printf; printf_size; printf_size_info; profil; profil_counter; pselect; psignal; @@ -287,7 +293,7 @@ GLIBC_2.0 { pututxline; putw; pvalloc; # q* - qecvt; qecvt_r; qfcvt; qfcvt_r; qgcvt; qsort; quotactl; + qecvt; qecvt_r; query_module; qfcvt; qfcvt_r; qgcvt; qsort; quotactl; # r* raise; rand; rand_r; random; random_r; rcmd; @@ -310,11 +316,13 @@ GLIBC_2.0 { seed48; seed48_r; seekdir; select; semctl; semget; semop; send; sendmsg; sendto; setaliasent; setbuf; - setbuffer; setdomainname; setegid; setenv; seteuid; setfsent; + setbuffer; setcontext; + setdomainname; setegid; setenv; seteuid; setfsent; setfsgid; setfsuid; setgid; setgrent; setgroups; sethostent; sethostid; sethostname; setitimer; setjmp; setlinebuf; setlocale; setlogin; setlogmask; setmntent; setnetent; setnetgrent; setpgid; - setpgrp; setpriority; setprotoent; setpwent; setregid; setreuid; + setpgrp; setpriority; setprotoent; setpwent; setregid; setresgid; + setresuid; setreuid; setrlimit; setrpcent; setservent; setsid; setsockopt; setspent; setstate; setstate_r; settimeofday; setttyent; setuid; setusershell; setutent; setutxent; setvbuf; sgetspent; sgetspent_r; shmat; shmctl; @@ -342,7 +350,7 @@ GLIBC_2.0 { svcudp_bufcreate; svcudp_create; svcudp_enablecache; swab; swapoff; swapon; symlink; sync; - syscall; sysconf; sysctl; sysinfo; syslog; + syscall; sysconf; sysctl; sysinfo; syslog; sysmips; system; # t* @@ -389,7 +397,7 @@ GLIBC_2.0 { xdr_keybuf; xdr_keystatus; xdr_long; xdr_netnamestr; xdr_netobj; xdr_opaque; xdr_opaque_auth; xdr_pmap; xdr_pmaplist; xdr_pointer; xdr_reference; xdr_rejected_reply; xdr_replymsg; xdr_rmtcall_args; - xdr_rmtcallres; xdr_short; xdr_string; xdr_u_char; xdr_u_int; + xdr_rmtcallres; xdr_short; xdr_sizeof; xdr_string; xdr_u_char; xdr_u_int; xdr_u_long; xdr_u_short; xdr_union; xdr_unixcred; xdr_vector; xdr_void; xdr_wrapstring; xdrmem_create; xdrrec_create; xdrrec_endofrecord; xdrrec_eof; xdrrec_skiprecord; xdrstdio_create; diff --git a/locale/loadlocale.c b/locale/loadlocale.c index 544c09ad88..edbe891f84 100644 --- a/locale/loadlocale.c +++ b/locale/loadlocale.c @@ -127,7 +127,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category) #endif filedata = (void *) __mmap ((caddr_t) 0, st.st_size, PROT_READ, MAP_FILE|MAP_COPY|MAP_INHERIT, fd, 0); - if (filedata == (void *) -1) + if (filedata == MAP_FAILED) { if (errno == ENOSYS) { diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c index 206246944f..6290274a72 100644 --- a/locale/programs/localedef.c +++ b/locale/programs/localedef.c @@ -279,7 +279,7 @@ cannot `stat' locale file `%s'"), localedef->categories[cat].generic = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (localedef->categories[cat].generic == (void *) -1) + if (localedef->categories[cat].generic == MAP_FAILED) { size_t left = st.st_size; void *read_ptr; diff --git a/login/getutent_r.c b/login/getutent_r.c index 98c5469463..96c458f3a3 100644 --- a/login/getutent_r.c +++ b/login/getutent_r.c @@ -18,20 +18,20 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include <assert.h> #include <bits/libc-lock.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> #include <utmp.h> #include "utmp-private.h" -/* The various backends we have. */ +/* Functions defined here. */ +static int setutent_unknown (void); static int getutent_r_unknown (struct utmp *buffer, struct utmp **result); +static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer, + struct utmp **result); +static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer, + struct utmp **result); static struct utmp *pututline_unknown (const struct utmp *data); -static int setutent_unknown (void); static void endutent_unknown (void); /* Initial Jump table. */ @@ -39,8 +39,8 @@ struct utfuncs __libc_utmp_unknown_functions = { setutent_unknown, getutent_r_unknown, - NULL, - NULL, + getutid_r_unknown, + getutline_r_unknown, pututline_unknown, endutent_unknown, NULL @@ -53,58 +53,99 @@ struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions; __libc_lock_define_initialized (, __libc_utmp_lock) -void -__setutent (void) +static int +setutent_unknown (void) { - __libc_lock_lock (__libc_utmp_lock); + int result; - (*__libc_utmp_jump_table->setutent) (); + /* See whether utmpd is running. */ + result = (*__libc_utmp_daemon_functions.setutent) (); + if (result) + __libc_utmp_jump_table = &__libc_utmp_daemon_functions; + else + { + result = (*__libc_utmp_file_functions.setutent) (); + if (result) + __libc_utmp_jump_table = &__libc_utmp_file_functions; + } - __libc_lock_unlock (__libc_utmp_lock); + return result; } -weak_alias (__setutent, setutent) -weak_alias (__setutent, setutxent) -void -__endutent (void) +static int +getutent_r_unknown (struct utmp *buffer, struct utmp **result) { - __libc_lock_lock (__libc_utmp_lock); + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->getutent_r) (buffer, result); - (*__libc_utmp_jump_table->endutent) (); + /* Not available. */ + *result = NULL; + return -1; +} - __libc_lock_unlock (__libc_utmp_lock); + +static int +getutid_r_unknown (const struct utmp *id, struct utmp *buffer, + struct utmp **result) +{ + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); + + /* Not available. */ + *result = NULL; + return -1; } -weak_alias (__endutent, endutent) -weak_alias (__endutent, endutxent) static int -setutent_unknown (void) +getutline_r_unknown (const struct utmp *line, struct utmp *buffer, + struct utmp **result) { - int result; + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); - /* See whether utmpd is running. */ - result = (*__libc_utmp_daemon_functions.setutent) (); - if (result) - __libc_utmp_jump_table = &__libc_utmp_daemon_functions; - else - { - result = (*__libc_utmp_file_functions.setutent) (); - __libc_utmp_jump_table = &__libc_utmp_file_functions; - } + /* Not available. */ + *result = NULL; + return -1; +} - return result; + +static struct utmp * +pututline_unknown (const struct utmp *data) +{ + /* The backend was not yet initialized. */ + if (setutent_unknown ()) + return (*__libc_utmp_jump_table->pututline) (data); + + /* Not available. */ + return NULL; } static void endutent_unknown (void) { - /* Huh, how do we came here? Nothing to do. */ + /* Nothing to do. */ } +void +__setutent (void) +{ + __libc_lock_lock (__libc_utmp_lock); + + (*__libc_utmp_jump_table->setutent) (); + + __libc_lock_unlock (__libc_utmp_lock); +} +weak_alias (__setutent, setutent) +weak_alias (__setutent, setutxent) + + int __getutent_r (struct utmp *buffer, struct utmp **result) { @@ -121,16 +162,6 @@ __getutent_r (struct utmp *buffer, struct utmp **result) weak_alias (__getutent_r, getutent_r) -static int -getutent_r_unknown (struct utmp *buffer, struct utmp **result) -{ - /* It is not yet initialized. */ - __setutent (); - - return (*__libc_utmp_jump_table->getutent_r) (buffer, result); -} - - struct utmp * __pututline (const struct utmp *data) { @@ -148,11 +179,15 @@ weak_alias (__pututline, pututline) weak_alias (__pututline, pututxline) -static struct utmp * -pututline_unknown (const struct utmp *data) +void +__endutent (void) { - /* It is not yet initialized. */ - __setutent (); + __libc_lock_lock (__libc_utmp_lock); - return (*__libc_utmp_jump_table->pututline) (data); + (*__libc_utmp_jump_table->endutent) (); + __libc_utmp_jump_table = &__libc_utmp_unknown_functions; + + __libc_lock_unlock (__libc_utmp_lock); } +weak_alias (__endutent, endutent) +weak_alias (__endutent, endutxent) diff --git a/login/getutid_r.c b/login/getutid_r.c index 90b75b8c01..3d5d63de29 100644 --- a/login/getutid_r.c +++ b/login/getutid_r.c @@ -20,8 +20,6 @@ #include <errno.h> #include <bits/libc-lock.h> -#include <string.h> -#include <unistd.h> #include <utmp.h> #include "utmp-private.h" @@ -38,7 +36,7 @@ int __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) { #if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0) - int retval = -1; + int retval; /* Test whether ID has any of the legal types. */ if (id->ut_type != RUN_LVL && id->ut_type != BOOT_TIME @@ -54,11 +52,7 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) __libc_lock_lock (__libc_utmp_lock); - /* Not yet initialized. */ - if ((*__libc_utmp_jump_table->setutent) ()) - retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); - else - *result = NULL; + retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); __libc_lock_unlock (__libc_utmp_lock); diff --git a/login/getutline.c b/login/getutline.c index 16a02f6e89..1e1ecb1ce3 100644 --- a/login/getutline.c +++ b/login/getutline.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -25,7 +25,7 @@ static struct utmp buffer; struct utmp * -getutline (const struct utmp *line) +__getutline (const struct utmp *line) { struct utmp *result; @@ -34,3 +34,5 @@ getutline (const struct utmp *line) return result; } +weak_alias (__getutline, getutline) +weak_alias (__getutline, getutxline) diff --git a/login/getutline_r.c b/login/getutline_r.c index a1bdc0bc4e..57335941c1 100644 --- a/login/getutline_r.c +++ b/login/getutline_r.c @@ -20,8 +20,6 @@ #include <errno.h> #include <bits/libc-lock.h> -#include <string.h> -#include <unistd.h> #include <utmp.h> #include "utmp-private.h" @@ -38,15 +36,11 @@ int __getutline_r (const struct utmp *line, struct utmp *buffer, struct utmp **result) { - int retval = -1; + int retval; __libc_lock_lock (__libc_utmp_lock); - /* Not yet initialized. */ - if ((*__libc_utmp_jump_table->setutent) ()) - retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); - else - *result = NULL; + retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); __libc_lock_unlock (__libc_utmp_lock); diff --git a/login/logout.c b/login/logout.c index 8a406c01ca..9a87fe4e3f 100644 --- a/login/logout.c +++ b/login/logout.c @@ -30,7 +30,7 @@ logout (const char *line) int result = 0; /* Tell that we want to use the UTMP file. */ - if (utmpname (_PATH_UTMP) == 0) + if (utmpname (_PATH_UTMP) == -1) return 0; /* Open UTMP file. */ diff --git a/login/programs/database.c b/login/programs/database.c index 00d573f336..7044cd8d87 100644 --- a/login/programs/database.c +++ b/login/programs/database.c @@ -88,7 +88,7 @@ open_database (const char *file, const char *old_file) error (0, errno, "%s", old_file); goto return_error; } - + database->old_file = strdup (old_file); if (database->old_file == NULL) { @@ -100,12 +100,12 @@ open_database (const char *file, const char *old_file) /* Initialize database. */ if (initialize_database (database) < 0) goto return_error; - + return database; return_error: close_database (database); - + return NULL; } @@ -121,16 +121,16 @@ synchronize_database (utmp_database *database) { time_t curtime; time_t mtime; - + curtime = time (NULL); - + if (get_mtime (database->old_fd, &mtime) < 0) { error (0, errno, _("%s: cannot get modification time"), database->old_file); return -1; } - + if (mtime >= database->mtime) { int position = 0; @@ -141,7 +141,7 @@ synchronize_database (utmp_database *database) { if (read_old_entry (database, position, &old_entry) < 0) break; - + if (read_entry (database, position, &entry) < 0 || !compare_entry (&old_entry, &entry)) { @@ -157,7 +157,7 @@ synchronize_database (utmp_database *database) database->mtime = curtime; } - + } return 0; @@ -175,7 +175,7 @@ close_database (utmp_database *database) if (database->old_fd >= 0) close (database->old_fd); - + /* Free allocated memory. */ if (database->file) free (database->file); @@ -200,7 +200,7 @@ read_entry (utmp_database *database, int position, struct utmp *entry) nbytes = read (database->fd, entry, sizeof (struct utmp)); if (nbytes != sizeof (struct utmp)) return -1; - + return 0; } @@ -221,7 +221,7 @@ write_entry (utmp_database *database, int position, fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fcntl (database->fd, F_SETLKW, &fl); - + offset = position * sizeof (struct utmp); if (lseek (database->fd, offset, SEEK_SET) < 0) goto fail; @@ -259,7 +259,7 @@ append_entry (utmp_database *database, const struct utmp *entry) fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fcntl (database->fd, F_SETLKW, &fl); - + offset = lseek (database->fd, 0, SEEK_END); if (offset % sizeof (struct utmp) != 0) { @@ -278,7 +278,7 @@ append_entry (utmp_database *database, const struct utmp *entry) } result = offset / sizeof (struct utmp); - + fail: /* And unlock the file. */ fl.l_type = F_UNLCK; @@ -303,7 +303,7 @@ read_old_entry (utmp_database *database, int position, nbytes = read (database->old_fd, &old_entry, sizeof (struct xtmp)); if (nbytes != sizeof (struct xtmp)) return -1; - + xtmp_to_utmp (&old_entry, entry); return 0; } @@ -318,7 +318,7 @@ write_old_entry (utmp_database *database, int position, off_t offset; utmp_to_xtmp (entry, &old_entry); - + offset = position * sizeof (struct xtmp); if (lseek (database->old_fd, offset, SEEK_SET) < 0) return -1; @@ -337,7 +337,7 @@ initialize_database (utmp_database *database) { struct utmp entry; int position = 0; - + assert (database); /* Check if there is a file in the old format to read. */ @@ -395,6 +395,7 @@ initialize_database (utmp_database *database) } +#if _HAVE_UT_TYPE - 0 static int store_state_entry (utmp_database *database, int old_position, const struct utmp *old_entry) @@ -413,7 +414,7 @@ store_state_entry (utmp_database *database, int old_position, /* Read the next entry. */ if (read_entry (database, new_position, &new_entry) < 0) break; - + if (old_entry->ut_type == new_entry.ut_type) { found = 1; @@ -428,16 +429,23 @@ store_state_entry (utmp_database *database, int old_position, { const struct utmp *entry; - if (old_entry->ut_time > new_entry.ut_time) + if ( +#if _HAVE_UT_TV - 0 + old_entry->ut_tv.tv_sec > new_entry.ut_tv.tv_sec +#else + old_entry->ut_time > new_entry.ut_time +#endif + ) entry = old_entry; else entry = &new_entry; - + return replace_entry (database, old_position, new_position, entry); } return store_entry (database, old_position, old_entry); } +#endif static int @@ -468,11 +476,17 @@ store_process_entry (utmp_database *database, int old_position, { const struct utmp *entry; - if (old_entry->ut_time > new_entry.ut_time) + if ( +#if _HAVE_UT_TV - 0 + old_entry->ut_tv.tv_sec > new_entry.ut_tv.tv_sec +#else + old_entry->ut_time > new_entry.ut_time +#endif + ) entry = old_entry; else entry = &new_entry; - + return replace_entry (database, old_position, new_position, entry); } @@ -485,7 +499,7 @@ replace_entry (utmp_database *database, int old_position, int new_position, const struct utmp *entry) { struct utmp tmp; - + if (read_entry (database, old_position, &tmp) < 0 || write_entry (database, old_position, entry) < 0 || write_entry (database, new_position, &tmp) < 0) @@ -518,7 +532,7 @@ static int get_mtime (int filedes, time_t *timer) { struct stat st; - + if (fstat (filedes, &st) < 0) return -1; diff --git a/login/programs/utmpdump.c b/login/programs/utmpdump.c index e1422b5028..7be404ce24 100644 --- a/login/programs/utmpdump.c +++ b/login/programs/utmpdump.c @@ -29,9 +29,15 @@ void print_entry (struct utmp *up) { +#if _HAVE_UT_TV - 0 printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-15.15s] [%ld]\n", up->ut_type, up->ut_pid, up->ut_id, up->ut_user, - up->ut_line, 4 + ctime (&up->ut_time), up->ut_tv.tv_usec); + up->ut_line, 4 + ctime (&up->ut_tv.tv_sec), up->ut_tv.tv_usec); +#else + printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-15.15s]\n", + up->ut_type, up->ut_pid, up->ut_id, up->ut_user, + up->ut_line, 4 + ctime (&up->ut_time)); +#endif } int @@ -41,13 +47,13 @@ main (int argc, char *argv[]) if (argc > 1) utmpname (argv[1]); - + setutent (); while ((up = getutent ())) print_entry (up); endutent (); - + return EXIT_SUCCESS; } diff --git a/login/programs/xtmp.c b/login/programs/xtmp.c index d2d5feee3b..105145b01d 100644 --- a/login/programs/xtmp.c +++ b/login/programs/xtmp.c @@ -42,7 +42,11 @@ xtmp_to_utmp (const struct xtmp *xtmp, struct utmp *utmp) #if _HAVE_XT_ID - 0 strncpy (utmp->ut_id, xtmp->xt_id, sizeof xtmp->xt_id); #endif +#if _HAVE_UT_TV - 0 + utmp->ut_tv.tv_sec = xtmp->xt_time; +#else utmp->ut_time = xtmp->xt_time; +#endif strncpy (utmp->ut_user, xtmp->xt_user, XT_NAMESIZE); #if _HAVE_XT_HOST - 0 strncpy (utmp->ut_host, xtmp->xt_host, XT_HOSTSIZE); @@ -66,7 +70,11 @@ utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp) #if _HAVE_XT_ID - 0 strncpy (xtmp->xt_id, utmp->ut_id, sizeof xtmp->xt_id); #endif +#if _HAVE_UT_TV - 0 + xtmp->xt_time = utmp->ut_tv.tv_sec; +#else xtmp->xt_time = utmp->ut_time; +#endif strncpy (xtmp->xt_user, utmp->ut_user, XT_NAMESIZE); #if _HAVE_XT_HOST - 0 strncpy (xtmp->xt_host, utmp->ut_host, XT_HOSTSIZE); @@ -79,24 +87,28 @@ utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp) function returns 1 if the information that is in both old and new style entries is identical. Otherwise this function returns 0. */ int -compare_entry (const struct utmp *xtmp, const struct utmp *utmp) +compare_entry (const struct xtmp *xtmp, const struct utmp *utmp) { return ( #if _HAVE_XT_TYPE - 0 - xtmp->ut_type == utmp->ut_type + xtmp->xt_type == utmp->ut_type #endif #if _HAVE_XT_PID - 0 - && xtmp->ut_pid == utmp->ut_pid + && xtmp->xt_pid == utmp->ut_pid #endif - && !strncmp (xtmp->ut_line, utmp->ut_line, XT_LINESIZE - 1) + && !strncmp (xtmp->xt_line, utmp->ut_line, XT_LINESIZE - 1) #if _HAVE_XT_ID - 0 - && !strncmp (xtmp->ut_id, utmp->ut_id, sizeof utmp->ut_id) + && !strncmp (xtmp->xt_id, utmp->ut_id, sizeof utmp->ut_id) +#endif +#if _HAVE_UT_TV - 0 + && xtmp->xt_time == utmp->ut_tv.tv_sec +#else + && xtmp->xt_time == utmp->ut_time #endif - && xtmp->ut_time == utmp->ut_time - && !strncmp (xtmp->ut_user, utmp->ut_user, XT_NAMESIZE) + && !strncmp (xtmp->xt_user, utmp->ut_user, XT_NAMESIZE) #if _HAVE_XT_HOST - 0 - && !strncmp (xtmp->ut_host, utmp->ut_host, XT_HOSTSIZE - 1) + && !strncmp (xtmp->xt_host, utmp->ut_host, XT_HOSTSIZE - 1) #endif - && xtmp->ut_addr == utmp->ut_addr); + && xtmp->xt_addr == utmp->ut_addr); } diff --git a/login/programs/xtmp.h b/login/programs/xtmp.h index 8fa982ee4f..508993248a 100644 --- a/login/programs/xtmp.h +++ b/login/programs/xtmp.h @@ -50,7 +50,7 @@ struct xtmp extern void xtmp_to_utmp (const struct xtmp *xtmp, struct utmp *utmp); extern void utmp_to_xtmp (const struct utmp *utmp, struct xtmp *xtmp); -extern int compare_entry (const struct utmp *xtmp, +extern int compare_entry (const struct xtmp *xtmp, const struct utmp *utmp); #endif /* xtmp.h */ diff --git a/login/utmp_daemon.c b/login/utmp_daemon.c index 5907e06e2d..db3c90e428 100644 --- a/login/utmp_daemon.c +++ b/login/utmp_daemon.c @@ -17,8 +17,8 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <assert.h> #include <errno.h> -#include <limits.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> @@ -31,7 +31,7 @@ /* Descriptor for the socket. */ -static int daemon_sock = INT_MIN; +static int daemon_sock = -1; /* Functions defined here. */ @@ -59,12 +59,13 @@ struct utfuncs __libc_utmp_daemon_functions = static int do_setutent (int sock); static int do_getutent (int sock, struct utmp *buffer); -static int do_endutent (int sock); -static int do_getutline (int sock, const struct utmp *line, - struct utmp *buffer); static int do_getutid (int sock, const struct utmp *id, struct utmp *buffer); static int do_pututline (int sock, const struct utmp *utmp); +static int do_getutline (int sock, const struct utmp *line, + struct utmp *buffer); +static int do_pututline (int sock, const struct utmp *utmp); +static int do_endutent (int sock); static int do_updwtmp (int sock, const char *file, const struct utmp *utmp); @@ -79,7 +80,7 @@ setutent_daemon (void) if (access (_PATH_UTMPD_RW, F_OK) == -1 && access (_PATH_UTMPD_RO, F_OK) == -1) return 0; - + if (daemon_sock < 0) { daemon_sock = open_socket (_PATH_UTMPD_RW); @@ -100,33 +101,10 @@ setutent_daemon (void) } -static void -endutent_daemon (void) -{ - if (daemon_sock >= 0) - { - /* Send request to the daemon. */ - do_endutent (daemon_sock); - close (daemon_sock); - } - - daemon_sock = INT_MIN; -} - - static int getutent_r_daemon (struct utmp *buffer, struct utmp **result) { - /* Open connection if not already done. */ - if (daemon_sock == INT_MIN) - setutent_daemon (); - - if (daemon_sock < 0) - { - /* Not available. */ - *result = NULL; - return -1; - } + assert (daemon_sock >= 0); /* Send request to the daemon. */ if (do_getutent (daemon_sock, buffer) < 0) @@ -141,20 +119,16 @@ getutent_r_daemon (struct utmp *buffer, struct utmp **result) static int -getutline_r_daemon (const struct utmp *line, struct utmp *buffer, - struct utmp **result) +getutid_r_daemon (const struct utmp *id, struct utmp *buffer, + struct utmp **result) { - if (daemon_sock < 0) - { - *result = NULL; - return -1; - } + assert (daemon_sock >= 0); /* Send request to the daemon. */ - if (do_getutline (daemon_sock, line, buffer) < 0) + if (do_getutid (daemon_sock, id, buffer) < 0) { *result = NULL; - return -1;; + return -1; } *result = buffer; @@ -163,17 +137,13 @@ getutline_r_daemon (const struct utmp *line, struct utmp *buffer, static int -getutid_r_daemon (const struct utmp *id, struct utmp *buffer, - struct utmp **result) +getutline_r_daemon (const struct utmp *line, struct utmp *buffer, + struct utmp **result) { - if (daemon_sock < 0) - { - *result = NULL; - return -1; - } + assert (daemon_sock >= 0); /* Send request to the daemon. */ - if (do_getutid (daemon_sock, id, buffer) < 0) + if (do_getutline (daemon_sock, line, buffer) < 0) { *result = NULL; return -1; @@ -187,13 +157,7 @@ getutid_r_daemon (const struct utmp *id, struct utmp *buffer, static struct utmp * pututline_daemon (const struct utmp *utmp) { - /* Open connection if not already done. */ - if (daemon_sock == INT_MIN) - setutent_daemon (); - - if (daemon_sock < 0) - /* Something went wrong. */ - return NULL; + assert (daemon_sock >= 0); /* Send request to the daemon. */ if (do_pututline (daemon_sock, utmp) < 0) @@ -203,6 +167,19 @@ pututline_daemon (const struct utmp *utmp) } +static void +endutent_daemon (void) +{ + assert (daemon_sock >= 0); + + /* Send request to the daemon. */ + do_endutent (daemon_sock); + + close (daemon_sock); + daemon_sock = -1; +} + + static int updwtmp_daemon (const char *file, const struct utmp *utmp) { @@ -233,11 +210,11 @@ do_setutent (int sock) size_t size; size = sizeof (setutent_request) + strlen (__libc_utmp_file_name) + 1; - + request = malloc (size); if (request == NULL) return -1; - + request->header.version = UTMPD_VERSION; request->header.size = size; request->header.type = UTMPD_REQ_SETUTENT; @@ -286,24 +263,27 @@ do_getutent (int sock, struct utmp *buffer) } static int -do_endutent (int sock) +do_getutid (int sock, const struct utmp *id, struct utmp *buffer) { - endutent_request request; - endutent_reply reply; + getutid_request request; + getutid_reply reply; request.header.version = UTMPD_VERSION; - request.header.size = sizeof (endutent_request); - request.header.type = UTMPD_REQ_ENDUTENT; + request.header.size = sizeof (getutid_request); + request.header.type = UTMPD_REQ_GETUTID; + memcpy (&request.id, id, sizeof (struct utmp)); reply.header.version = UTMPD_VERSION; - reply.header.size = sizeof (endutent_reply); - reply.header.type = UTMPD_REQ_ENDUTENT; + reply.header.size = sizeof (getutid_reply); + reply.header.type = UTMPD_REQ_GETUTID; if (send_request (sock, &request.header, &reply.header) < 0) return -1; if (reply.result < 0) __set_errno (reply.errnum); + else + memcpy (buffer, &reply.entry, sizeof (struct utmp)); return reply.result; } @@ -335,45 +315,42 @@ do_getutline (int sock, const struct utmp *line, struct utmp *buffer) } static int -do_getutid (int sock, const struct utmp *id, struct utmp *buffer) +do_pututline (int sock, const struct utmp *utmp) { - getutid_request request; - getutid_reply reply; + pututline_request request; + pututline_reply reply; request.header.version = UTMPD_VERSION; - request.header.size = sizeof (getutid_request); - request.header.type = UTMPD_REQ_GETUTID; - memcpy (&request.id, id, sizeof (struct utmp)); + request.header.size = sizeof (pututline_request); + request.header.type = UTMPD_REQ_PUTUTLINE; + memcpy (&request.utmp, utmp, sizeof (struct utmp)); reply.header.version = UTMPD_VERSION; - reply.header.size = sizeof (getutid_reply); - reply.header.type = UTMPD_REQ_GETUTID; + reply.header.size = sizeof (pututline_reply); + reply.header.type = UTMPD_REQ_PUTUTLINE; if (send_request (sock, &request.header, &reply.header) < 0) return -1; if (reply.result < 0) __set_errno (reply.errnum); - else - memcpy (buffer, &reply.entry, sizeof (struct utmp)); return reply.result; } static int -do_pututline (int sock, const struct utmp *utmp) +do_endutent (int sock) { - pututline_request request; - pututline_reply reply; + endutent_request request; + endutent_reply reply; request.header.version = UTMPD_VERSION; - request.header.size = sizeof (pututline_request); - request.header.type = UTMPD_REQ_PUTUTLINE; - memcpy (&request.utmp, utmp, sizeof (struct utmp)); + request.header.size = sizeof (endutent_request); + request.header.type = UTMPD_REQ_ENDUTENT; reply.header.version = UTMPD_VERSION; - reply.header.size = sizeof (pututline_reply); - reply.header.type = UTMPD_REQ_PUTUTLINE; + reply.header.size = sizeof (endutent_reply); + reply.header.type = UTMPD_REQ_ENDUTENT; if (send_request (sock, &request.header, &reply.header) < 0) return -1; @@ -392,11 +369,11 @@ do_updwtmp (int sock, const char *file, const struct utmp *utmp) size_t size; size = sizeof (updwtmp_request) + strlen (file) + 1; - + request = malloc (size); if (request == NULL) return -1; - + request->header.version = UTMPD_VERSION; request->header.size = size; request->header.type = UTMPD_REQ_UPDWTMP; diff --git a/login/utmp_file.c b/login/utmp_file.c index 6d6e05b292..bea63644f7 100644 --- a/login/utmp_file.c +++ b/login/utmp_file.c @@ -18,13 +18,11 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <assert.h> #include <errno.h> #include <fcntl.h> -#include <limits.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> -#include <sys/stat.h> #include <unistd.h> #include <utmp.h> @@ -32,9 +30,10 @@ /* Descriptor for the file and position. */ -static int file_fd = INT_MIN; +static int file_fd = -1; static off_t file_offset; +/* Cache for the last read entry. */ static struct utmp last_entry; @@ -68,14 +67,14 @@ setutent_file (void) if (file_fd < 0) { const char *file_name = __libc_utmp_file_name; - + if (strcmp (__libc_utmp_file_name, _PATH_UTMP) == 0 && __access (_PATH_UTMP "x", F_OK) == 0) file_name = _PATH_UTMP "x"; else if (strcmp (__libc_utmp_file_name, _PATH_WTMP) == 0 && __access (_PATH_WTMP "x", F_OK) == 0) file_name = _PATH_WTMP "x"; - + file_fd = open (file_name, O_RDWR); if (file_fd == -1) { @@ -96,18 +95,8 @@ setutent_file (void) /* Make sure the entry won't match. */ last_entry.ut_type = -1; #endif - - return 1; -} - - -static void -endutent_file (void) -{ - if (file_fd >= 0) - close (file_fd); - file_fd = INT_MIN; + return 1; } @@ -117,11 +106,9 @@ getutent_r_file (struct utmp *buffer, struct utmp **result) ssize_t nbytes; struct flock fl; /* Information struct for locking. */ - /* Open utmp file if not already done. */ - if (file_fd == INT_MIN) - setutent_file (); + assert (file_fd >= 0); - if (file_fd == -1 || file_offset == -1l) + if (file_offset == -1l) { /* Not available. */ *result = NULL; @@ -131,12 +118,16 @@ getutent_r_file (struct utmp *buffer, struct utmp **result) /* XXX The following is not perfect. Instead of locking the file itself Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl> suggests to use an extra locking file. */ + /* XXX I think using an extra locking file does not solve the + problems. Instead we should set an alarm, which causes fcntl to + fail, as in ../nis/lckcache.c. + Mark Kettenis <kettenis@phys.uva.nl>. */ /* Try to get the lock. */ memset (&fl, '\0', sizeof (struct flock)); fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; - fcntl (file_fd, F_SETLKW, &fl); + fcntl (file_fd, F_SETLK, &fl); /* Read the next entry. */ nbytes = read (file_fd, &last_entry, sizeof (struct utmp)); @@ -162,62 +153,6 @@ getutent_r_file (struct utmp *buffer, struct utmp **result) } -/* For implementing this function we don't use the getutent_r function - because we can avoid the reposition on every new entry this way. */ -static int -getutline_r_file (const struct utmp *line, struct utmp *buffer, - struct utmp **result) -{ - struct flock fl; - - if (file_fd < 0 || file_offset == -1l) - { - *result = NULL; - return -1; - } - - /* Try to get the lock. */ - memset (&fl, '\0', sizeof (struct flock)); - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - fcntl (file_fd, F_SETLKW, &fl); - - while (1) - { - /* Read the next entry. */ - if (read (file_fd, &last_entry, sizeof (struct utmp)) - != sizeof (struct utmp)) - { - __set_errno (ESRCH); - file_offset = -1l; - *result = NULL; - goto unlock_return; - } - file_offset += sizeof (struct utmp); - - /* Stop if we found a user or login entry. */ - if ( -#if _HAVE_UT_TYPE - 0 - (last_entry.ut_type == USER_PROCESS - || last_entry.ut_type == LOGIN_PROCESS) - && -#endif - !strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)) - break; - } - - memcpy (buffer, &last_entry, sizeof (struct utmp)); - *result = buffer; - -unlock_return: - /* And unlock the file. */ - fl.l_type = F_UNLCK; - fcntl (file_fd, F_SETLKW, &fl); - - return ((*result == NULL) ? -1 : 0); -} - - static int proc_utmp_eq (const struct utmp *entry, const struct utmp *match) { @@ -308,7 +243,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer) unlock_return: /* And unlock the file. */ fl.l_type = F_UNLCK; - fcntl (file_fd, F_SETLKW, &fl); + fcntl (file_fd, F_SETLK, &fl); return result; } @@ -320,7 +255,9 @@ static int getutid_r_file (const struct utmp *id, struct utmp *buffer, struct utmp **result) { - if (file_fd < 0 || file_offset == -1l) + assert (file_fd >= 0); + + if (file_offset == -1l) { *result = NULL; return -1; @@ -339,6 +276,64 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer, } +/* For implementing this function we don't use the getutent_r function + because we can avoid the reposition on every new entry this way. */ +static int +getutline_r_file (const struct utmp *line, struct utmp *buffer, + struct utmp **result) +{ + struct flock fl; + + assert (file_fd >= 0); + + if (file_offset == -1l) + { + *result = NULL; + return -1; + } + + /* Try to get the lock. */ + memset (&fl, '\0', sizeof (struct flock)); + fl.l_type = F_RDLCK; + fl.l_whence = SEEK_SET; + fcntl (file_fd, F_SETLKW, &fl); + + while (1) + { + /* Read the next entry. */ + if (read (file_fd, &last_entry, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __set_errno (ESRCH); + file_offset = -1l; + *result = NULL; + goto unlock_return; + } + file_offset += sizeof (struct utmp); + + /* Stop if we found a user or login entry. */ + if ( +#if _HAVE_UT_TYPE - 0 + (last_entry.ut_type == USER_PROCESS + || last_entry.ut_type == LOGIN_PROCESS) + && +#endif + !strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)) + break; + } + + memcpy (buffer, &last_entry, sizeof (struct utmp)); + *result = buffer; + +unlock_return: + /* And unlock the file. */ + fl.l_type = F_UNLCK; + fcntl (file_fd, F_SETLK, &fl); + + return ((*result == NULL) ? -1 : 0); +} + + static struct utmp * pututline_file (const struct utmp *data) { @@ -347,13 +342,7 @@ pututline_file (const struct utmp *data) struct utmp *pbuf; int found; - /* Open utmp file if not already done. */ - if (file_fd == INT_MIN) - setutent_file (); - - if (file_fd == -1) - /* Something went wrong. */ - return NULL; + assert (file_fd >= 0); /* Find the correct place to insert the data. */ if (file_offset > 0 @@ -375,7 +364,7 @@ pututline_file (const struct utmp *data) memset (&fl, '\0', sizeof (struct flock)); fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; - fcntl (file_fd, F_SETLKW, &fl); + fcntl (file_fd, F_SETLK, &fl); if (found < 0) { @@ -418,12 +407,22 @@ pututline_file (const struct utmp *data) unlock_return: /* And unlock the file. */ fl.l_type = F_UNLCK; - fcntl (file_fd, F_SETLKW, &fl); + fcntl (file_fd, F_SETLK, &fl); return pbuf; } +static void +endutent_file (void) +{ + assert (file_fd >= 0); + + close (file_fd); + file_fd = -1; +} + + static int updwtmp_file (const char *file, const struct utmp *utmp) { @@ -441,7 +440,7 @@ updwtmp_file (const char *file, const struct utmp *utmp) memset (&fl, '\0', sizeof (struct flock)); fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; - fcntl (fd, F_SETLKW, &fl); + fcntl (fd, F_SETLK, &fl); /* Remember original size of log file. */ offset = lseek (fd, 0, SEEK_END); diff --git a/login/utmpname.c b/login/utmpname.c index c0b6df2ce7..e0a78aff42 100644 --- a/login/utmpname.c +++ b/login/utmpname.c @@ -44,6 +44,7 @@ __utmpname (const char *file) /* Close the old file. */ (*__libc_utmp_jump_table->endutent) (); + __libc_utmp_jump_table = &__libc_utmp_unknown_functions; if (strcmp (file, __libc_utmp_file_name) != 0) { @@ -68,7 +69,6 @@ __utmpname (const char *file) } } - __libc_utmp_jump_table = &__libc_utmp_unknown_functions; result = 0; done: diff --git a/mach/setup-thread.c b/mach/setup-thread.c index 177d02d300..a49fe3f2ed 100644 --- a/mach/setup-thread.c +++ b/mach/setup-thread.c @@ -41,33 +41,14 @@ __mach_setup_thread (task_t task, thread_t thread, void *pc, mach_msg_type_number_t tssize = MACHINE_THREAD_STATE_COUNT; vm_address_t stack; vm_size_t size; - int anywhere = 0; + int anywhere; size = stack_size ? *stack_size ? : STACK_SIZE : STACK_SIZE; + stack = stack_base ? *stack_base ? : 0 : 0; + anywhere = !stack_base || !*stack_base; - if (stack_base && *stack_base) - stack = *stack_base; - else if (size == STACK_SIZE) - { - /* Cthreads has a bug that makes its stack-probing code fail if - the stack is too low in memory. It's bad to try and fix it there - until cthreads is integrated into libc, so we'll just do it here - by requesting a high address. When the cthreads bug is fixed, - this assignment to STACK should be changed to 0, and the ANYWHERE - argument to vm_allocate should be changed to 0. This comment should - be left, however, in order to confuse people who wonder why its - here. (Though perhaps that last sentence (and this one) should - be deleted to maximize the effect.) */ -#ifdef STACK_GROWTH_DOWN - stack = VM_MAX_ADDRESS - size - __vm_page_size; -#else - stack = VM_MIN_ADDRESS; -#endif - } - else - anywhere = 1; - - if (error = __vm_allocate (task, &stack, size + __vm_page_size, anywhere)) + error = __vm_allocate (task, &stack, size + __vm_page_size, anywhere); + if (error) return error; if (stack_size) diff --git a/malloc/malloc.c b/malloc/malloc.c index 5b16a0ac20..1a5c886b6c 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -1684,7 +1684,7 @@ static mchunkptr mmap_chunk(size) size_t size; size = (size + SIZE_SZ + page_mask) & ~page_mask; p = (mchunkptr)MMAP(size, PROT_READ|PROT_WRITE); - if(p == (mchunkptr)-1) return 0; + if(p == (mchunkptr) MAP_FAILED) return 0; n_mmaps++; if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps; @@ -1812,7 +1812,7 @@ new_heap(size) size_t size; size = (size + page_mask) & ~page_mask; p1 = (char *)MMAP(HEAP_MAX_SIZE<<1, PROT_NONE); - if(p1 == (char *)-1) + if(p1 == MAP_FAILED) return 0; p2 = (char *)(((unsigned long)p1 + HEAP_MAX_SIZE) & ~(HEAP_MAX_SIZE-1)); ul = p2 - p1; diff --git a/manual/math.texi b/manual/math.texi index d4449bb24d..71b365151f 100644 --- a/manual/math.texi +++ b/manual/math.texi @@ -232,7 +232,7 @@ infinite. @item Squre root if the operand is less then zero. @item -Conversion of an internal floating-point number to an integer or toa +Conversion of an internal floating-point number to an integer or to a decimal string when overflow, infinity, or NaN precludes a faithful representation in that format and this cannot otherwise be signaled. @item @@ -247,7 +247,7 @@ If the exception does not cause a trap handler to be called the result of the operation is taken as a quiet NaN. @item Division by Zero -This exception is raised of the devisor is zero and the dividend is a +This exception is raised if the devisor is zero and the dividend is a finite nonzero number. If no trap occurs the result is either @iftex @tex @@ -270,8 +270,8 @@ $-\infty$ signs of the operands. @item Overflow -This exception is signalled whenever if the result cannot be represented -as a finite value in the destination precision's format. If no trap +This exception is signalled whenever the result cannot be represented +as a finite value in the precision format of the destination. If no trap occurs the result depends on the sign of the intermediate result and the current rounding mode (@w{IEEE 754}, @w{section 7.3}): @enumerate @@ -334,7 +334,7 @@ $\infty$. @end enumerate @item Underflow -The underflow exception is created when a intermediate result is too +The underflow exception is created when an intermediate result is too small for the operation or if the operations result rounded to the destination precision causes a loss of accuracy by approximating the result by denormalized numbers. @@ -342,17 +342,17 @@ result by denormalized numbers. When no trap is installed for the underflow exception, underflow shall be signaled (via the underflow flag) only when both tininess and loss of accuracy have been detected. If no trap handler is installed the -operation continues witht he inprecise small value or zero if the +operation continues with an inprecise small value or zero if the destination precision cannot hold the small exact result. @item Inexact -This exception is signaled if the rounded result is not exact (such as +This exception is signalled if the rounded result is not exact (such as computing the square root of two) or the result overflows without an overflow trap. @end table To control whether an exception causes a trap to occur all @w{IEEE 754} -conformant floating-point implementation (either hardware or software) +conformant floating-point implementations (either hardware or software) have a control word. By setting specific bits for each exception in this control word the programmer can decide whether a trap is wanted or not. @@ -378,42 +378,42 @@ actual implementation can be very different, depending on the underlying hardware or software. To address the single exception the @file{fenv.h} headers defines a -number macros: +number of macros: @vtable @code @comment fenv.h @comment ISO @item FE_INEXACT -Represent the inexact exception iff the FPU supports this exception. +Represents the inexact exception iff the FPU supports this exception. @comment fenv.h @comment ISO @item FE_DIVBYZERO -Represent the divide by zero exception iff the FPU supports this exception. +Represents the divide by zero exception iff the FPU supports this exception. @comment fenv.h @comment ISO @item FE_UNDERFLOW -Represent the underflow exception iff the FPU supports this exception. +Represents the underflow exception iff the FPU supports this exception. @comment fenv.h @comment ISO @item FE_OVERFLOW -Represent the overflow exception iff the FPU supports this exception. +Represents the overflow exception iff the FPU supports this exception. @comment fenv.h @comment ISO @item FE_INVALID -Represent the invalid exception iff the FPU supports this exception. +Represents the invalid exception iff the FPU supports this exception. @end vtable The macro @code{FE_ALL_EXCEPT} is the bitwise OR of all exception macros which are supported by the FP implementation. -Each of the supported exception flag can either be set or unset. The +Each of the supported exception flags can either be set or unset. The @w{ISO C 9X} standard defines functions to set, unset and test the status of the flags. @comment fenv.h @comment ISO @deftypefun void feclearexcept (int @var{excepts}) -This functions clears all of the supported exception flags denoted by +This function clears all of the supported exception flags denoted by @var{excepts} in the status word. @end deftypefun @@ -430,7 +430,7 @@ exception flags indicated by the parameter @var{excepts}. @end deftypefun @noindent -To restore the previously saved values one can use this functions: +To restore the previously saved values one can use this function: @comment fenv.h @comment ISO @@ -486,7 +486,7 @@ control word for the exceptions and the rounding mode can be safed. The file @file{fenv.h} defines the type @code{fenv_t}. The layout of a variable of this type is implementation defined but the variable is able -to contain the complete status informations. To fill a variable of this +to contain the complete status information. To fill a variable of this type one can use this function: @comment fenv.h @@ -497,7 +497,7 @@ Store the current floating-point environment in the object pointed to by @end deftypefun @noindent -Another possibility which is useful is several situations is +Another possibility which is useful in several situations is @comment fenv.h @comment ISO @@ -505,7 +505,7 @@ Another possibility which is useful is several situations is Store the current floating-point environment in the object pointed to by @var{envp}. Afterwards, all exception flags are cleared and if available a mode is installed which continues on all exception and does -not cause a trap to occur. In ths case a nonzero value is returned. +not cause a trap to occur. In this case a nonzero value is returned. If the floating-point implementation does not support such a non-stop mode, the return value is zero. @@ -605,14 +605,14 @@ $-\infty$. Round toward zero. @end vtable -At any time one of the four rounding modes above is selected. To get +At any time one of the above four rounding modes is selected. To get information about the currently selected mode one can use this function: @comment fenv.h @comment ISO @deftypefun int fegetround (void) Return the currently selected rounding mode, represented by one of the -values of the defined rouding mode macros. +values of the defined rounding mode macros. @end deftypefun @noindent @@ -625,18 +625,18 @@ Change the currently selected rounding mode to the mode described by the parameter @var{round}. If @var{round} does not correspond to one of the supported rounding modes nothing is changed. -The function return a nonzero value iff the requested rounding mode can +The function returns a nonzero value iff the requested rounding mode can be established. Otherwise zero is returned. @end deftypefun -Changing the rounding mode can be necessary for various reasons. But +Changing the rounding mode might be necessary for various reasons. But changing the mode only to round a given number normally is no good idea. The standard defines a set of functions which can be used to round an argument according to some rules and for all of the rounding modes there is a corresponding function. If a large set of number has to be rounded it might be good to change -the rounding mode and do not use the function the library provides. So +the rounding mode and to not use the function the library provides. So the perhaps necessary switching of the rounding mode in the library function can be avoided. But since not all rounding modes are guaranteed to exist on any platform this possible implementation cannot @@ -684,7 +684,7 @@ The value is the reziprocal of the square root of the value of the number pi. ALl values are defined as @code{long double} values unless the compiler does not support this type or @code{__STDC__} is not defined (both is -unlikey). Historically the numbers were @code{double} values and some +unlikely). Historically the numbers were @code{double} values and some old code still relies on this so you might want to add explizit casts if the extra precision of the @code{long double} value is not needed. One critical case are functions with a variable number of arguments, such as @@ -705,7 +705,7 @@ this value is not added to @file{math.h}. Every program should use @section Floating-Point Comparison Functions @cindex unordered comparison -The @w{IEEE 754} standards defines s'a set of functions which allows to +The @w{IEEE 754} standards defines a set of functions which allows to compare even those numbers which normally would cause an exception to be raised since they are unordered. E.g., the expression @@ -774,7 +774,7 @@ All the macros are defined in a way to ensure that both arguments are evaluated exactly once and so they can be used exactly like the builtin operators. -On several platform these macros are mapped on very efficient functions +On several platform these macros are mapped to very efficient functions the processor understands. But on machines missing these functions, the macros above might be rather slow. So it is best to use the builtin operators unless it is necessary to use unordered comparisons. diff --git a/manual/socket.texi b/manual/socket.texi index 0353eb7ed3..9cb9b435e4 100644 --- a/manual/socket.texi +++ b/manual/socket.texi @@ -142,11 +142,11 @@ But now the POSIX people came and unified the interface with their words possible. A solution provides the Unix98 specification which finally introduces a -type @code{socklen_t}. This type is used in all of the cases in +type @code{socklen_t}. This type is used in all of the cases that were previously changed to use @code{size_t}. The only requirement of this type is that it is an unsigned type of at least 32 bits. Therefore, implementations which require references to 32 bit variables be passed -can be as happy as implementations which right from the start of 64 bit +can be as happy as implementations which use right from the start 64 bit values. diff --git a/manual/time.texi b/manual/time.texi index 1022e1a41f..d711234c0b 100644 --- a/manual/time.texi +++ b/manual/time.texi @@ -536,6 +536,26 @@ Calling @code{localtime} has one other effect: it sets the variable Zone Functions}. @end deftypefun +Using the @code{localtime} function is a big problem in multi-threaded +programs. The result is returned in a static buffer and this is used in +all threads. POSIX.1c introduced a varient of this function. + +@comment time.h +@comment POSIX.1c +@deftypefun {struct tm *} localtime_r (const time_t *@var{time}, struct tm *@var{resultp}) +The @code{localtime_r} function works just like the @code{localtime} +function. It takes a pointer to a variable containing the calendar time +and converts it to the broken-down time format. + +But the result is not placed in a static buffer. Instead it is placed +in the object of type @code{struct tm} to which the parameter +@var{resultp} points. + +If the conversion is successful the function returns a pointer to the +object the result was written into, i.e., it returns @var{resultp}. +@end deftypefun + + @comment time.h @comment ISO @deftypefun {struct tm *} gmtime (const time_t *@var{time}) @@ -547,6 +567,21 @@ Recall that calendar times are @emph{always} expressed in coordinated universal time. @end deftypefun +As for the @code{localtime} function we have the problem that the result +is placed ina static variable. POSIX.1c also provides a replacement for +@code{gmtime}. + +@comment time.h +@comment POSIX.1c +@deftypefun {struct tm *} gmtime_r (const time_t *@var{time}, struct tm *@var{resultp}) +This function is similar to @code{localtime_r}, except that it converts +just like @code{gmtime} the given time as Coordinated Universal Time. + +If the conversion is successful the function returns a pointer to the +object the result was written into, i.e., it returns @var{resultp}. +@end deftypefun + + @comment time.h @comment ISO @deftypefun time_t mktime (struct tm *@var{brokentime}) @@ -602,6 +637,20 @@ string.) @end deftypefun @comment time.h +@comment POSIX.1c +@deftypefun {char *} asctime_r (const struct tm *@var{brokentime}, char *@var{buffer}) +This function is similar to @code{asctime} but instead of placing the +result in a static buffer it writes the string in the buffer pointed to +by the parameter @var{buffer}. This buffer should have at least room +for 16 bytes. + +If no error occurred the function returns a pointer to the string the +result was written into, i.e., it returns @var{buffer}. Otherwise +return @code{NULL}. +@end deftypefun + + +@comment time.h @comment ISO @deftypefun {char *} ctime (const time_t *@var{time}) The @code{ctime} function is similar to @code{asctime}, except that the @@ -617,6 +666,23 @@ does so. @xref{Time Zone Functions}. @end deftypefun @comment time.h +@comment POSIX.1c +@deftypefun {char *} ctime_r (const time_t *@var{time}, char *@var{buffer}) +This function is similar to @code{ctime}, only that it places the result +in the string pointed to by @var{buffer}. It is equivalent to (written +using gcc extensions, @xref{Statement Exprs,,,gcc,Porting and Using gcc}.): + +@smallexample +(@{ struct tm tm; asctime_r (localtime_r (time, &tm), buf); @}) +@end smallexample + +If no error occurred the function returns a pointer to the string the +result was written into, i.e., it returns @var{buffer}. Otherwise +return @code{NULL}. +@end deftypefun + + +@comment time.h @comment ISO @comment POSIX.2 @deftypefun size_t strftime (char *@var{s}, size_t @var{size}, const char *@var{template}, const struct tm *@var{brokentime}) @@ -885,7 +951,7 @@ A literal @samp{%} character. The @var{size} parameter can be used to specify the maximum number of characters to be stored in the array @var{s}, including the terminating null character. If the formatted time requires more than @var{size} -characters, @code{strftime} return zero and the content of the array +characters, @code{strftime} returns zero and the content of the array @var{s} is indetermined. Otherwise the return value indicates the number of characters placed in the array @var{s}, not including the terminating null character. @@ -1095,6 +1161,10 @@ GNU programs it is better to use the @code{tm_zone} member of the broken-down time structure, since @code{tm_zone} reports the correct abbreviation even when it is not the latest one. +Though the strings are declared as @code{char *} the user must stay away +from modifying these strings. Modying the strings will almost certainly +lead to trouble. + @end deftypevar @comment time.h diff --git a/manual/users.texi b/manual/users.texi index a622dd5fd4..ca9dee4ca6 100644 --- a/manual/users.texi +++ b/manual/users.texi @@ -42,6 +42,9 @@ can use to examine these databases. * Who Logged In:: Getting the name of the user who logged in, or of the real user ID of the current process. +* User Accounting Database:: Keeping information about users and various + actions in databases. + * User Database:: Functions and data structures for accessing the user database. * Group Database:: Functions and data structures for @@ -51,7 +54,7 @@ can use to examine these databases. inquiry functions. @end menu -@node User and Group IDs, Process Persona, Users and Groups, Users and Groups +@node User and Group IDs @section User and Group IDs @cindex login name @@ -72,7 +75,7 @@ not accessible to users who are not a member of that group. Each group has a @dfn{group name} and @dfn{group ID}. @xref{Group Database}, for how to find information about a group ID or group name. -@node Process Persona, Why Change Persona, User and Group IDs, Users and Groups +@node Process Persona @section The Persona of a Process @cindex persona @cindex effective user ID @@ -114,7 +117,7 @@ its permission to access files, see @ref{Access Permission}. The user ID of a process also controls permissions for sending signals using the @code{kill} function. @xref{Signaling Another Process}. -@node Why Change Persona, How Change Persona, Process Persona, Users and Groups +@node Why Change Persona @section Why Change the Persona of a Process? The most obvious situation where it is necessary for a process to change @@ -146,7 +149,7 @@ the game program wants to update this file, it can change its effective user ID to be that for @code{games}. In effect, the program must adopt the persona of @code{games} so it can write the scores file. -@node How Change Persona, Reading Persona, Why Change Persona, Users and Groups +@node How Change Persona @section How an Application Can Change Persona @cindex @code{setuid} programs @@ -177,7 +180,7 @@ when they are not needed, which makes for more robustness. @c !!! talk about _POSIX_SAVED_IDS -@node Reading Persona, Setting User ID, How Change Persona, Users and Groups +@node Reading Persona @section Reading the Persona of a Process Here are detailed descriptions of the functions for reading the user and @@ -262,7 +265,7 @@ read_all_groups (void) @end smallexample @end deftypefun -@node Setting User ID, Setting Groups, Reading Persona, Users and Groups +@node Setting User ID @section Setting the User ID This section describes the functions for altering the user ID (real @@ -325,7 +328,7 @@ have permission to change to the specified ID. @end table @end deftypefun -@node Setting Groups, Enable/Disable Setuid, Setting User ID, Users and Groups +@node Setting Groups @section Setting the Group IDs This section describes the functions for altering the group IDs (real @@ -400,7 +403,7 @@ the user name @var{user}. The group ID @var{gid} is also included. @c groups USER is a member of. @end deftypefun -@node Enable/Disable Setuid, Setuid Program Example, Setting Groups, Users and Groups +@node Enable/Disable Setuid @section Enabling and Disabling Setuid Access A typical setuid program does not need its special access all of the @@ -466,7 +469,7 @@ feature with a preprocessor conditional, like this: #endif @end smallexample -@node Setuid Program Example, Tips for Setuid, Enable/Disable Setuid, Users and Groups +@node Setuid Program Example @section Setuid Program Example Here's an example showing how to set up a program that changes its @@ -606,7 +609,7 @@ record_score (int score) @end group @end smallexample -@node Tips for Setuid, Who Logged In, Setuid Program Example, Users and Groups +@node Tips for Setuid @section Tips for Writing Setuid Programs It is easy for setuid programs to give the user access that isn't @@ -650,7 +653,7 @@ would ordinarily have permission to access those files. You can use the uses the real user and group IDs, rather than the effective IDs. @end itemize -@node Who Logged In, User Database, Tips for Setuid, Users and Groups +@node Who Logged In @section Identifying Who Logged In @cindex login name, determining @cindex user ID, determining @@ -658,7 +661,9 @@ uses the real user and group IDs, rather than the effective IDs. You can use the functions listed in this section to determine the login name of the user who is running a process, and the name of the user who logged in the current session. See also the function @code{getuid} and -friends (@pxref{Reading Persona}). +friends (@pxref{Reading Persona}). How this information is collected by +the system and how to control/add/remove information from the background +storage is described in @ref{User Accounting Database}. The @code{getlogin} function is declared in @file{unistd.h}, while @code{cuserid} and @code{L_cuserid} are declared in @file{stdio.h}. @@ -707,7 +712,610 @@ For most purposes, it is more useful to use the environment variable precisely because the user can set @code{LOGNAME} arbitrarily. @xref{Standard Environment}. -@node User Database, Group Database, Who Logged In, Users and Groups + +@node User Accounting Database +@section The User Accounting Database +@cindex user accounting database + +Most Unix-like operating systems keep track of logged in users by +maintaining a user accounting database. This user accounting database +stores for each terminal, who has logged on, at what time, the process +ID of the user's login shell, etc., etc., but also stores information +about the run level of the system, the time of the last system reboot, +and possibly more. + +The user accounting database typically lives in @file{/etc/utmp}, +@file{/var/adm/utmp} or @file{/var/run/utmp}. However, these files +should @strong{never} be accessed directly. For reading information +from and writing information to the user accounting database, the +functions described in this section should be used. + + +@menu +* Manipulating the Database:: Scanning and modifying the user + accounting database. +* XPG Functions:: A standardized way for doing the same thing. +* Logging In and Out:: Functions from BSD that modify the user + accounting database. +@end menu + +@node Manipulating the Database +@subsection Manipulating the User Accounting Database + +These functions and the corresponding data structures are declared in +the header file @file{utmp.h}. +@pindex utmp.h + +@comment utmp.h +@comment SVID +@deftp {Data Type} {struct exit_status} +The @code{exit_status} data structure is used to hold information about +the exit status of processes marked as @code{DEAD_PROCESS} in the user +accounting database. + +@table @code +@item short int e_termination +The exit status of the process. + +@item short int e_exit +The exit status of the process. +@end table +@end deftp + +@deftp {Data Type} {struct utmp} +The @code{utmp} data structure is used to hold information about entries +in the user accounting database. On the GNU system it has the following +members: + +@table @code +@item short int ut_type +Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL}, +@code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS}, +@code{LOGIN_PROCESS}, @code{USER_PROCESS}, @code{DEAD_PROCESS} or +@code{ACCOUNTING}. + +@item pid_t ut_pid +The process ID number of the login process. + +@item char ut_line[] +The device name of the tty (without @file{/dev/}). + +@item char ut_id[] +The inittab ID of the process. + +@item char ut_user[] +The user's login name. + +@item char ut_host[] +The name of the host from which the user logged in. + +@item struct exit_status ut_exit +The exit status of a process marked as @code{DEAD_PROCESS}. + +@item long ut_session +The Session ID, used for windowing. + +@item struct timeval ut_tv +Time the entry was made. For entries of type @code{OLD_TIME} this is +the time when the system clock changed, and for entries of type +@code{NEW_TIME} this is the time the system clock was set to. + +@item int32_t ut_addr_v6[4] +The Internet address of a remote host. +@end table +@end deftp + +The @code{ut_type}, @code{ut_pid}, @code{ut_id}, @code{ut_tv}, and +@code{ut_host} fields are not available on all systems. Portable +applications therefore should be prepared for these situations. To help +doing this the @file{utmp.h} header provides macros +@code{_HAVE_UT_TYPE}, @code{_HAVE_UT_PID}, @code{_HAVE_UT_ID}, +@code{_HAVE_UT_TV}, and @code{_HAVE_UT_HOST} if the respective field is +available. The programmer can handle the situations by using +@code{#ifdef} in the program code. + +The following macros are defined for use as values for the +@code{ut_type} member of the @code{utmp} structure. The values are +integer constants. + +@table @code +@comment utmp.h +@comment SVID +@vindex EMPTY +@item EMPTY +This macro is used to indicate that the entry contains no valid user +accounting information. + +@comment utmp.h +@comment SVID +@vindex RUN_LVL +@item RUN_LVL +This macro is used to identify the systems runlevel. + +@comment utmp.h +@comment SVID +@vindex BOOT_TIME +@item BOOT_TIME +This macro is used to identify the time of system boot. + +@comment utmp.h +@comment SVID +@vindex OLD_TIME +@item OLD_TIME +This macro is used to identify the time when the system clock changed. + +@comment utmp.h +@comment SVID +@vindex NEW_TIME +@item NEW_TIME +This macro is used to identify the time after the system changed. + +@comment utmp.h +@comment SVID +@vindex INIT_PROCESS +@item INIT_PROCESS +This macro is used to identify a process spawned by the init process. + +@comment utmp.h +@comment SVID +@vindex LOGIN_PROCESS +@item LOGIN_PROCESS +This macro is used to identify the session leader of a logged in user. + +@comment utmp.h +@comment SVID +@vindex USER_PROCESS +@item USER_PROCESS +This macro is used to identify a user process. + +@comment utmp.h +@comment SVID +@vindex DEAD_PROCESS +@item DEAD_PROCESS +This macro is used to identify a terminated process. + +@comment utmp.h +@comment SVID +@vindex ACCOUNTING +@item ACCOUNTING +??? +@end table + +The size of the @code{ut_line}, @code{ut_id}, @code{ut_user} and +@code{ut_host} arrays can be found using the @code{sizeof} operator. + +Many older systems have, instead of an @code{ut_tv} member, an +@code{ut_time} member, usually of type @code{time_t}, for representing +the time associated with the entry. Therefore, for backwards +compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for +@code{ut_tv.tv_sec}. + +@comment utmp.h +@comment SVID +@deftypefun void setutent (void) +This function opens the user accounting database to begin scanning it. +You can then call @code{getutent}, @code{getutid} or @code{getutline} to +read entries and @code{pututline} to write entries. + +If the database is already open, it resets the input to the beginning of +the database. +@end deftypefun + +@comment utmp.h +@comment SVID +@deftypefun {struct utmp *} getutent (void) +The @code{getutent} function reads the next entry from the user +accounting database. It returns a pointer to the entry, which is +statically allocated and may be overwritten by subsequent calls to +@code{getutent}. You must copy the contents of the structure if you +wish to save the information or you can use the @code{getutent_r} +function which stores the data in a user-provided buffer. + +A null pointer is returned in case no further entry is available. +@end deftypefun + +@comment utmp.h +@comment SVID +@deftypefun void endutent (void) +This function closes the user accounting database. +@end deftypefun + +@comment utmp.h +@comment SVID +@deftypefun {struct utmp *} getutid (const struct utmp *@var{id}) +This function searches forward from the current point in the database +for an entry that matches @var{id}. If the @code{ut_type} member of the +@var{id} structure is one of @code{RUN_LVL}, @code{BOOT_TIME}, +@code{OLD_TIME} or @code{NEW_TIME} the entries match if the +@code{ut_type} members are identical. If the @code{ut_type} member of +the @var{id} structure is @code{INIT_PROCESS}, @code{LOGIN_PROCESS}, +@code{USER_PROCESS} or @code{DEAD_PROCESS}, the entries match if the the +@code{ut_type} member of the entry read from the database is one of +these four, and the @code{ut_id} members match. However if the +@code{ut_id} member of either the @var{id} structure or the entry read +from the database is empty it checks if the @code{ut_line} members match +instead. If a matching entry is found, @code{getutid} returns a pointer +to the entry, which is statically allocated, and may be overwritten by a +subsequent call to @code{getutent}, @code{getutid} or @code{getutline}. +You must copy the contents of the structure if you wish to save the +information. + +A null pointer is returned in case the end of the database is reached +without a match. + +The @code{getutid} function may cache the last read entry. Therefore, +if you are using @code{getutid} to search for multiple occurrences, it +is necessary to zero out the static data after each call. Otherwise +@code{getutid} could just return a pointer to the same entry over and +over again. +@end deftypefun + +@comment utmp.h +@comment SVID +@deftypefun {struct utmp *} getutline (const struct utmp *@var{line}) +This function searches forward from the current point in the database +until it finds an entry whose @code{ut_type} value is +@code{LOGIN_PROCESS} or @code{USER_PROCESS}, and whose @code{ut_line} +member matches the @code{ut_line} member of the @var{line} structure. +If it finds such an entry, it returns a pointer to the entry which is +statically allocated, and may be overwritten by a subsequent call to +@code{getutent}, @code{getutid} or @code{getutline}. You must copy the +contents of the structure if you wish to save the information. + +A null pointer is returned in case the end of the database is reached +without a match. + +The @code{getutline} function may cache the last read entry. Therefore +if you are using @code{getutline} to search for multiple occurrences, it +is necessary to zero out the static data after each call. Otherwise +@code{getutline} could just return a pointer to the same entry over and +over again. +@end deftypefun + +@comment utmp.h +@comment SVID +@deftypefun {struct utmp *} pututline (const struct utmp *@var{utmp}) +The @code{pututline} function inserts the entry @code{*@var{utmp}} at +the appropriate place in the user accounting database. If it finds that +it is not already at the correct place in the database, it uses +@code{getutid} to search for the position to insert the entry, however +this will not modify the static structure returned by @code{getutent}, +@code{getutid} and @code{getutline}. If this search fails, the entry +is appended to the database. + +The @code{pututline} function returns a pointer to a copy of the entry +inserted in the user accounting database, or a null pointer if the entry +could not be added. The following @code{errno} error conditions are +defined for this function: + +@table @code +@item EPERM +The process does not have the appropriate privileges; you cannot modify +the user accounting database. +@end table +@end deftypefun + +All the @code{get*} functions mentioned before store the information +they return in a static buffer. This can be a problem in multi-threaded +programs since the data return for the request is overwritten be the +return value data in another thread. Therefore the GNU C Library +provides as extensions three more functions which return the data in a +user-provided buffer. + +@comment utmp.h +@comment GNU +@deftypefun int getutent_r (struct utmp *@var{buffer}, struct utmp **@var{result}) +The @code{getutent_r} is equivalent to the @code{getutent} function. It +returns the next entry from the database. But instead of storing the +information in a static buffer it stores it in the buffer pointed to by +the parameter @var{buffer}. + +If the call was successful, the function returns @code{0} and the +pointer variable pointed to by the parameter @var{result} contains a +pointer to the buffer which contains the result (this is most probably +the same value as @var{buffer}). If something went wrong during the +execution of @code{getutent_r} the function returns @code{-1}. + +This function is a GNU extension. +@end deftypefun + +@comment utmp.h +@comment GNU +@deftypefun int getutid_r (const struct utmp *@var{id}, struct utmp *@var{buffer}, struct utmp **@var{result}) +This function retrieves just like @code{getutid} the next entry matching +the information stored in @var{id}. But the result is stored in the +buffer pointed to by the parameter @var{buffer}. + +If successful the function returns @code{0} and the pointer variable +pointed to by the parameter @var{result} contains a pointer to the +buffer with the result (probably the same as @var{result}. If not +successful the function return @code{-1}. + +This function is a GNU extension. +@end deftypefun + +@comment utmp.h +@comment GNU +@deftypefun int getutline_r (const struct utmp *@var{line}, struct utmp *@var{buffer}, struct utmp **@var{result}) +This function retrieves just like @code{getutline} the next entry +matching the information stored in @var{line}. But the result is stored +in the buffer pointed to by the parameter @var{buffer}. + +If successful the function returns @code{0} and the pointer variable +pointed to by the parameter @var{result} contains a pointer to the +buffer with the result (probably the same as @var{result}. If not +successful the function return @code{-1}. + +This function is a GNU extension. +@end deftypefun + + +In addition to the user accounting database, most systems keep a number +of similar databases. For example most systems keep a log file with all +previous logins (usually in @file{/etc/wtmp} or @file{/var/log/wtmp}). + +For specifying which database to examine, the following function should +be used. + +@comment utmp.h +@comment SVID +@deftypefun int utmpname (const char *@var{file}) +The @code{utmpname} function changes the name of the database to be +examined to @var{file}, and closes any previously opened database. By +default @code{getutent}, @code{getutid}, @code{getutline} and +@code{pututline} read from and write to the user accounting database. + +The following macros are defined for use as the @var{file} argument: + +@deftypevr Macro {char *} _PATH_UTMP +This macro is used to specify the user accounting database. +@end deftypevr + +@deftypevr Macro {char *} _PATH_WTMP +This macro is used to specify the user accounting log file. +@end deftypevr + +The @code{utmpname} function returns a value of @code{0} if the new name +was successfully stored, and a value of @code{-1} to indicate an error. +Note that @code{utmpname} does not try open the database, and that +therefore the return value does not say anything about whether the +database can be successfully opened. +@end deftypefun + +Specially for maintaining log-like databases the GNU C Library provides +the following function: + +@comment utmp.h +@comment SVID +@deftypefun void updwtmp (const char *@var{wtmp_file}, const struct utmp *@var{utmp}) +The @code{updwtmp} function appends the entry *@var{utmp} to the +database specified by @var{wtmp_file}. For possible values for the +@var{wtmp_file} argument see the @code{utmpname} function. +@end deftypefun + +@strong{Portability Note:} Although many operating systems provide a +subset of these functions, they are not standardized. There are often +subtle differences in the return types, and there are considerable +differences between the various definitions of @code{struct utmp}. When +programming for the GNU system, it is probably probably best to stick +with the functions described in this section. If however, you want your +program to be portable, consider using the XPG functions described in +@ref{XPG Functions}, or take a look at the BSD compatible functions in +@ref{Logging In and Out}. + + +@node XPG Functions +@subsection XPG User Accounting Database Functions + +These functions, described in the X/Open Portability Guide, are declared +in the header file @file{utmpx.h}. +@pindex utmpx.h + +@deftp {Data Type} {struct utmpx} +The @code{utmpx} data structure contains at least the following members: + +@table @code +@item short int ut_type +Specifies the type of login; one of @code{EMPTY}, @code{RUN_LVL}, +@code{BOOT_TIME}, @code{OLD_TIME}, @code{NEW_TIME}, @code{INIT_PROCESS}, +@code{LOGIN_PROCESS}, @code{USER_PROCESS} or @code{DEAD_PROCESS}. + +@item pid_t ut_pid +The process ID number of the login process. + +@item char ut_line[] +The device name of the tty (without @file{/dev/}). + +@item char ut_id[] +The inittab ID of the process. + +@item char ut_user[] +The user's login name. + +@item struct timeval ut_tv +Time the entry was made. For entries of type @code{OLD_TIME} this is +the time when the system clock changed, and for entries of type +@code{NEW_TIME} this is the time the system clock was set to. +@end table +On the GNU system, @code{struct utmpx} is identical to @code{struct +utmp} except for the fact that including @file{utmpx.h} does not make +visible the declaration of @code{struct exit_status}. +@end deftp + +The following macros are defined for use as values for the +@code{ut_type} member of the @code{utmpx} structure. The values are +integer constants and are, on the GNU system, identical to the +definitions in @file{utmp.h}. + +@table @code +@comment utmpx.h +@comment XPG4.2 +@vindex EMPTY +@item EMPTY +This macro is used to indicate that the entry contains no valid user +accounting information. + +@comment utmpx.h +@comment XPG4.2 +@vindex RUN_LVL +@item RUN_LVL +This macro is used to identify the systems runlevel. + +@comment utmpx.h +@comment XPG4.2 +@vindex BOOT_TIME +@item BOOT_TIME +This macro is used to identify the time of system boot. + +@comment utmpx.h +@comment XPG4.2 +@vindex OLD_TIME +@item OLD_TIME +This macro is used to identify the time when the system clock changed. + +@comment utmpx.h +@comment XPG4.2 +@vindex NEW_TIME +@item NEW_TIME +This macro is used to identify the time after the system changed. + +@comment utmpx.h +@comment XPG4.2 +@vindex INIT_PROCESS +@item INIT_PROCESS +This macro is used to identify a process spawned by the init process. + +@comment utmpx.h +@comment XPG4.2 +@vindex LOGIN_PROCESS +@item LOGIN_PROCESS +This macro is used to identify the session leader of a logged in user. + +@comment utmpx.h +@comment XPG4.2 +@vindex USER_PROCESS +@item USER_PROCESS +This macro is used to identify a user process. + +@comment utmpx.h +@comment XPG4.2 +@vindex DEAD_PROCESS +@item DEAD_PROCESS +This macro is used to identify a terminated process. +@end table + +The size of the @code{ut_line}, @code{ut_id} and @code{ut_user} arrays +can be found using the @code{sizeof} operator. + +@comment utmpx.h +@comment XPG4.2 +@deftypefun void setutxent (void) +This function is similar to @code{setutent}. On the GNU system it is +simply an alias for @code{setutent}. +@end deftypefun + +@comment utmpx.h +@comment XPG4.2 +@deftypefun {struct utmpx *} getutxent (void) +The @code{getutxent} function is similar to @code{getutent}, but returns +a pointer to a @code{struct utmpx} instead of @code{struct utmp}. On +the GNU system it simply is an alias for @code{getutent}. +@end deftypefun + +@comment utmpx.h +@comment XPG4.2 +@deftypefun void endutxent (void) +This function is similar to @code{endutent}. On the GNU system it is +simply an alias for @code{endutent}. +@end deftypefun + +@comment utmpx.h +@comment XPG4.2 +@deftypefun {struct utmpx *} getutxid (const struct utmpx *@var{id}) +This function is similar to @code{getutid}, but uses @code{struct utmpx} +instead of @code{struct utmp}. On the GNU system it is simply an alias +for @code{getutid}. +@end deftypefun + +@comment utmpx.h +@comment XPG4.2 +@deftypefun {struct utmpx *} getutxline (const struct utmpx *@var{line}) +This function is similar to @code{getutid}, but uses @code{struct utmpx} +instead of @code{struct utmp}. On the GNU system it is simply an alias +for @code{getutline}. +@end deftypefun + +@comment utmpx.h +@comment XPG4.2 +@deftypefun {struct utmpx *} pututxline (const struct utmpx *@var{utmp}) +The @code{pututxline} function provides functionality identical to +@code{pututline}, but uses @code{struct utmpx} instead of @code{struct +utmp}. On the GNU system @code{pututxline} is simply an alias for +@code{pututline}. +@end deftypefun + + +@node Logging In and Out +@subsection Logging In and Out + +These functions, derived from BSD, are available in the separate +@file{libutil} library, and declared in @file{utmp.h}. +@pindex utmp.h + +Note that the @code{ut_user} member of @code{struct utmp} is called +@code{ut_name} in BSD. Therefore, @code{ut_name} is defined as an alias +for @code{ut_user} in @file{utmp.h}. + +@comment utmp.h +@comment BSD +@deftypefun int login_tty (int @var{filedes}) +This function makes @var{filedes} the controlling terminal of the +current process, redirects standard input, standard output and +standard error output to this terminal, and closes @var{filedes}. + +This function returns @code{0} on successful completion, and @code{-1} +on error. +@end deftypefun + +@comment utmp.h +@comment BSD +@deftypefun void login (const struct utmp *@var{entry}) +The @code{login} functions inserts an entry into the user accounting +database. The @code{ut_line} member is set to the name of the terminal +on standard input. If standard input is not a terminal @code{login} +uses standard output or standard error output to determine the name of +the terminal. If @code{struct utmp} has a @code{ut_type} member, +@code{login} sets it to @code{USER_PROCESS}, and if there is an +@code{ut_pid} member, it will be set to the process ID of the current +process. The remaining entries are copied from @var{entry}. + +A copy of the entry is written to the user accounting log file. +@end deftypefun + +@comment utmp.h +@comment BSD +@deftypefun int logout (const char *@var{ut_line}) +This function modifies the user accounting database to indicate that the +user on @var{ut_line} has logged out. + +The @code{logout} function returns @code{1} if the entry was successfully +written to the database, or @code{0} on error. +@end deftypefun + +@comment utmp.h +@comment BSD +@deftypefun void logwtmp (const char *@var{ut_line}, const char *@var{ut_name}, const char *@var{ut_host}) +The @code{logwtmp} function appends an entry to the user accounting log +file, for the current time and the information provided in the +@var{ut_line}, @var{ut_name} and @var{ut_host} arguments. +@end deftypefun + +@strong{Portability Note:} The BSD @code{struct utmp} only has the +@code{ut_line}, @code{ut_name}, @code{ut_host} and @code{ut_time} +members. Older systems do not even have the @code{ut_host} member. + + +@node User Database @section User Database @cindex user database @cindex password database @@ -725,7 +1333,7 @@ network server gives access to it. * Writing a User Entry:: How a program can rewrite a user's record. @end menu -@node User Data Structure, Lookup User, User Database, User Database +@node User Data Structure @subsection The Data Structure that Describes a User The functions and data structures for accessing the system user database @@ -766,7 +1374,7 @@ be used. @end table @end deftp -@node Lookup User, Scanning All Users, User Data Structure, User Database +@node Lookup User @subsection Looking Up One User @cindex converting user ID to user name @cindex converting user name to user ID @@ -839,7 +1447,7 @@ In the later case the global @var{errno} variable is set to @end deftypefun -@node Scanning All Users, Writing a User Entry, Lookup User, User Database +@node Scanning All Users @subsection Scanning the List of All Users @cindex scanning the user list @@ -927,7 +1535,7 @@ This function closes the internal stream used by @code{getpwent} or @code{getpwent_r}. @end deftypefun -@node Writing a User Entry, , Scanning All Users, User Database +@node Writing a User Entry @subsection Writing a User Entry @comment pwd.h @@ -947,7 +1555,7 @@ would inevitably leave out much of the important information. The function @code{putpwent} is declared in @file{pwd.h}. @end deftypefun -@node Group Database, Netgroup Database, User Database, Users and Groups +@node Group Database @section Group Database @cindex group database @pindex /etc/group @@ -963,7 +1571,7 @@ service provides access to it. * Scanning All Groups:: Scanning the list of all groups. @end menu -@node Group Data Structure, Lookup Group, Group Database, Group Database +@node Group Data Structure @subsection The Data Structure for a Group The functions and data structures for accessing the system group @@ -990,7 +1598,7 @@ null pointer. @end table @end deftp -@node Lookup Group, Scanning All Groups, Group Data Structure, Group Database +@node Lookup Group @subsection Looking Up One Group @cindex converting group name to group ID @cindex converting group ID to group name @@ -1061,7 +1669,7 @@ In the later case the global @var{errno} variable is set to @code{ERANGE}. @end deftypefun -@node Scanning All Groups, , Lookup Group, Group Database +@node Scanning All Groups @subsection Scanning the List of All Groups @cindex scanning the group list @@ -1148,7 +1756,7 @@ This function closes the internal stream used by @code{getgrent} or @code{getgrent_r}. @end deftypefun -@node Netgroup Database, Database Example, Group Database, Users and Groups +@node Netgroup Database @section Netgroup Database @menu @@ -1158,7 +1766,7 @@ This function closes the internal stream used by @code{getgrent} or * Netgroup Membership:: How to test for netgroup membership. @end menu -@node Netgroup Data, Lookup Netgroup, Netgroup Database, Netgroup Database +@node Netgroup Data @subsection Netgroup Data @cindex Netgroup @@ -1191,7 +1799,7 @@ case is useful as well. I.e., there may be entries which will not match any input. For entries like a name consisting of the single character @code{-} shall be used. -@node Lookup Netgroup, Netgroup Membership, Netgroup Data, Netgroup Database +@node Lookup Netgroup @subsection Looking up one Netgroup The lookup functions for netgroups are a bit different to all other @@ -1262,7 +1870,7 @@ selected netgroup. As a result all string pointers returned by calls to @code{getnetgrent} are invalid afterwards. @end deftypefun -@node Netgroup Membership, , Lookup Netgroup, Netgroup Database +@node Netgroup Membership @subsection Testing for Netgroup Membership It is often not necessary to scan the whole netgroup since often the @@ -1295,7 +1903,7 @@ itself is not found, the netgroup does not contain the triple or internal errors occurred. @end deftypefun -@node Database Example, , Netgroup Database, Users and Groups +@node Database Example @section User and Group Database Example Here is an example program showing the use of the system database inquiry diff --git a/math/libm-test.c b/math/libm-test.c index 982e051bdd..5b773d6bd8 100644 --- a/math/libm-test.c +++ b/math/libm-test.c @@ -999,6 +999,7 @@ cbrt_test (void) check_isinfn ("cbrt (-inf) == -inf", FUNC(cbrt) (minus_infty)); check_isnan ("cbrt (NaN) == NaN", FUNC(cbrt) (nan_value)); #endif + check ("cbrt (-0.001) == -0.1", FUNC(cbrt) (-0.001), -0.1); check_eps ("cbrt (8) == 2", FUNC(cbrt) (8), 2, CHOOSE (5e-17L, 0, 0)); check_eps ("cbrt (-27) == -3", FUNC(cbrt) (-27.0), -3.0, CHOOSE (3e-16L, 0, 0)); diff --git a/math/test-fenv.c b/math/test-fenv.c index 2c3aeb07f9..4da2e37dae 100644 --- a/math/test-fenv.c +++ b/math/test-fenv.c @@ -228,8 +228,21 @@ fe_tests (void) static void feenv_nomask_test (const char *flag_name, int fe_exc) { +#if defined FE_NOMASK_ENV int status; pid_t pid; + fenv_t saved; + + fegetenv (&saved); + errno = 0; + fesetenv (FE_NOMASK_ENV); + status = errno; + fesetenv (&saved); + if (status == ENOSYS) + { + printf ("Test: not testing FE_NOMASK_ENV, it isn't implemented.\n"); + return; + } printf ("Test: after fesetenv (FE_NOMASK_ENV) processes will abort\n"); printf (" when feraiseexcept (%s) is called.\n", flag_name); @@ -265,6 +278,7 @@ feenv_nomask_test (const char *flag_name, int fe_exc) ++count_errors; } } +#endif } /* Test that program doesn't abort with default environment */ diff --git a/nis/Banner b/nis/Banner index 77ab77e8d2..3a1729c3b0 100644 --- a/nis/Banner +++ b/nis/Banner @@ -1 +1 @@ -NIS(YP)/NIS+ NSS modules 0.12 by Thorsten Kukuk +NIS(YP)/NIS+ NSS modules 0.13 by Thorsten Kukuk diff --git a/nis/Makefile b/nis/Makefile index 7c70c9c2a8..e7dd50c1d9 100644 --- a/nis/Makefile +++ b/nis/Makefile @@ -21,7 +21,7 @@ # subdir := nis -headers := $(wildcard rpcsvc/*.[hx]) bits/nislib.h +headers := $(wildcard rpcsvc/*.[hx]) distribute := nss-nis.h nss-nisplus.h nis_intern.h Banner \ nisplus-parser.h diff --git a/nis/nis_cache.c b/nis/nis_cache.c index 8e1d583003..4c0ea7b186 100644 --- a/nis/nis_cache.c +++ b/nis/nis_cache.c @@ -20,25 +20,288 @@ #include <fcntl.h> #include <unistd.h> #include <syslog.h> +#include <string.h> #include <sys/stat.h> #include <sys/mman.h> #include <rpcsvc/nis.h> -#include <rpcsvc/nislib.h> #include <rpcsvc/nis_cache.h> #include <bits/libc-lock.h> #include "nis_intern.h" -/* XXX Only dummy functions in the moment. The real implementation - will follow, if we have a working nis_cachemgr */ +static struct timeval TIMEOUT = {10, 0}; + +#define HEADER_MAGIC 0x07021971 +#define SPACER_MAGIC 0x07654321 + +#define CACHE_VERSION 0x00000001 + +struct cache_header +{ + u_long magic; /* Magic number */ + u_long vers; /* Cache file format version */ + u_short tcp_port; /* tcp port of nis_cachemgr */ + u_short udp_port; /* udp port of nis_cachemgr */ + u_long entries; /* Number of cached objs. */ + off_t used; /* How many space are used ? */ +}; +typedef struct cache_header cache_header; + +struct cache_spacer +{ + u_long magic; /* Magic number */ + u_long hashval; + time_t ctime; /* time we have created this object */ + time_t ttl; /* time to life of this object */ + off_t next_offset; +}; +typedef struct cache_spacer cache_spacer; + +static int cache_fd = -1; +static int clnt_sock; +static caddr_t maddr = NULL; +static size_t msize; +static CLIENT *cache_clnt = NULL; + +/* If there is no cachemgr, we shouldn't use NIS_SHARED_DIRCACHE, if + there is no NIS_SHARED_DIRCACHE, we couldn't use nis_cachemgr. + So, if the clnt_call to nis_cachemgr fails, we also close the cache file. + But another thread could read the cache => lock the cache_fd and cache_clnt + variables with the same lock */ +__libc_lock_define_initialized (static, mgrlock) + +/* close file handles and nis_cachemgr connection */ +static void +__cache_close (void) +{ + if (cache_fd != -1) + { + close (cache_fd); + cache_fd = -1; + } + if (cache_clnt != NULL) + { + clnt_destroy (cache_clnt); + close (clnt_sock); + cache_clnt = NULL; + } +} + +/* open the cache file and connect to nis_cachemgr */ +static bool_t +__cache_open (void) +{ + struct sockaddr_in sin; + cache_header hptr; + + if ((cache_fd = open (CACHEFILE, O_RDONLY)) == -1) + return FALSE; + + if (read (cache_fd, &hptr, sizeof (cache_header)) == -1 + || lseek (cache_fd, 0, SEEK_SET) < 0) + { + close (cache_fd); + cache_fd = -1; + return FALSE; + } + if (hptr.magic != HEADER_MAGIC) + { + close (cache_fd); + cache_fd = -1; + syslog (LOG_ERR, _("NIS+: cache file is corrupt!")); + return FALSE; + } + + memset (&sin, '\0', sizeof (sin)); + sin.sin_family = AF_INET; + clnt_sock = RPC_ANYSOCK; + sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + sin.sin_port = htons (hptr.tcp_port); + cache_clnt = clnttcp_create (&sin, CACHEPROG, CACHE_VER_1, &clnt_sock, 0, 0); + if (cache_clnt == NULL) + { + close (cache_fd); + cache_fd = -1; + return FALSE; + } + /* If the program exists, close the socket */ + if (fcntl (clnt_sock, F_SETFD, FD_CLOEXEC) == -1) + perror (_("fcntl: F_SETFD")); + return TRUE; +} + +/* Ask the cache manager to update directory 'name' + for us (because the ttl has expired). */ +static nis_error +__cache_refresh (nis_name name) +{ + char clnt_res = 0; + nis_error result = NIS_SUCCESS; + + __libc_lock_lock (mgrlock); + + if (cache_clnt == NULL) + result = NIS_FAIL; + else if (clnt_call (cache_clnt, NIS_CACHE_REFRESH_ENTRY, + (xdrproc_t) xdr_wrapstring, (caddr_t) name, + (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) + != RPC_SUCCESS) + { + __cache_close (); + result = NIS_FAIL; + } + + __libc_lock_unlock (mgrlock); + + return result; +} + +static nis_error +__cache_find (const_nis_name name, directory_obj **obj) +{ + unsigned long hash; + struct cache_header *hptr; + struct cache_spacer *cs; + struct directory_obj *dir; + XDR xdrs; + caddr_t addr, ptr; + time_t now = time (NULL); + + if (maddr == NULL) + return NIS_FAIL; + + hash = __nis_hash (name, strlen(name)); + hptr = (cache_header *)maddr; + if ((hptr->magic != HEADER_MAGIC) || (hptr->vers != CACHE_VERSION)) + { + syslog (LOG_ERR, _("NIS+: cache file is corrupt!")); + return NIS_SYSTEMERROR; + } + cs = (cache_spacer *)(maddr + sizeof (cache_header)); + while (cs->next_offset) + { + if (cs->magic != SPACER_MAGIC) + { + syslog (LOG_ERR, _("NIS+: cache file is corrupt!")); + return NIS_SYSTEMERROR; + } + if (cs->hashval == hash) + { + if ((now - cs->ctime) > cs->ttl) + return NIS_CACHEEXPIRED; + dir = calloc (1, sizeof (directory_obj)); + addr = (caddr_t)cs + sizeof (cache_spacer); + xdrmem_create (&xdrs, addr, cs->next_offset, XDR_DECODE); + xdr_directory_obj (&xdrs, dir); + xdr_destroy (&xdrs); + *obj = dir; + return NIS_SUCCESS; + } + ptr = (caddr_t)cs; + ptr += cs->next_offset + sizeof (struct cache_spacer); + cs = (struct cache_spacer *)ptr; + } + return NIS_NOTFOUND; +} + +static directory_obj * +internal_cache_search (const_nis_name name) +{ + directory_obj *dir; + nis_error res; + int second_refresh = 0; + struct stat s; + + if (cache_fd == -1) + if (__cache_open () == FALSE) + return NULL; + + again: + /* This lock is for nis_cachemgr, so it couldn't write a new cache + file if we reading it */ + if (__nis_lock_cache () == -1) + return NULL; + + if (maddr != NULL) + munmap (maddr, msize); + if (fstat (cache_fd, &s) < 0) + maddr = MAP_FAILED; + else + { + msize = s.st_size; + maddr = mmap (0, msize, PROT_READ, MAP_SHARED, cache_fd, 0); + } + if (maddr == MAP_FAILED) + { + __nis_unlock_cache (); + return NULL; + } + + res = __cache_find (name, &dir); + + munmap (maddr, msize); + maddr = NULL; + /* Allow nis_cachemgr to write a new cachefile */ + __nis_unlock_cache (); + + switch(res) + { + case NIS_CACHEEXPIRED: + if (second_refresh) + { + __cache_close (); + syslog (LOG_WARNING, + _("NIS+: nis_cachemgr failed to refresh object for us")); + return NULL; + } + ++second_refresh; + if (__cache_refresh ((char *) name) != NIS_SUCCESS) + return NULL; + goto again; + break; + case NIS_SUCCESS: + return dir; + default: + return NULL; + } +} + directory_obj * __cache_search (const_nis_name name) { - return NULL; + directory_obj *dir; + + __libc_lock_lock (mgrlock); + + dir = internal_cache_search (name); + + __libc_lock_unlock (mgrlock); + + return dir; } -nis_error +nis_error __cache_add (fd_result *fd) { - return NIS_FAIL; + char clnt_res = 0; + nis_error result = NIS_SUCCESS; + + __libc_lock_lock (mgrlock); + + if (cache_clnt == NULL) + if (__cache_open () == FALSE) + result = NIS_FAIL; + + if (cache_clnt != NULL && + (clnt_call (cache_clnt, NIS_CACHE_ADD_ENTRY, (xdrproc_t) xdr_fd_result, + (caddr_t)fd, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) + != RPC_SUCCESS)) + { + __cache_close (); + result = NIS_RPCERROR; + } + + __libc_lock_unlock (mgrlock); + + return result; } diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c index e80c06d269..eb0f6fec8f 100644 --- a/nss/nss_files/files-XXX.c +++ b/nss/nss_files/files-XXX.c @@ -72,7 +72,7 @@ internal_setent (int stayopen) stream = fopen (DATAFILE, "r"); if (stream == NULL) - status = NSS_STATUS_UNAVAIL; + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; else { /* We have to make sure the file is `closed on exec'. */ diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c index 0a910aa0fe..bf4fa8a2f0 100644 --- a/nss/nss_files/files-alias.c +++ b/nss/nss_files/files-alias.c @@ -49,7 +49,7 @@ internal_setent (void) stream = fopen ("/etc/aliases", "r"); if (stream == NULL) - status = NSS_STATUS_UNAVAIL; + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; else { /* We have to make sure the file is `closed on exec'. */ diff --git a/string/stratcliff.c b/string/stratcliff.c index ebe565968e..6115d2f8db 100644 --- a/string/stratcliff.c +++ b/string/stratcliff.c @@ -1,5 +1,5 @@ /* Test for string function add boundaries of usable memory. - Copyright (C) 1996 Free Software Foundation, Inc. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -41,7 +41,7 @@ main (int argc, char *argv[]) MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); dest = (char *) mmap (NULL, 3*size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - if (adr == (char *)-1L || dest == (char *)-1L) + if (adr == MAP_FAILED || dest == MAP_FAILED) { if (errno == ENOSYS) puts ("No test, mmap not available."); diff --git a/string/tester.c b/string/tester.c index 23d0af8acb..0e65442063 100644 --- a/string/tester.c +++ b/string/tester.c @@ -107,6 +107,19 @@ main (void) (void) strcpy (one, ""); equal (one, "", 7); /* Boundary condition. */ + /* A closely related function is stpcpy. */ + it = "stpcpy"; + check ((stpcpy (one, "abcde") - one) == 5, 1); + equal (one, "abcde", 2); + + check ((stpcpy (one, "x") - one) == 1, 3); + equal (one, "x", 4); /* Writeover. */ + equal (one+2, "cde", 5); /* Wrote too much? */ + + check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 6); + equal (one, "abc", 7); + equal (one + 4, "e", 8); + /* stpncpy. */ it = "stpncpy"; diff --git a/sunrpc/Makefile b/sunrpc/Makefile index ad21cb251e..d4595482a2 100644 --- a/sunrpc/Makefile +++ b/sunrpc/Makefile @@ -64,7 +64,7 @@ routines := auth_none auth_unix authuxprot bindrsvprt \ pmap_prot2 pmap_rmt rpc_prot rpc_common rpc_cmsg \ svc svc_auth svc_authux svc_raw svc_run svc_simple \ svc_tcp svc_udp xdr xdr_array xdr_float xdr_mem \ - xdr_rec xdr_ref xdr_stdio publickey + xdr_rec xdr_ref xdr_stdio publickey xdr_sizeof others := rpcinfo install-bin := rpcgen diff --git a/sunrpc/rpc/xdr.h b/sunrpc/rpc/xdr.h index d0ab0d0cf6..2c6522d849 100644 --- a/sunrpc/rpc/xdr.h +++ b/sunrpc/rpc/xdr.h @@ -288,6 +288,7 @@ extern bool_t xdr_reference __P ((XDR * __xdrs, caddr_t * __pp, u_int __size, extern bool_t xdr_pointer __P ((XDR * __xdrs, char **__objpp, u_int __obj_size, xdrproc_t __xdr_obj)); extern bool_t xdr_wrapstring __P ((XDR * __xdrs, char **__cpp)); +extern u_long xdr_sizeof __P ((xdrproc_t, void *)); /* * Common opaque bytes objects used by many rpc protocols; diff --git a/sunrpc/xdr_sizeof.c b/sunrpc/xdr_sizeof.c new file mode 100644 index 0000000000..72403e0a26 --- /dev/null +++ b/sunrpc/xdr_sizeof.c @@ -0,0 +1,157 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * xdr_sizeof.c + * + * Copyright 1990 Sun Microsystems, Inc. + * + * General purpose routine to see how much space something will use + * when serialized using XDR. + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <sys/types.h> +#include <stdlib.h> + +/* ARGSUSED */ +static bool_t +x_putlong (XDR *xdrs, const long *longp) +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return TRUE; +} + +/* ARGSUSED */ +static bool_t +x_putbytes (XDR *xdrs, const char *bp, u_int len) +{ + xdrs->x_handy += len; + return TRUE; +} + +static u_int +x_getpostn (const XDR *xdrs) +{ + return xdrs->x_handy; +} + +/* ARGSUSED */ +static bool_t +x_setpostn (XDR *xdrs, u_int len) +{ + /* This is not allowed */ + return FALSE; +} + +static long * +x_inline (XDR *xdrs, int len) +{ + if (len == 0) + { + return NULL; + } + if (xdrs->x_op != XDR_ENCODE) + { + return NULL; + } + if (len < (int) xdrs->x_base) + { + /* x_private was already allocated */ + xdrs->x_handy += len; + return (long *) xdrs->x_private; + } + else + { + /* Free the earlier space and allocate new area */ + if (xdrs->x_private) + free (xdrs->x_private); + if ((xdrs->x_private = (caddr_t) malloc (len)) == NULL) + { + xdrs->x_base = 0; + return NULL; + } + xdrs->x_base = (caddr_t) len; + xdrs->x_handy += len; + return (long *) xdrs->x_private; + } +} + +static int +harmless (void) +{ + /* Always return FALSE/NULL, as the case may be */ + return 0; +} + +static void +x_destroy (XDR *xdrs) +{ + xdrs->x_handy = 0; + xdrs->x_base = 0; + if (xdrs->x_private) + { + free (xdrs->x_private); + xdrs->x_private = NULL; + } + return; +} + +unsigned long +xdr_sizeof (xdrproc_t func, void *data) +{ + XDR x; + struct xdr_ops ops; + bool_t stat; + /* to stop ANSI-C compiler from complaining */ + typedef bool_t (*dummyfunc1) (XDR *, long *); + typedef bool_t (*dummyfunc2) (XDR *, caddr_t, u_int); + + ops.x_putlong = x_putlong; + ops.x_putbytes = x_putbytes; + ops.x_inline = x_inline; + ops.x_getpostn = x_getpostn; + ops.x_setpostn = x_setpostn; + ops.x_destroy = x_destroy; + + /* the other harmless ones */ + ops.x_getlong = (dummyfunc1) harmless; + ops.x_getbytes = (dummyfunc2) harmless; + + x.x_op = XDR_ENCODE; + x.x_ops = &ops; + x.x_handy = 0; + x.x_private = (caddr_t) NULL; + x.x_base = (caddr_t) 0; + + stat = func (&x, data); + if (x.x_private) + free (x.x_private); + return stat == TRUE ? (unsigned) x.x_handy : 0; +} diff --git a/sysdeps/generic/bits/utmp.h b/sysdeps/generic/bits/utmp.h index b8decb0598..ccc318bfa1 100644 --- a/sysdeps/generic/bits/utmp.h +++ b/sysdeps/generic/bits/utmp.h @@ -17,7 +17,7 @@ Boston, MA 02111-1307, USA. */ #ifndef _UTMP_H -#error "Never use <bits/utmp.h> directly; include <utmp.h> instead." +# error "Never use <bits/utmp.h> directly; include <utmp.h> instead." #endif @@ -33,21 +33,23 @@ __BEGIN_DECLS -struct lastlog { - time_t ll_time; - char ll_line[UT_LINESIZE]; - char ll_host[UT_HOSTSIZE]; -}; +struct lastlog + { + time_t ll_time; + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; + }; -struct utmp { - char ut_line[UT_LINESIZE]; - char ut_name[UT_NAMESIZE]; - char ut_host[UT_HOSTSIZE]; - long ut_time; -}; +struct utmp + { + char ut_line[UT_LINESIZE]; + char ut_user[UT_NAMESIZE]; +#define ut_name ut_user + char ut_host[UT_HOSTSIZE]; + long int ut_time; + }; #define _HAVE_UT_HOST 1 /* We have the ut_host field. */ - __END_DECLS diff --git a/sysdeps/generic/bits/utmpx.h b/sysdeps/generic/bits/utmpx.h new file mode 100644 index 0000000000..f85fce0052 --- /dev/null +++ b/sysdeps/generic/bits/utmpx.h @@ -0,0 +1,34 @@ +/* Structures and definitions for the user accounting database. Generic/BSDish + Copyright (C) 1993, 1996, 1997 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _UTMPX_H +#error "Never use <bits/utmpx.h> directly; include <utmpx.h> instead." +#endif + + +#define __UT_NAMESIZE 8 +#define __UT_LINESIZE 8 +#define __UT_HOSTSIZE 16 + +struct utmpx +{ + char ut_line[__UT_LINESIZE]; + char ut_name[__UT_NAMESIZE]; + char ut_host[__UT_HOSTSIZE]; + long ut_time; +}; diff --git a/sysdeps/generic/sys/mman.h b/sysdeps/generic/sys/mman.h index 9c2a1b62ce..6484e028c9 100644 --- a/sysdeps/generic/sys/mman.h +++ b/sysdeps/generic/sys/mman.h @@ -36,38 +36,48 @@ without PROT_READ. The only guarantees are that no writing will be allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ -#define PROT_NONE 0x00 /* No access. */ -#define PROT_READ 0x04 /* Pages can be read. */ -#define PROT_WRITE 0x02 /* Pages can be written. */ -#define PROT_EXEC 0x01 /* Pages can be executed. */ +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x04 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x01 /* Pages can be executed. */ /* Flags contain mapping type, sharing type and options. */ /* Mapping type (must choose one and only one of these). */ -#define MAP_FILE 0x0001 /* Mapped from a file or device. */ -#define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */ -#define MAP_TYPE 0x000f /* Mask for type field. */ +#ifdef __USE_BSD +# define MAP_FILE 0x0001 /* Mapped from a file or device. */ +# define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */ +# define MAP_TYPE 0x000f /* Mask for type field. */ +#endif /* Sharing types (must choose one and only one of these). */ -#define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */ -#define MAP_SHARED 0x0010 /* Share changes. */ -#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */ +#ifdef __USE_BSD +# define MAP_COPY 0x0020 /* Virtual copy of region at mapping time. */ +#endif +#define MAP_SHARED 0x0010 /* Share changes. */ +#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */ /* Other flags. */ -#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ -#define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */ -#define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */ -#define MAP_INHERIT 0x0800 /* Region is retained after exec. */ +#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ +#ifdef __USE_BSD +# define MAP_NOEXTEND 0x0200 /* For MAP_FILE, don't change file size. */ +# define MAP_HASSEMPHORE 0x0400 /* Region may contain semaphores. */ +# define MAP_INHERIT 0x0800 /* Region is retained after exec. */ +#endif /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif + +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -75,34 +85,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. Flags are from the MS_* set. */ -int msync __P ((__caddr_t __addr, size_t __len, int flags)); +extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/i386/i586/stpcpy.S b/sysdeps/i386/i586/stpcpy.S new file mode 100644 index 0000000000..ea24fa709a --- /dev/null +++ b/sysdeps/i386/i586/stpcpy.S @@ -0,0 +1,6 @@ +#define USE_AS_STPCPY +#define STRCPY __stpcpy + +#include <sysdeps/i386/i586/strcpy.S> + +weak_alias (__stpcpy, stpcpy) diff --git a/sysdeps/i386/i586/strcpy.S b/sysdeps/i386/i586/strcpy.S new file mode 100644 index 0000000000..7f89a2c0f7 --- /dev/null +++ b/sysdeps/i386/i586/strcpy.S @@ -0,0 +1,147 @@ +/* strcpy/stpcpy implementation for i586. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef USE_AS_STPCPY +# define STRCPY strcpy +#endif + +#define magic 0xfefefeff + + .text +ENTRY(STRCPY) + pushl %edi + pushl %esi + pushl %ebx + + movl 16(%esp), %edi + movl 20(%esp), %esi + + xorl %eax, %eax + leal -1(%esi), %ecx + + movl $magic, %ebx + andl $3, %ecx + +#ifdef PIC + call 2f +2: popl %edx + /* 0xb is the distance between 2: and 1: but we avoid writing + 1f-2b because the assembler generates worse code. */ + leal 0xb(%edx,%ecx,8), %ecx +#else + leal 1f(,%ecx,8), %ecx +#endif + + jmp *%ecx + + .align 8 +1: + orb (%esi), %al + jz L(end) + stosb + xorl %eax, %eax + incl %esi + + orb (%esi), %al + jz L(end) + stosb + xorl %eax, %eax + incl %esi + + orb (%esi), %al + jz L(end) + stosb + xorl %eax, %eax + incl %esi + +L(1): movl (%esi), %ecx + leal 4(%esi),%esi + + subl %ecx, %eax + addl %ebx, %ecx + + decl %eax + jnc L(3) + + movl %ecx, %edx + xorl %ecx, %eax + + subl %ebx, %edx + andl $~magic, %eax + + jne L(4) + + movl %edx, (%edi) + leal 4(%edi),%edi + + jmp L(1) + +L(3): movl %ecx, %edx + + subl %ebx, %edx + +L(4): movb %dl, (%edi) + testb %dl, %dl + + movl %edx, %eax + jz L(end2) + + shrl $16, %eax + movb %dh, 1(%edi) +#ifdef USE_AS_STPCPY + addl $1, %edi +#endif + + cmpb $0, %dh + jz L(end2) + +#ifdef USE_AS_STPCPY + movb %al, 1(%edi) + addl $1, %edi + + cmpb $0, %al + jz L(end2) + + addl $1, %edi +#else + movb %al, 2(%edi) + testb %al, %al + + leal 3(%edi), %edi + jz L(end2) +#endif + +L(end): movb %ah, (%edi) + +L(end2): +#ifdef USE_AS_STPCPY + movl %edi, %eax +#endif + popl %ebx + popl %esi + popl %edi +#ifndef USE_AS_STPCPY + movl 4(%esp), %eax +#endif + ret +END(STRCPY) diff --git a/sysdeps/i386/i686/Implies b/sysdeps/i386/i686/Implies index 75fde78977..b5c05ec7f2 100644 --- a/sysdeps/i386/i686/Implies +++ b/sysdeps/i386/i686/Implies @@ -1,2 +1,4 @@ -# Code optimized for i586 is better than simple i386 code. -i386/i586 +# Due to the reordering and the oher nifty extensions in the i686 it is +# not really good to use heavily i586 optimized code on a i686. It's +# better to use i486/i386 code. +i386/i486 diff --git a/sysdeps/libm-i387/e_rem_pio2.c b/sysdeps/libm-i387/e_rem_pio2.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/libm-i387/e_rem_pio2.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/libm-i387/e_rem_pio2f.c b/sysdeps/libm-i387/e_rem_pio2f.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/libm-i387/e_rem_pio2f.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/libm-i387/e_rem_pio2l.c b/sysdeps/libm-i387/e_rem_pio2l.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/libm-i387/e_rem_pio2l.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/libm-i387/k_rem_pio2.c b/sysdeps/libm-i387/k_rem_pio2.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/libm-i387/k_rem_pio2.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/libm-i387/k_rem_pio2f.c b/sysdeps/libm-i387/k_rem_pio2f.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/libm-i387/k_rem_pio2f.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/libm-i387/k_rem_pio2l.c b/sysdeps/libm-i387/k_rem_pio2l.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/libm-i387/k_rem_pio2l.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/libm-i387/s_cbrt.S b/sysdeps/libm-i387/s_cbrt.S index 4b9a2b11c6..3f6a0174f2 100644 --- a/sysdeps/libm-i387/s_cbrt.S +++ b/sysdeps/libm-i387/s_cbrt.S @@ -28,34 +28,36 @@ #endif .align ALIGNARG(4) - ASM_TYPE_DIRECTIVE(f1,@object) -f1: .double 0.354895765043919860 - ASM_SIZE_DIRECTIVE(f1) - ASM_TYPE_DIRECTIVE(f2,@object) -f2: .double 1.50819193781584896 - ASM_SIZE_DIRECTIVE(f2) - ASM_TYPE_DIRECTIVE(f3,@object) -f3: .double -2.11499494167371287 - ASM_SIZE_DIRECTIVE(f3) - ASM_TYPE_DIRECTIVE(f4,@object) -f4: .double 2.44693122563534430 - ASM_SIZE_DIRECTIVE(f4) - ASM_TYPE_DIRECTIVE(f5,@object) -f5: .double -1.83469277483613086 - ASM_SIZE_DIRECTIVE(f5) - ASM_TYPE_DIRECTIVE(f6,@object) -f6: .double 0.784932344976639262 - ASM_SIZE_DIRECTIVE(f6) ASM_TYPE_DIRECTIVE(f7,@object) f7: .double -0.145263899385486377 ASM_SIZE_DIRECTIVE(f7) + ASM_TYPE_DIRECTIVE(f6,@object) +f6: .double 0.784932344976639262 + ASM_SIZE_DIRECTIVE(f6) + ASM_TYPE_DIRECTIVE(f5,@object) +f5: .double -1.83469277483613086 + ASM_SIZE_DIRECTIVE(f5) + ASM_TYPE_DIRECTIVE(f4,@object) +f4: .double 2.44693122563534430 + ASM_SIZE_DIRECTIVE(f4) + ASM_TYPE_DIRECTIVE(f3,@object) +f3: .double -2.11499494167371287 + ASM_SIZE_DIRECTIVE(f3) + ASM_TYPE_DIRECTIVE(f2,@object) +f2: .double 1.50819193781584896 + ASM_SIZE_DIRECTIVE(f2) + ASM_TYPE_DIRECTIVE(f1,@object) +f1: .double 0.354895765043919860 + ASM_SIZE_DIRECTIVE(f1) -#define CBRT2 1.2599210498948731648 -#define SQR_CBRT2 1.5874010519681994748 +#define CBRT2 1.2599210498948731648 +#define ONE_CBRT2 0.793700525984099737355196796584 +#define SQR_CBRT2 1.5874010519681994748 +#define ONE_SQR_CBRT2 0.629960524947436582364439673883 ASM_TYPE_DIRECTIVE(factor,@object) -factor: .double 1.0 / SQR_CBRT2 - .double 1.0 / CBRT2 +factor: .double ONE_SQR_CBRT2 + .double ONE_CBRT2 .double 1.0 .double CBRT2 .double SQR_CBRT2 @@ -67,10 +69,10 @@ two54: .byte 0, 0, 0, 0, 0, 0, 0x50, 0x43 #ifdef PIC #define MO(op) op##@GOTOFF(%ebx) -#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f) +#define MOX(op,x) op##@GOTOFF(%ebx,x,1) #else #define MO(op) op -#define MOX(op,x,f) op(,x,f) +#define MOX(op,x) op(x) #endif .text @@ -102,8 +104,13 @@ ENTRY(__cbrt) #endif fmull MO(two54) movl $-54, %ecx +#ifdef PIC + fstpl 8(%esp) + movl 12(%esp), %eax +#else fstpl 4(%esp) movl 8(%esp), %eax +#endif movl %eax, %edx andl $0x7fffffff, %eax @@ -123,11 +130,16 @@ ENTRY(__cbrt) #endif fabs - /* The following code has two track: + /* The following code has two tracks: a) compute the normalized cbrt value b) compute xe/3 and xe%3 The right track computes the value for b) and this is done - in an optimized way by avoiding division. */ + in an optimized way by avoiding division. + + But why two tracks at all? Very easy: efficiency. Some FP + instruction can overlap with a certain amount of integer (and + FP) instructions. So we get (except for the imull) all + instructions for free. */ fld %st(0) /* xm : xm */ @@ -161,20 +173,24 @@ ENTRY(__cbrt) fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */ subl %edx, %ecx faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */ + shll $3, %ecx fmulp /* u*(t2+2*xm) : 2*t2+xm */ fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */ - fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ + fmull MOX(16+factor,%ecx) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ pushl %eax fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */ fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */ - popl %eax fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */ - fstp %st(1) + popl %edx #ifdef PIC + movl 12(%esp), %eax popl %ebx +#else + movl 8(%esp), %eax #endif - testl $0x80000000, 8(%esp) - jz 4f + testl %eax, %eax + fstp %st(1) + jns 4f fchs 4: ret diff --git a/sysdeps/libm-i387/s_cbrtf.S b/sysdeps/libm-i387/s_cbrtf.S index 6978da2d40..a14e04ed2f 100644 --- a/sysdeps/libm-i387/s_cbrtf.S +++ b/sysdeps/libm-i387/s_cbrtf.S @@ -28,22 +28,25 @@ #endif .align ALIGNARG(4) - ASM_TYPE_DIRECTIVE(f1,@object) -f1: .double 0.492659620528969547 - ASM_SIZE_DIRECTIVE(f1) - ASM_TYPE_DIRECTIVE(f2,@object) -f2: .double 0.697570460207922770 - ASM_SIZE_DIRECTIVE(f2) ASM_TYPE_DIRECTIVE(f3,@object) f3: .double 0.191502161678719066 ASM_SIZE_DIRECTIVE(f3) + ASM_TYPE_DIRECTIVE(f2,@object) +f2: .double 0.697570460207922770 + ASM_SIZE_DIRECTIVE(f2) + ASM_TYPE_DIRECTIVE(f1,@object) +f1: .double 0.492659620528969547 + ASM_SIZE_DIRECTIVE(f1) -#define CBRT2 1.2599210498948731648 -#define SQR_CBRT2 1.5874010519681994748 +#define CBRT2 1.2599210498948731648 +#define ONE_CBRT2 0.793700525984099737355196796584 +#define SQR_CBRT2 1.5874010519681994748 +#define ONE_SQR_CBRT2 0.629960524947436582364439673883 ASM_TYPE_DIRECTIVE(factor,@object) -factor: .double 1.0 / SQR_CBRT2 - .double 1.0 / CBRT2 + .align ALIGNARG(4) +factor: .double ONE_SQR_CBRT2 + .double ONE_CBRT2 .double 1.0 .double CBRT2 .double SQR_CBRT2 @@ -55,10 +58,10 @@ two25: .byte 0, 0, 0, 0x4c #ifdef PIC #define MO(op) op##@GOTOFF(%ebx) -#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f) +#define MOX(op,x) op##@GOTOFF(%ebx,x,1) #else #define MO(op) op -#define MOX(op,x,f) op(,x,f) +#define MOX(op,x) op(x) #endif .text @@ -114,11 +117,16 @@ ENTRY(__cbrtf) #endif fabs - /* The following code has two track: + /* The following code has two tracks: a) compute the normalized cbrt value b) compute xe/3 and xe%3 The right track computes the value for b) and this is done - in an optimized way by avoiding division. */ + in an optimized way by avoiding division. + + But why two tracks at all? Very easy: efficiency. Some FP + instruction can overlap with a certain amount of integer (and + FP) instructions. So we get (except for the imull) all + instructions for free. */ fld %st(0) /* xm : xm */ fmull MO(f3) /* f3*xm : xm */ @@ -142,20 +150,24 @@ ENTRY(__cbrtf) fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */ subl %edx, %ecx faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */ + shll $3, %ecx fmulp /* u*(t2+2*xm) : 2*t2+xm */ fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */ - fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ + fmull MOX(16+factor,%ecx) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ pushl %eax fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */ fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */ - popl %eax fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */ - fstp %st(1) + popl %edx #ifdef PIC + movl 8(%esp), %eax popl %ebx +#else + movl 4(%esp), %eax #endif - testl $0x80000000, 4(%esp) - jz 4f + testl %eax, %eax + fstp %st(1) + jns 4f fchs 4: ret diff --git a/sysdeps/libm-i387/s_cbrtl.S b/sysdeps/libm-i387/s_cbrtl.S index b2023d1991..6a3b9a8dc5 100644 --- a/sysdeps/libm-i387/s_cbrtl.S +++ b/sysdeps/libm-i387/s_cbrtl.S @@ -28,52 +28,69 @@ #endif .align ALIGNARG(4) - ASM_TYPE_DIRECTIVE(f1,@object) -f1: .double 0.338058687610520237 - ASM_SIZE_DIRECTIVE(f1) - ASM_TYPE_DIRECTIVE(f2,@object) -f2: .double 1.67595307700780102 - ASM_SIZE_DIRECTIVE(f2) - ASM_TYPE_DIRECTIVE(f3,@object) -f3: .double -2.82414939754975962 - ASM_SIZE_DIRECTIVE(f3) - ASM_TYPE_DIRECTIVE(f4,@object) -f4: .double 4.09559907378707839 - ASM_SIZE_DIRECTIVE(f4) - ASM_TYPE_DIRECTIVE(f5,@object) -f5: .double -4.11151425200350531 - ASM_SIZE_DIRECTIVE(f5) - ASM_TYPE_DIRECTIVE(f6,@object) -f6: .double 2.65298938441952296 - ASM_SIZE_DIRECTIVE(f6) - ASM_TYPE_DIRECTIVE(f7,@object) -f7: .double -0.988553671195413709 - ASM_SIZE_DIRECTIVE(f7) ASM_TYPE_DIRECTIVE(f8,@object) -f8: .double 0.161617097923756032 +f8: .tfloat 0.161617097923756032 ASM_SIZE_DIRECTIVE(f8) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f7,@object) +f7: .tfloat -0.988553671195413709 + ASM_SIZE_DIRECTIVE(f7) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f6,@object) +f6: .tfloat 2.65298938441952296 + ASM_SIZE_DIRECTIVE(f6) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f5,@object) +f5: .tfloat -4.11151425200350531 + ASM_SIZE_DIRECTIVE(f5) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f4,@object) +f4: .tfloat 4.09559907378707839 + ASM_SIZE_DIRECTIVE(f4) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f3,@object) +f3: .tfloat -2.82414939754975962 + ASM_SIZE_DIRECTIVE(f3) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f2,@object) +f2: .tfloat 1.67595307700780102 + ASM_SIZE_DIRECTIVE(f2) + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(f1,@object) +f1: .tfloat 0.338058687610520237 + ASM_SIZE_DIRECTIVE(f1) -#define CBRT2 1.2599210498948731648 -#define SQR_CBRT2 1.5874010519681994748 +#define CBRT2 1.2599210498948731648 +#define ONE_CBRT2 0.793700525984099737355196796584 +#define SQR_CBRT2 1.5874010519681994748 +#define ONE_SQR_CBRT2 0.629960524947436582364439673883 + /* We make the entries in the following table all 16 bytes + wide to avoid having to implement a multiplication by 10. */ ASM_TYPE_DIRECTIVE(factor,@object) -factor: .double 1.0 / SQR_CBRT2 - .double 1.0 / CBRT2 - .double 1.0 - .double CBRT2 - .double SQR_CBRT2 + .align ALIGNARG(4) +factor: .tfloat ONE_SQR_CBRT2 + .byte 0, 0, 0, 0, 0, 0 + .tfloat ONE_CBRT2 + .byte 0, 0, 0, 0, 0, 0 + .tfloat 1.0 + .byte 0, 0, 0, 0, 0, 0 + .tfloat CBRT2 + .byte 0, 0, 0, 0, 0, 0 + .tfloat SQR_CBRT2 ASM_SIZE_DIRECTIVE(factor) ASM_TYPE_DIRECTIVE(two64,@object) + .align ALIGNARG(4) two64: .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43 ASM_SIZE_DIRECTIVE(two64) #ifdef PIC #define MO(op) op##@GOTOFF(%ebx) -#define MOX(op,x,f) op##@GOTOFF(%ebx,x,f) +#define MOX(op,x) op##@GOTOFF(%ebx,x,1) #else #define MO(op) op -#define MOX(op,x,f) op(,x,f) +#define MOX(op,x) op(x) #endif .text @@ -97,7 +114,7 @@ ENTRY(__cbrtl) #endif cmpl $0, %eax - je 2f + jne 2f #ifdef PIC fldt 8(%esp) @@ -106,8 +123,13 @@ ENTRY(__cbrtl) #endif fmull MO(two64) movl $-64, %ecx +#ifdef PIC + fstpt 8(%esp) + movl 16(%esp), %eax +#else fstpt 4(%esp) movl 12(%esp), %eax +#endif movl %eax, %edx andl $0x7fff, %eax @@ -126,31 +148,45 @@ ENTRY(__cbrtl) #endif fabs - /* The following code has two track: + /* The following code has two tracks: a) compute the normalized cbrt value b) compute xe/3 and xe%3 The right track computes the value for b) and this is done - in an optimized way by avoiding division. */ + in an optimized way by avoiding division. - fld %st(0) /* xm : xm */ + But why two tracks at all? Very easy: efficiency. Some FP + instruction can overlap with a certain amount of integer (and + FP) instructions. So we get (except for the imull) all + instructions for free. */ - fmull MO(f7) /* f7*xm : xm */ + fldt MO(f8) /* f8 : xm */ + fmul %st(1) /* f8*xm : xm */ + + fldt MO(f7) + faddp /* f7+f8*xm : xm */ + fmul %st(1) /* (f7+f8*xm)*xm : xm */ movl $1431655766, %eax - faddl MO(f6) /* f6+f7*xm : xm */ + fldt MO(f6) + faddp /* f6+(f7+f8*xm)*xm : xm */ imull %ecx - fmul %st(1) /* (f6+f7*xm)*xm : xm */ + fmul %st(1) /* (f6+(f7+f8*xm)*xm)*xm : xm */ movl %ecx, %eax - faddl MO(f5) /* f5+(f6+f7*xm)*xm : xm */ + fldt MO(f5) + faddp /* f5+(f6+(f7+f8*xm)*xm)*xm : xm */ sarl $31, %eax - fmul %st(1) /* (f5+(f6+f7*xm)*xm)*xm : xm */ + fmul %st(1) /* (f5+(f6+(f7+f8*xm)*xm)*xm)*xm : xm */ subl %eax, %edx - faddl MO(f4) /* f4+(f5+(f6+f7*xm)*xm)*xm : xm */ - fmul %st(1) /* (f4+(f5+(f6+f7*xm)*xm)*xm)*xm : xm */ - faddl MO(f3) /* f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm : xm */ - fmul %st(1) /* (f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm : xm */ - faddl MO(f2) /* f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm : xm */ - fmul %st(1) /* (f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm)*xm : xm */ - faddl MO(f1) /* u:=f1+(f2+(f3+(f4+(f5+(f6+f7*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f4) + faddp /* f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm : xm */ + fmul %st(1) /* (f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f3) + faddp /* f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm : xm */ + fmul %st(1) /* (f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f2) + faddp /* f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fmul %st(1) /* (f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm)*xm : xm */ + fldt MO(f1) + faddp /* u:=f1+(f2+(f3+(f4+(f5+(f6+(f7+f8*xm)*xm)*xm)*xm)*xm)*xm)*xm : xm */ fld %st /* u : u : xm */ fmul %st(1) /* u*u : u : xm */ @@ -164,19 +200,24 @@ ENTRY(__cbrtl) fadd %st(0) /* 2*t2 : t2+2*xm : u : xm */ subl %edx, %ecx faddp %st, %st(3) /* t2+2*xm : u : 2*t2+xm */ + shll $4, %ecx fmulp /* u*(t2+2*xm) : 2*t2+xm */ fdivp %st, %st(1) /* u*(t2+2*xm)/(2*t2+xm) */ - fmull MOX(16+factor,%ecx,8) /* u*(t2+2*xm)/(2*t2+xm)*FACT */ + fldt MOX(32+factor,%ecx) + fmulp /* u*(t2+2*xm)/(2*t2+xm)*FACT */ pushl %eax fildl (%esp) /* xe/3 : u*(t2+2*xm)/(2*t2+xm)*FACT */ fxch /* u*(t2+2*xm)/(2*t2+xm)*FACT : xe/3 */ - popl %eax fscale /* u*(t2+2*xm)/(2*t2+xm)*FACT*2^xe/3 */ - fstp %st(1) + popl %edx #ifdef PIC + movl 16(%esp), %eax popl %ebx +#else + movl 12(%esp), %eax #endif - testl $0x8000, 12(%esp) + testl $0x8000, %eax + fstp %st(1) jz 4f fchs 4: ret diff --git a/sysdeps/libm-ieee754/s_isinf.c b/sysdeps/libm-ieee754/s_isinf.c index 6f76ce1fba..4f063d09c5 100644 --- a/sysdeps/libm-ieee754/s_isinf.c +++ b/sysdeps/libm-ieee754/s_isinf.c @@ -16,12 +16,8 @@ static char rcsid[] = "$NetBSD: s_isinf.c,v 1.3 1995/05/11 23:20:14 jtc Exp $"; #include "math.h" #include "math_private.h" -#ifdef __STDC__ - int __isinf(double x) -#else - int __isinf(x) - double x; -#endif +int +__isinf (double x) { int32_t hx,lx; EXTRACT_WORDS(hx,lx,x); diff --git a/sysdeps/libm-ieee754/s_isinff.c b/sysdeps/libm-ieee754/s_isinff.c index 18a0b5e03b..efc0935251 100644 --- a/sysdeps/libm-ieee754/s_isinff.c +++ b/sysdeps/libm-ieee754/s_isinff.c @@ -15,12 +15,8 @@ static char rcsid[] = "$NetBSD: s_isinff.c,v 1.3 1995/05/11 23:20:21 jtc Exp $"; #include "math.h" #include "math_private.h" -#ifdef __STDC__ - int __isinff(float x) -#else - int __isinff(x) - float x; -#endif +int +__isinff (float x) { int32_t ix,t; GET_FLOAT_WORD(ix,x); diff --git a/sysdeps/libm-ieee754/s_isinfl.c b/sysdeps/libm-ieee754/s_isinfl.c index b499821441..697534ed0d 100644 --- a/sysdeps/libm-ieee754/s_isinfl.c +++ b/sysdeps/libm-ieee754/s_isinfl.c @@ -16,12 +16,8 @@ static char rcsid[] = "$NetBSD: $"; #include "math.h" #include "math_private.h" -#ifdef __STDC__ - int __isinfl(long double x) -#else - int __isinfl(x) - long double x; -#endif +int +__isinfl (long double x) { int32_t se,hx,lx; GET_LDOUBLE_WORDS(se,hx,lx,x); diff --git a/sysdeps/libm-ieee754/s_lround.c b/sysdeps/libm-ieee754/s_lround.c index 0f91280a79..974dbde050 100644 --- a/sysdeps/libm-ieee754/s_lround.c +++ b/sysdeps/libm-ieee754/s_lround.c @@ -26,40 +26,40 @@ #ifdef NO_LONG_DOUBLE /* The `long double' is in fact the IEEE `double' type. */ +/* This code does not presently work. */ + long int __lround (long double x) { int32_t j0; u_int32_t i1, i0; long int result; + int sign; EXTRACT_WORDS (i0, i1, x); j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; if (j0 < 20) { if (j0 < 0) - result = j0 < -1 ? 0 : ((i0 & 0x80000000) ? -1 : 1); + result = j0 < -1 ? 0 : sign; else { u_int32_t i = 0xfffff >> j0; + i0 |= 0x100000; if (((i0 & i) | i1) == 0) - result = (long int) ((i0 & 0xfffff) | 0x100000) >> j0; + result = i0 >> j0; else - { - /* X is not integral. */ - u_int32_t j = i0 + (0x80000 >> j0); - if (j < i0) - result = (long int) 0x80000 >> (20 - j0); - else - result = (j | 0x100000) >> (20 - j0); - } + /* X is not integral. */ + result = (i0 + (0x80000 >> j0)) >> (20 - j0); } } else if (j0 >= 8 * sizeof (long int) || j0 > 51) { /* The number is too large. It is left implementation defined what happens. */ - result = (long int) x; + return (long int) x; } else { @@ -97,7 +97,7 @@ __lround (long double x) } } - return i0 & 0x80000000 ? -result : result; + return sign * result; } #else long int diff --git a/sysdeps/m68k/fpu/e_rem_pio2.c b/sysdeps/m68k/fpu/e_rem_pio2.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/m68k/fpu/e_rem_pio2.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/m68k/fpu/e_rem_pio2f.c b/sysdeps/m68k/fpu/e_rem_pio2f.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/m68k/fpu/e_rem_pio2f.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/m68k/fpu/e_rem_pio2l.c b/sysdeps/m68k/fpu/e_rem_pio2l.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/m68k/fpu/e_rem_pio2l.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/m68k/fpu/k_rem_pio2.c b/sysdeps/m68k/fpu/k_rem_pio2.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/m68k/fpu/k_rem_pio2.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/m68k/fpu/k_rem_pio2f.c b/sysdeps/m68k/fpu/k_rem_pio2f.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/m68k/fpu/k_rem_pio2f.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/m68k/fpu/k_rem_pio2l.c b/sysdeps/m68k/fpu/k_rem_pio2l.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/sysdeps/m68k/fpu/k_rem_pio2l.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/sysdeps/mach/bits/libc-lock.h b/sysdeps/mach/bits/libc-lock.h index 79a1e00464..17eeefcdb5 100644 --- a/sysdeps/mach/bits/libc-lock.h +++ b/sysdeps/mach/bits/libc-lock.h @@ -75,6 +75,27 @@ typedef cthread_key_t __libc_key_t; (*__save_FCT)(__save_ARG); \ } +/* Use mutexes as once control variables. */ + +struct __libc_once + { + __libc_lock_t lock; + int done; + }; + +#define __libc_once_define(CLASS,NAME) \ + CLASS struct __libc_once NAME = { MUTEX_INITIALZER, 0 } + + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + __libc_lock_lock (ONCE_CONTROL.lock); \ + if (!ONCE_CONTROL.done) \ + (INIT_FUNCTION) (); \ + ONCE_CONTROL.done = 1; \ + __libc_lock_lock (ONCE_CONTROL.lock); \ + } while (0) #ifdef _LIBC /* We need portable names for some functions. E.g., when they are diff --git a/sysdeps/mach/hurd/Dist b/sysdeps/mach/hurd/Dist index 62fe4d96c6..e6067b8a73 100644 --- a/sysdeps/mach/hurd/Dist +++ b/sysdeps/mach/hurd/Dist @@ -1,3 +1,4 @@ errnos.awk err_hurd.sub libc-ldscript libc_p-ldscript +cthreads.c diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile index 43d5eb9a2d..bf1c3b02bc 100644 --- a/sysdeps/mach/hurd/Makefile +++ b/sysdeps/mach/hurd/Makefile @@ -18,6 +18,9 @@ ifdef in-Makerules +subdirs := $(filter-out sunrpc,$(subdirs)) # XXX skip broken dirs +# See hurd/Makefile for commands that install some crucial sunrpc headers. + # Look for header files in hurd/ under the top-level library source directory. # Look for generated header files where they get created. includes += -I$(..)hurd -I$(common-objpfx)hurd/ @@ -33,7 +36,6 @@ inhibit-unix-syscalls = yes # be compatible with some existing binaries for that system. inhibit-glue = yes - ifeq (,$(filter mach hurd,$(subdir))) # Subdirectories other than hurd/ might use the generated Hurd headers. # So make sure we get a chance to run in hurd/ to make them before all else. @@ -48,6 +50,12 @@ $(patsubst %,$(hurd-objpfx)hurd/%.%,auth io fs process): $(MAKE) -C $(..)hurd generated no_deps=t endif +# Hurd profil.c includes this file, so give a rule to make it. +ifeq ($(subdir),gmon) +$(common-objpfx)hurd/../mach/RPC_task_get_sampled_pcs.c: + $(MAKE) -C $(..)mach generated no_deps=t +endif + # Generate errnos.h from the section of the manual that lists all the errno # codes. @@ -115,11 +123,6 @@ $(inst_libdir)/libc.so: $(rpcuserlibs) ifeq (elf,$(subdir)) $(objpfx)librtld.so: $(rpcuserlibs:.so=_pic.a) endif - -# We need the CThreads interface. -ifeq (misc,$(subdir)) -sysdep_routines += cthreads -endif endif # in-Makerules diff --git a/sysdeps/mach/hurd/Subdirs b/sysdeps/mach/hurd/Subdirs index 16b8348437..739919f4b1 100644 --- a/sysdeps/mach/hurd/Subdirs +++ b/sysdeps/mach/hurd/Subdirs @@ -1 +1,2 @@ hurd +login diff --git a/sysdeps/mach/hurd/profil.c b/sysdeps/mach/hurd/profil.c index d3c5131b10..d76cc25a3c 100644 --- a/sysdeps/mach/hurd/profil.c +++ b/sysdeps/mach/hurd/profil.c @@ -34,10 +34,20 @@ static size_t maxsamples; static size_t pc_offset; static size_t sample_scale; static sampled_pc_seqno_t seqno; -static struct mutex lock = MUTEX_INITIALIZER; +static spin_lock_t lock = SPIN_LOCK_INITIALIZER; static mach_msg_timeout_t collector_timeout; /* ms between collections. */ static int profile_tick; +/* Reply port used by profiler thread */ +static mach_port_t profil_reply_port; + +/* Forwards */ +static kern_return_t profil_task_get_sampled_pcs (mach_port_t, + sampled_pc_seqno_t *, + sampled_pc_array_t, + mach_msg_type_number_t *); +static void fetch_samples (void); + /* Enable statistical profiling, writing samples of the PC into at most SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling is enabled, the system examines the user PC and increments @@ -87,7 +97,7 @@ update_waiter (u_short *sample_buffer, size_t size, size_t offset, u_int scale) } int -__profile_frequency () +__profile_frequency (void) { return profile_tick; } @@ -97,13 +107,20 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale) { error_t err; - __mutex_lock (&lock); + __spin_lock (&lock); if (scale == 0) { /* Disable profiling. */ int count; - __thread_suspend (profile_thread); + + if (profile_thread != MACH_PORT_NULL) + __thread_suspend (profile_thread); + + /* Fetch the last set of samples */ + if (sample_scale) + fetch_samples (); + err = __task_disable_pc_sampling (__mach_task_self (), &count); sample_scale = 0; seqno = 0; @@ -111,57 +128,102 @@ profil (u_short *sample_buffer, size_t size, size_t offset, u_int scale) else err = update_waiter (sample_buffer, size, offset, scale); - __mutex_unlock (&lock); + __spin_unlock (&lock); return err ? __hurd_fail (err) : 0; } +/* Fetch PC samples. This function must be very careful not to depend + on Hurd threadvar variables. We arrange that by using a special + stub arranged for at the end of this file. */ static void -profile_waiter (void) +fetch_samples (void) { sampled_pc_t pc_samples[MAX_PC_SAMPLES]; mach_msg_type_number_t nsamples, i; - mach_port_t rcv = __mach_reply_port (); - mach_msg_header_t msg; error_t err; - while (1) + nsamples = MAX_PC_SAMPLES; + + err = profil_task_get_sampled_pcs (__mach_task_self (), &seqno, + pc_samples, &nsamples); + if (err) { - __mutex_lock (&lock); + static error_t special_profil_failure; + static volatile int a, b, c; - nsamples = sizeof pc_samples / sizeof pc_samples[0]; - err = __task_get_sampled_pcs (__mach_task_self (), &seqno, - pc_samples, &nsamples); - assert_perror (err); + special_profil_failure = err; + a = 1; + b = 0; + while (1) + c = a / b; + } - for (i = 0; i < nsamples; ++i) - { - size_t idx = (((pc_samples[i].pc - pc_offset) / 2) * - sample_scale / 65536); - if (idx < maxsamples) - ++samples[idx]; - } + for (i = 0; i < nsamples; ++i) + { + /* Do arithmetic in long long to avoid overflow problems. */ + long long pc_difference = pc_samples[i].pc - pc_offset; + size_t idx = ((pc_difference / 2) * sample_scale) / 65536; + if (idx < maxsamples) + ++samples[idx]; + } +} + + +/* This function must be very careful not to depend on Hurd threadvar + variables. We arrange that by using special stubs arranged for at the + end of this file. */ +static void +profile_waiter (void) +{ + mach_msg_header_t msg; + mach_port_t timeout_reply_port; + + profil_reply_port = __mach_reply_port (); + timeout_reply_port = __mach_reply_port (); - __vm_deallocate (__mach_task_self (), - (vm_address_t) pc_samples, - nsamples * sizeof *pc_samples); + while (1) + { + __spin_lock (&lock); + + fetch_samples (); - __mutex_unlock (&lock); + __spin_unlock (&lock); __mach_msg (&msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof msg, - rcv, collector_timeout, MACH_PORT_NULL); + timeout_reply_port, collector_timeout, MACH_PORT_NULL); } } -data_set_element (_hurd_fork_locks, lock); +/* Fork interaction */ + +/* Before fork, lock the interlock so that we are in a clean state. */ +static void +fork_profil_prepare (void) +{ + __spin_lock (&lock); +} +text_set_element (_hurd_fork_prepare_hook, fork_profil_prepare); + +/* In the parent, unlock the interlock once fork is complete. */ +static void +fork_profil_parent (void) +{ + __spin_unlock (&lock); +} +text_set_element (_hurd_fork_parent_hook, fork_profil_parent); +/* In the childs, unlock the interlock, and start a profiling thread up + if necessary. */ static void -fork_profil (void) +fork_profil_child (void) { u_short *sb; size_t n, o, ss; error_t err; + __spin_unlock (&lock); + if (profile_thread != MACH_PORT_NULL) { __mach_port_deallocate (__mach_task_self (), profile_thread); @@ -183,4 +245,37 @@ fork_profil (void) assert_perror (err); } } -text_set_element (_hurd_fork_child_hook, fork_profil); +text_set_element (_hurd_fork_child_hook, fork_profil_child); + + + + +/* Special RPC stubs for profile_waiter are made by including the normal + source code, with special CPP state to prevent it from doing the + usual thing. */ + +/* Include these first; then our #define's will take full effect, not + being overridden. */ +#include <mach/mig_support.h> + +/* This need not do anything; it is always associated with errors, which + are fatal in profile_waiter anyhow. */ +#define __mig_put_reply_port(foo) + +/* Use our static variable instead of the usual threadvar mechanism for + this. */ +#define __mig_get_reply_port() profil_reply_port + +/* Make the functions show up as static */ +#define mig_external static + +/* Turn off the attempt to generate ld aliasing records. */ +#undef weak_alias +#define weak_alias(a,b) + +/* And change their names to avoid confusing disasters. */ +#define __vm_deallocate_rpc profil_vm_deallocate +#define __task_get_sampled_pcs profil_task_get_sampled_pcs + +/* And include the source code */ +#include <../mach/RPC_task_get_sampled_pcs.c> diff --git a/sysdeps/mips/Dist b/sysdeps/mips/Dist index ad6ea0313a..9b6fd71f01 100644 --- a/sysdeps/mips/Dist +++ b/sysdeps/mips/Dist @@ -1 +1,3 @@ setjmp_aux.c +rtld-ldscript.in +rtld-parms diff --git a/sysdeps/mips/mips64/Dist b/sysdeps/mips/mips64/Dist index ad6ea0313a..4cde3d0e5d 100644 --- a/sysdeps/mips/mips64/Dist +++ b/sysdeps/mips/mips64/Dist @@ -1 +1,2 @@ setjmp_aux.c +rtld-parms diff --git a/sysdeps/mips/mipsel/Dist b/sysdeps/mips/mipsel/Dist new file mode 100644 index 0000000000..98a10ec269 --- /dev/null +++ b/sysdeps/mips/mipsel/Dist @@ -0,0 +1 @@ +rtld-parms diff --git a/sysdeps/posix/defs.c b/sysdeps/posix/defs.c index 4a12292f55..bc0d34bf15 100644 --- a/sysdeps/posix/defs.c +++ b/sysdeps/posix/defs.c @@ -32,7 +32,7 @@ { \ _IOMAGIC, \ NULL, NULL, NULL, NULL, 0, \ - (PTR) fd, \ + (void *) fd, \ { readwrite, /* ... */ }, \ { NULL, NULL, NULL, NULL, NULL }, \ { NULL, NULL }, \ diff --git a/sysdeps/powerpc/Dist b/sysdeps/powerpc/Dist index ae16c0f8fb..282cf1394e 100644 --- a/sysdeps/powerpc/Dist +++ b/sysdeps/powerpc/Dist @@ -1,2 +1,3 @@ fenv_const.c fenv_libc.h +quad_float.h diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile index 4100901d62..0a50956640 100644 --- a/sysdeps/powerpc/Makefile +++ b/sysdeps/powerpc/Makefile @@ -1,3 +1,13 @@ ifeq ($(subdir),math) -libm-support += fenv_const +libm-support += fenv_const fe_nomask t_sqrt + +# These routines have not been tested, so it's probable they don't work; +# and they don't provide the complete list of FP routines. So there's +# no point in compiling them. +#sysdep_routines += q_feq q_fne q_utoq q_dtoq q_itoq q_stoq q_neg q_ulltoq \ +# q_lltoq q_qtou q_qtoi q_qtoull q_qtoll q_qtos + +tests += test-arith test-arithf +LDLIBS-test-arith = libm +LDLIBS-test-arithf = libm endif diff --git a/sysdeps/powerpc/bits/fenv.h b/sysdeps/powerpc/bits/fenv.h index 08d998e118..8c26a2548f 100644 --- a/sysdeps/powerpc/bits/fenv.h +++ b/sysdeps/powerpc/bits/fenv.h @@ -37,9 +37,10 @@ enum /* ... except for FE_INVALID, for which we use bit 31. FE_INVALID actually corresponds to bits 7 through 12 and 21 through 23 in the FPSCR, but we can't use that because the current draft - says that it must be a power of 2. Instead we use bit 24 which - is the enable bit for all the FE_INVALID exceptions. */ - FE_INVALID = 1 << 31-24, + says that it must be a power of 2. Instead we use bit 2 which + is the summary bit for all the FE_INVALID exceptions, which + kind of makes sense. */ + FE_INVALID = 1 << 31-2, #define FE_INVALID FE_INVALID #ifdef __USE_GNU @@ -69,19 +70,22 @@ enum FE_INVALID_IMZ = 1 << 31-11, #define FE_INVALID_IMZ FE_INVALID_IMZ - /* Comparison with NaN or SNaN. */ + /* Comparison with NaN or SNaN. */ FE_INVALID_COMPARE = 1 << 31-12, #define FE_INVALID_COMPARE FE_INVALID_COMPARE - /* Invalid operation flag for software (not set by hardware). */ + /* Invalid operation flag for software (not set by hardware). */ + /* Note that some chips don't have this implemented, presumably + because no-one expected anyone to write software for them %-). */ FE_INVALID_SOFTWARE = 1 << 31-21, #define FE_INVALID_SOFTWARE FE_INVALID_SOFTWARE - /* Square root of negative number (including -Inf). */ + /* Square root of negative number (including -Inf). */ + /* Note that some chips don't have this implemented. */ FE_INVALID_SQRT = 1 << 31-22, #define FE_INVALID_SQRT FE_INVALID_SQRT - /* Conversion-to-integer of a NaN or a number too large or too small. */ + /* Conversion-to-integer of a NaN or a number too large or too small. */ FE_INVALID_INTEGER_CONVERSION = 1 << 31-23, #define FE_INVALID_INTEGER_CONVERSION FE_INVALID_INTEGER_CONVERSION @@ -122,7 +126,53 @@ extern const fenv_t __fe_dfl_env; #define FE_DFL_ENV (&__fe_dfl_env) #ifdef __USE_GNU -/* Floating-point environment where none of the exceptions are masked. */ -extern const fenv_t __fe_nomask_env; -# define FE_NOMASK_ENV (&__fe_nomask_env) +/* Floating-point environment where all exceptions are enabled. Note that + this is not sufficient to give you SIGFPE. */ +extern const fenv_t __fe_enabled_env; +# define FE_ENABLED_ENV (&__fe_enabled_env) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. */ +extern const fenv_t __fe_nonieee_env; +# define FE_NONIEEE_ENV (&__fe_nonieee_env) + +/* Floating-point environment with all exceptions enabled. Note that + just evaluating this value will set the processor into 'FPU + exceptions imprecise recoverable' mode, which may cause a significant + performance penalty (but have no other visible effect). */ +extern const fenv_t *__fe_nomask_env __P ((void)); +# define FE_NOMASK_ENV (__fe_nomask_env ()) #endif + +#ifdef __OPTIMIZE__ +/* Inline definition for fegetround. */ +# define fegetround() \ + (__extension__ ({ int __fegetround_result; \ + __asm__ ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; })) + +/* Inline definition for feraiseexcept. */ +# define feraiseexcept(__excepts) \ + (__extension__ ({ if (__builtin_constant_p (__excepts) \ + && ((__excepts) & -(__excepts)) == 0 \ + && (__excepts) != FE_INVALID) { \ + if ((__excepts) != 0) \ + __asm__ __volatile__ \ + ("mtfsb1 %0" \ + : : "i"(32 - __builtin_ffs (__excepts))); \ + } else \ + (feraiseexcept) (__excepts); })) + +/* Inline definition for feclearexcept. */ +# define feclearexcept(__excepts) \ + (__extension__ ({ if (__builtin_constant_p (__excepts) \ + && ((__excepts) & -(__excepts)) == 0 \ + && (__excepts) != FE_INVALID) { \ + if ((__excepts) != 0) \ + __asm__ __volatile__ \ + ("mtfsb0 %0" \ + : : "i"(32 - __builtin_ffs (__excepts))); \ + } else \ + (feclearexcept) (__excepts); })) +#endif /* __OPTIMIZE__ */ diff --git a/sysdeps/powerpc/bits/mathdef.h b/sysdeps/powerpc/bits/mathdef.h index c0e6caa843..9f91863333 100644 --- a/sysdeps/powerpc/bits/mathdef.h +++ b/sysdeps/powerpc/bits/mathdef.h @@ -30,7 +30,7 @@ #ifdef __GNUC__ #if __STDC__ == 1 -/* In GNU or ANSI mode, gcc leaves `float' expressions as-is, I think. */ +/* In GNU or ANSI mode, gcc leaves `float' expressions as-is. */ typedef float float_t; /* `float' expressions are evaluated as `float'. */ typedef double double_t; /* `double' expressions are evaluated as @@ -70,3 +70,7 @@ typedef double double_t; #define INFINITY HUGE_VAL #endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +#define FP_ILOGB0 0x80000001 +#define FP_ILOGBNAN 0x7fffffff diff --git a/sysdeps/powerpc/dl-machine.h b/sysdeps/powerpc/dl-machine.h index c9d1d7332a..74436d15c1 100644 --- a/sysdeps/powerpc/dl-machine.h +++ b/sysdeps/powerpc/dl-machine.h @@ -57,10 +57,11 @@ #define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm) #define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh) -#define PPC_DCBST(where) asm __volatile__ ("dcbst 0,%0" : : "r"(where)) -#define PPC_SYNC asm __volatile__ ("sync") -#define PPC_ISYNC asm __volatile__ ("sync; isync") -#define PPC_ICBI(where) asm __volatile__ ("icbi 0,%0" : : "r"(where)) +#define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where)) +#define PPC_SYNC asm volatile ("sync") +#define PPC_ISYNC asm volatile ("sync; isync") +#define PPC_ICBI(where) asm volatile ("icbi 0,%0" : : "r"(where)) +#define PPC_DIE asm volatile ("tweq 0,0") /* Use this when you've modified some code, but it won't be in the instruction fetch queue (or when it doesn't matter if it is). */ @@ -147,9 +148,9 @@ elf_machine_load_address (void) /* The PLT uses Elf32_Rela relocs. */ #define elf_machine_relplt elf_machine_rela - /* This code is used in dl-runtime.c to call the `fixup' function - and then redirect to the address it returns. It is called - from code built in the PLT by elf_machine_runtime_setup. */ +/* This code is used in dl-runtime.c to call the `fixup' function + and then redirect to the address it returns. It is called + from code built in the PLT by elf_machine_runtime_setup. */ #define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\ .section \".text\" .align 2 @@ -511,11 +512,14 @@ elf_machine_lazy_rel (struct link_map *map, const Elf32_Rela *reloc) static inline void elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, const Elf32_Sym *sym, const struct r_found_version *version, - Elf32_addr *const reloc_addr) + Elf32_Addr *const reloc_addr) { +#ifndef RTLD_BOOTSTRAP const Elf32_Sym *const refsym = sym; +#endif Elf32_Word loadbase, finaladdr; const int rinfo = ELF32_R_TYPE (reloc->r_info); + extern char **_dl_argv; if (rinfo == R_PPC_NONE) return; @@ -598,7 +602,6 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, if (sym->st_size > refsym->st_size || (_dl_verbose && sym->st_size < refsym->st_size)) { - extern char **_dl_argv; const char *strtab; strtab = ((void *) map->l_addr @@ -631,11 +634,31 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, plt = (Elf32_Word *)((char *)map->l_addr + map->l_info[DT_PLTGOT]->d_un.d_val); index = (reloc_addr - plt - PLT_INITIAL_ENTRY_WORDS)/2; - if (index >= PLT_DOUBLE_SIZE) { /* Slots greater than or equal to 2^13 have 4 words available instead of two. */ + /* FIXME: There are some possible race conditions in this code, + when called from 'fixup'. + + 1) Suppose that a lazy PLT entry is executing, a + context switch between threads (or a signal) occurs, + and the new thread or signal handler calls the same + lazy PLT entry. Then the PLT entry would be changed + while it's being run, which will cause a segfault + (almost always). + + 2) Suppose the reverse: that a lazy PLT entry is + being updated, a context switch occurs, and the new + code calls the lazy PLT entry that is being updated. + Then the half-fixed PLT entry will be executed, which + will also almost always cause a segfault. + + These problems don't happen with the 2-word entries, because + only one of the two instructions are changed when a lazy + entry is retargeted at the actual PLT entry; the li + instruction stays the same (we have to update it anyway, + because we might not be updating a lazy PLT entry). */ reloc_addr[0] = OPCODE_LI (11, finaladdr); reloc_addr[1] = OPCODE_ADDIS (11, 11, finaladdr + 0x8000 >> 16); reloc_addr[2] = OPCODE_MTCTR (11); @@ -648,19 +671,27 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, num_plt_entries = (map->l_info[DT_PLTRELSZ]->d_un.d_val / sizeof(Elf32_Rela)); + plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr; reloc_addr[0] = OPCODE_LI (11, index*4); reloc_addr[1] = OPCODE_B (-(4*(index*2 + 1 - PLT_LONGBRANCH_ENTRY_WORDS + PLT_INITIAL_ENTRY_WORDS))); - plt[index+PLT_DATA_START_WORDS (num_plt_entries)] = finaladdr; } } MODIFIED_CODE (reloc_addr); } else - assert (! "unexpected dynamic reloc type"); + { +#ifdef RTLD_BOOTSTRAP + PPC_DIE; /* There is no point calling _dl_sysdep_error, it + almost certainly hasn't been relocated properly. */ +#else + _dl_sysdep_error (_dl_argv[0] ?: "<program name unknown>", + ": Unknown relocation type\n", NULL); +#endif + } if (rinfo == R_PPC_ADDR16_LO || rinfo == R_PPC_ADDR16_HI || diff --git a/sysdeps/powerpc/e_sqrt.c b/sysdeps/powerpc/e_sqrt.c new file mode 100644 index 0000000000..df80973f58 --- /dev/null +++ b/sysdeps/powerpc/e_sqrt.c @@ -0,0 +1,141 @@ +/* Single-precision floating point square root. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> +#include <math_private.h> +#include <fenv_libc.h> +#include <inttypes.h> + +static const double almost_half = 0.5000000000000001; /* 0.5 + 2^-53 */ +static const uint32_t a_nan = 0x7fc00000; +static const uint32_t a_inf = 0x7f800000; +static const float two108 = 3.245185536584267269e+32; +static const float twom54 = 5.551115123125782702e-17; +extern const float __t_sqrt[1024]; + +/* The method is based on a description in + Computation of elementary functions on the IBM RISC System/6000 processor, + P. W. Markstein, IBM J. Res. Develop, 34(1) 1990. + Basically, it consists of two interleaved Newton-Rhapson approximations, + one to find the actual square root, and one to find its reciprocal + without the expense of a division operation. The tricky bit here + is the use of the POWER/PowerPC multiply-add operation to get the + required accuracy with high speed. + + The argument reduction works by a combination of table lookup to + obtain the initial guesses, and some careful modification of the + generated guesses (which mostly runs on the integer unit, while the + Newton-Rhapson is running on the FPU). */ +double +__sqrt(double x) +{ + const float inf = *(const float *)&a_inf; + /* x = f_wash(x); *//* This ensures only one exception for SNaN. */ + if (x > 0) + { + if (x != inf) + { + /* Variables named starting with 's' exist in the + argument-reduced space, so that 2 > sx >= 0.5, + 1.41... > sg >= 0.70.., 0.70.. >= sy > 0.35... . + Variables named ending with 'i' are integer versions of + floating-point values. */ + double sx; /* The value of which we're trying to find the + square root. */ + double sg,g; /* Guess of the square root of x. */ + double sd,d; /* Difference between the square of the guess and x. */ + double sy; /* Estimate of 1/2g (overestimated by 1ulp). */ + double sy2; /* 2*sy */ + double e; /* Difference between y*g and 1/2 (se = e * fsy). */ + double shx; /* == sx * fsg */ + double fsg; /* sg*fsg == g. */ + fenv_t fe; /* Saved floating-point environment (stores rounding + mode and whether the inexact exception is + enabled). */ + uint32_t xi0, xi1, sxi, fsgi; + const float *t_sqrt; + + fe = fegetenv_register(); + EXTRACT_WORDS (xi0,xi1,x); + relax_fenv_state(); + sxi = xi0 & 0x3fffffff | 0x3fe00000; + INSERT_WORDS (sx, sxi, xi1); + t_sqrt = __t_sqrt + (xi0 >> 52-32-8-1 & 0x3fe); + sg = t_sqrt[0]; + sy = t_sqrt[1]; + + /* Here we have three Newton-Rhapson iterations each of a + division and a square root and the remainder of the + argument reduction, all interleaved. */ + sd = -(sg*sg - sx); + fsgi = xi0 + 0x40000000 >> 1 & 0x7ff00000; + sy2 = sy + sy; + sg = sy*sd + sg; /* 16-bit approximation to sqrt(sx). */ + INSERT_WORDS (fsg, fsgi, 0); + e = -(sy*sg - almost_half); + sd = -(sg*sg - sx); + if ((xi0 & 0x7ff00000) == 0) + goto denorm; + sy = sy + e*sy2; + sg = sg + sy*sd; /* 32-bit approximation to sqrt(sx). */ + sy2 = sy + sy; + e = -(sy*sg - almost_half); + sd = -(sg*sg - sx); + sy = sy + e*sy2; + shx = sx * fsg; + sg = sg + sy*sd; /* 64-bit approximation to sqrt(sx), + but perhaps rounded incorrectly. */ + sy2 = sy + sy; + g = sg * fsg; + e = -(sy*sg - almost_half); + d = -(g*sg - shx); + sy = sy + e*sy2; + fesetenv_register (fe); + return g + sy*d; + denorm: + /* For denormalised numbers, we normalise, calculate the + square root, and return an adjusted result. */ + fesetenv_register (fe); + return __sqrt(x * two108) * twom54; + } + } + else if (x < 0) + { +#ifdef FE_INVALID_SQRT + feraiseexcept (FE_INVALID_SQRT); + /* For some reason, some PowerPC processors don't implement + FE_INVALID_SQRT. I guess no-one ever thought they'd be + used for square roots... :-) */ + if (!fetestexcept (FE_INVALID)) +#endif + feraiseexcept (FE_INVALID); +#ifndef _IEEE_LIBM + if (_LIB_VERSION != _IEEE_) + x = __kernel_standard(x,x,26); + else +#endif + x = *(const float*)&a_nan; + } + return f_wash(x); +} + +weak_alias (__sqrt, sqrt) +/* Strictly, this is wrong, but the only places where _ieee754_sqrt is + used will not pass in a negative result. */ +strong_alias(__sqrt,__ieee754_sqrt) diff --git a/sysdeps/powerpc/e_sqrtf.c b/sysdeps/powerpc/e_sqrtf.c new file mode 100644 index 0000000000..804dff3c44 --- /dev/null +++ b/sysdeps/powerpc/e_sqrtf.c @@ -0,0 +1,136 @@ +/* Single-precision floating point square root. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> +#include <math_private.h> +#include <fenv_libc.h> +#include <inttypes.h> + +static const float almost_half = 0.50000006; /* 0.5 + 2^-24 */ +static const uint32_t a_nan = 0x7fc00000; +static const uint32_t a_inf = 0x7f800000; +static const float two48 = 281474976710656.0; +static const float twom24 = 5.9604644775390625e-8; +extern const float __t_sqrt[1024]; + +/* The method is based on a description in + Computation of elementary functions on the IBM RISC System/6000 processor, + P. W. Markstein, IBM J. Res. Develop, 34(1) 1990. + Basically, it consists of two interleaved Newton-Rhapson approximations, + one to find the actual square root, and one to find its reciprocal + without the expense of a division operation. The tricky bit here + is the use of the POWER/PowerPC multiply-add operation to get the + required accuracy with high speed. + + The argument reduction works by a combination of table lookup to + obtain the initial guesses, and some careful modification of the + generated guesses (which mostly runs on the integer unit, while the + Newton-Rhapson is running on the FPU). */ +float +__sqrtf(float x) +{ + const float inf = *(const float *)&a_inf; + /* x = f_washf(x); *//* This ensures only one exception for SNaN. */ + if (x > 0) + { + if (x != inf) + { + /* Variables named starting with 's' exist in the + argument-reduced space, so that 2 > sx >= 0.5, + 1.41... > sg >= 0.70.., 0.70.. >= sy > 0.35... . + Variables named ending with 'i' are integer versions of + floating-point values. */ + float sx; /* The value of which we're trying to find the square + root. */ + float sg,g; /* Guess of the square root of x. */ + float sd,d; /* Difference between the square of the guess and x. */ + float sy; /* Estimate of 1/2g (overestimated by 1ulp). */ + float sy2; /* 2*sy */ + float e; /* Difference between y*g and 1/2 (note that e==se). */ + float shx; /* == sx * fsg */ + float fsg; /* sg*fsg == g. */ + fenv_t fe; /* Saved floating-point environment (stores rounding + mode and whether the inexact exception is + enabled). */ + uint32_t xi, sxi, fsgi; + const float *t_sqrt; + + GET_FLOAT_WORD (xi, x); + fe = fegetenv_register (); + relax_fenv_state (); + sxi = xi & 0x3fffffff | 0x3f000000; + SET_FLOAT_WORD (sx, sxi); + t_sqrt = __t_sqrt + (xi >> 23-8-1 & 0x3fe); + sg = t_sqrt[0]; + sy = t_sqrt[1]; + + /* Here we have three Newton-Rhapson iterations each of a + division and a square root and the remainder of the + argument reduction, all interleaved. */ + sd = -(sg*sg - sx); + fsgi = xi + 0x40000000 >> 1 & 0x7f800000; + sy2 = sy + sy; + sg = sy*sd + sg; /* 16-bit approximation to sqrt(sx). */ + e = -(sy*sg - almost_half); + SET_FLOAT_WORD (fsg, fsgi); + sd = -(sg*sg - sx); + sy = sy + e*sy2; + if ((xi & 0x7f800000) == 0) + goto denorm; + shx = sx * fsg; + sg = sg + sy*sd; /* 32-bit approximation to sqrt(sx), + but perhaps rounded incorrectly. */ + sy2 = sy + sy; + g = sg * fsg; + e = -(sy*sg - almost_half); + d = -(g*sg - shx); + sy = sy + e*sy2; + fesetenv_register (fe); + return g + sy*d; + denorm: + /* For denormalised numbers, we normalise, calculate the + square root, and return an adjusted result. */ + fesetenv_register (fe); + return __sqrtf(x * two48) * twom24; + } + } + else if (x < 0) + { +#ifdef FE_INVALID_SQRT + feraiseexcept (FE_INVALID_SQRT); + /* For some reason, some PowerPC processors don't implement + FE_INVALID_SQRT. I guess no-one ever thought they'd be + used for square roots... :-) */ + if (!fetestexcept (FE_INVALID)) +#endif + feraiseexcept (FE_INVALID); +#ifndef _IEEE_LIBM + if (_LIB_VERSION != _IEEE_) + x = __kernel_standard(x,x,126); + else +#endif + x = *(const float*)&a_nan; + } + return f_washf(x); +} + +weak_alias (__sqrtf, sqrtf) +/* Strictly, this is wrong, but the only places where _ieee754_sqrt is + used will not pass in a negative result. */ +strong_alias(__sqrtf,__ieee754_sqrtf) diff --git a/sysdeps/powerpc/fclrexcpt.c b/sysdeps/powerpc/fclrexcpt.c index 1e66140c2e..cfcf175637 100644 --- a/sysdeps/powerpc/fclrexcpt.c +++ b/sysdeps/powerpc/fclrexcpt.c @@ -19,6 +19,7 @@ #include <fenv_libc.h> +#undef feclearexcept void feclearexcept (int excepts) { @@ -28,7 +29,8 @@ feclearexcept (int excepts) u.fenv = fegetenv_register (); /* Clear the relevant bits. */ - u.l[1] = u.l[1] & ~FE_to_sticky (excepts); + u.l[1] = u.l[1] & ~(-((excepts) >> 31-FPSCR_VX & 1) & FE_ALL_INVALID + | (excepts) & FPSCR_STICKY_BITS); /* Put the new state in effect. */ fesetenv_register (u.fenv); diff --git a/sysdeps/powerpc/fe_nomask.c b/sysdeps/powerpc/fe_nomask.c new file mode 100644 index 0000000000..bca49055d1 --- /dev/null +++ b/sysdeps/powerpc/fe_nomask.c @@ -0,0 +1,32 @@ +/* Procedure definition for FE_NOMASK_ENV. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <fenv.h> +#include <errno.h> + +/* This is presently a stub, until it's decided how the kernels should + support this. */ + +const fenv_t * +__fe_nomask_env(void) +{ + __set_errno (ENOSYS); + return FE_ENABLED_ENV; +} +stub_warning (__fe_nomask_env) diff --git a/sysdeps/powerpc/fegetround.c b/sysdeps/powerpc/fegetround.c index 05395f0797..3bb9fb49e0 100644 --- a/sysdeps/powerpc/fegetround.c +++ b/sysdeps/powerpc/fegetround.c @@ -19,13 +19,11 @@ #include <fenv_libc.h> +#undef fegetround int fegetround (void) { - fenv_union_t u; - - u.fenv = fegetenv_register (); - - /* The rounding mode is bits 30 and 31 of the FPSCR. */ - return u.l[1] & 3; + int result; + asm ("mcrfs 7,7 ; mfcr %0" : "=r"(result) : : "cr7"); \ + return result & 3; } diff --git a/sysdeps/powerpc/fenv_const.c b/sysdeps/powerpc/fenv_const.c index fa35fbc0cf..506bd43df0 100644 --- a/sysdeps/powerpc/fenv_const.c +++ b/sysdeps/powerpc/fenv_const.c @@ -25,5 +25,9 @@ const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = 0xfff8000000000000ULL; /* Floating-point environment where none of the exceptions are masked. */ -const unsigned long long __fe_nomask_env __attribute__ ((aligned (8))) = +const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = 0xfff80000000000f8ULL; + +/* Floating-point environment with the NI bit set. */ +const unsigned long long __fe_nonieee_env __attribute__ ((aligned (8))) = +0xfff8000000000004ULL; diff --git a/sysdeps/powerpc/fenv_libc.h b/sysdeps/powerpc/fenv_libc.h index 45d61e1565..343be16fcb 100644 --- a/sysdeps/powerpc/fenv_libc.h +++ b/sysdeps/powerpc/fenv_libc.h @@ -22,23 +22,17 @@ #include <fenv.h> -/* Transform a logical or of the FE_* bits to a bit pattern for the - appropriate sticky bits in the FPSCR. */ -#define FE_to_sticky(excepts) \ - (-(excepts & FE_INVALID) & FE_ALL_INVALID \ - | (excepts) & (FE_ALL_EXCEPT & ~FE_INVALID | FE_ALL_INVALID)) - /* The sticky bits in the FPSCR indicating exceptions have occurred. */ #define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID) /* Equivalent to fegetenv, but returns a fenv_t instead of taking a pointer. */ #define fegetenv_register() \ - ({ fenv_t env; asm ("mffs %0" : "=f" (env)); env; }) + ({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; }) /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ #define fesetenv_register(env) \ - ({ double d = (env); asm ("mtfsf 0xff,%0" : : "f" (d)); }) + ({ double d = (env); asm volatile ("mtfsf 0xff,%0" : : "f" (d)); }) /* This very handy macro: - Sets the rounding mode to 'round to nearest'; @@ -48,10 +42,65 @@ functions. */ #define relax_fenv_state() asm ("mtfsfi 7,0") +/* Set/clear a particular FPSCR bit (for instance, + reset_fpscr_bit(FPSCR_VE); + prevents INVALID exceptions from being raised). */ +#define set_fpscr_bit(x) asm volatile ("mtfsb1 %0" : : "i"(x)) +#define reset_fpscr_bit(x) asm volatile ("mtfsb0 %0" : : "i"(x)) + typedef union { fenv_t fenv; unsigned int l[2]; } fenv_union_t; +/* Definitions of all the FPSCR bit numbers */ +enum { + FPSCR_FX = 0, /* exception summary */ + FPSCR_FEX, /* enabled exception summary */ + FPSCR_VX, /* invalid operation summary */ + FPSCR_OX, /* overflow */ + FPSCR_UX, /* underflow */ + FPSCR_ZX, /* zero divide */ + FPSCR_XX, /* inexact */ + FPSCR_VXSNAN, /* invalid operation for SNaN */ + FPSCR_VXISI, /* invalid operation for Inf-Inf */ + FPSCR_VXIDI, /* invalid operation for Inf/Inf */ + FPSCR_VXZDZ, /* invalid operation for 0/0 */ + FPSCR_VXIMZ, /* invalid operation for Inf*0 */ + FPSCR_VXVC, /* invalid operation for invalid compare */ + FPSCR_FR, /* fraction rounded [fraction was incremented by round] */ + FPSCR_FI, /* fraction inexact */ + FPSCR_FPRF_C, /* result class descriptor */ + FPSCR_FPRF_FL, /* result less than (usually, less than 0) */ + FPSCR_FPRF_FG, /* result greater than */ + FPSCR_FPRF_FE, /* result equal to */ + FPSCR_FPRF_FU, /* result unordered */ + FPSCR_20, /* reserved */ + FPSCR_VXSOFT, /* invalid operation set by software */ + FPSCR_VXSQRT, /* invalid operation for square root */ + FPSCR_VXCVI, /* invalid operation for invalid integer convert */ + FPSCR_VE, /* invalid operation exception enable */ + FPSCR_OE, /* overflow exception enable */ + FPSCR_UE, /* underflow exception enable */ + FPSCR_ZE, /* zero divide exception enable */ + FPSCR_XE, /* inexact exception enable */ + FPSCR_NI /* non-IEEE mode (typically, no denormalised numbers) */ + /* the remaining two least-significant bits keep the rounding mode */ +}; + +/* This operation (i) sets the appropriate FPSCR bits for its + parameter, (ii) converts SNaN to the corresponding NaN, and (iii) + otherwise passes its parameter through unchanged (in particular, -0 + and +0 stay as they were). The `obvious' way to do this is optimised + out by gcc. */ +#define f_wash(x) \ + ({ double d; asm volatile ("fmul %0,%1,%2" \ + : "=f"(d) \ + : "f" (x), "f"((float)1.0)); d; }) +#define f_washf(x) \ + ({ float f; asm volatile ("fmuls %0,%1,%2" \ + : "=f"(f) \ + : "f" (x), "f"((float)1.0)); f; }) + #endif /* fenv_libc.h */ diff --git a/sysdeps/powerpc/fgetexcptflg.c b/sysdeps/powerpc/fgetexcptflg.c index d6bd58dc69..adbdfe22b9 100644 --- a/sysdeps/powerpc/fgetexcptflg.c +++ b/sysdeps/powerpc/fgetexcptflg.c @@ -23,11 +23,10 @@ void fegetexceptflag (fexcept_t *flagp, int excepts) { fenv_union_t u; - unsigned int flag; /* Get the current state. */ u.fenv = fegetenv_register (); - /* Return that portion that corresponds to the requested exceptions. */ - *flagp = flag = u.l[1] & FPSCR_STICKY_BITS & FE_to_sticky (excepts); + /* Return (all of) it. */ + *flagp = u.l[1]; } diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h index d21987ffd8..c4c478672b 100644 --- a/sysdeps/powerpc/fpu_control.h +++ b/sysdeps/powerpc/fpu_control.h @@ -52,6 +52,7 @@ typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); #define _FPU_GETCW(cw) ( { \ fpu_control_t tmp[2] __attribute__ ((__aligned__(8))); \ __asm__ ("mffs 0; stfd 0,%0" : "=m" (*tmp) : : "fr0"); \ + (cw)=tmp[1]; \ tmp[1]; } ) #define _FPU_SETCW(cw) { \ fpu_control_t tmp[2] __attribute__ ((__aligned__(8))); \ diff --git a/sysdeps/powerpc/fraiseexcpt.c b/sysdeps/powerpc/fraiseexcpt.c index 4305c3dcd2..d0c7971836 100644 --- a/sysdeps/powerpc/fraiseexcpt.c +++ b/sysdeps/powerpc/fraiseexcpt.c @@ -19,6 +19,7 @@ #include <fenv_libc.h> +#undef feraiseexcept void feraiseexcept (int excepts) { @@ -36,9 +37,17 @@ feraiseexcept (int excepts) u.l[1] = (u.l[1] | excepts & FPSCR_STICKY_BITS /* Turn FE_INVALID into FE_INVALID_SOFTWARE. */ - | excepts << (31 - 21) - (31 - 24) & FE_INVALID_SOFTWARE); + | (excepts >> (31 - FPSCR_VX) - (31 - FPSCR_VXSOFT) + & FE_INVALID_SOFTWARE)); /* Store the new status word (along with the rest of the environment), triggering any appropriate exceptions. */ fesetenv_register (u.fenv); + + if ((excepts & FE_INVALID) + /* For some reason, some PowerPC chips (the 601, in particular) + don't have FE_INVALID_SOFTWARE implemented. Detect this + case and raise FE_INVALID_SNAN instead. */ + && !fetestexcept (FE_INVALID)) + set_fpscr_bit (FPSCR_VXSNAN); } diff --git a/sysdeps/powerpc/fsetexcptflg.c b/sysdeps/powerpc/fsetexcptflg.c index 4279b74849..b762552dbf 100644 --- a/sysdeps/powerpc/fsetexcptflg.c +++ b/sysdeps/powerpc/fsetexcptflg.c @@ -23,15 +23,26 @@ void fesetexceptflag (const fexcept_t *flagp, int excepts) { fenv_union_t u; + fexcept_t flag; /* Get the current state. */ u.fenv = fegetenv_register (); + /* Ignore exceptions not listed in 'excepts'. */ + flag = *flagp & excepts; + /* Replace the exception status */ - u.l[1] = u.l[1] & FPSCR_STICKY_BITS | *flagp & FE_to_sticky (excepts); + u.l[1] = (u.l[1] & ~(FPSCR_STICKY_BITS & excepts) + | flag & FPSCR_STICKY_BITS + | (flag >> (31 - FPSCR_VX) - (31 - FPSCR_VXSOFT) + & FE_INVALID_SOFTWARE)); /* Store the new status word (along with the rest of the environment). This may cause floating-point exceptions if the restored state requests it. */ fesetenv_register (u.fenv); + + /* Deal with FE_INVALID_SOFTWARE not being implemented on some chips. */ + if (flag & FE_INVALID) + feraiseexcept(FE_INVALID); } diff --git a/sysdeps/powerpc/ftestexcept.c b/sysdeps/powerpc/ftestexcept.c index 52733f7ae7..6cb8dd5e28 100644 --- a/sysdeps/powerpc/ftestexcept.c +++ b/sysdeps/powerpc/ftestexcept.c @@ -23,16 +23,11 @@ int fetestexcept (int excepts) { fenv_union_t u; - int flags; /* Get the current state. */ u.fenv = fegetenv_register (); - /* Find the bits that indicate exceptions have occurred. */ - flags = u.l[1] & FPSCR_STICKY_BITS; - - /* Set the FE_INVALID bit if any of the FE_INVALID_* bits are set. */ - flags |= ((u.l[1] & FE_ALL_INVALID) != 0) << 31-24; - - return flags & excepts; + /* The FE_INVALID bit is dealt with correctly by the hardware, so we can + just: */ + return u.l[1] & excepts; } diff --git a/sysdeps/powerpc/q_addsub.c b/sysdeps/powerpc/q_addsub.c new file mode 100644 index 0000000000..e4ef6d8165 --- /dev/null +++ b/sysdeps/powerpc/q_addsub.c @@ -0,0 +1,549 @@ +/* Add or subtract two 128-bit floating point values. C prototype. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* Add 'a' to 'b' and put the result in 'result', but treat a[0]=axx, + b[0]=bxx. bxx differs from b[0] only in the high bit, similarly axx. */ +/* Exceptions to raise: + - Invalid (SNaN) + - Invalid (Inf-Inf) + - Overflow + - Underflow + - Inexact + */ + +/* Handle cases where exponent of a or b is maximum. */ +static void +handle_max_exponent(unsigned result[4], + const unsigned a[4], const unsigned b[4], + const unsigned axx, /* Treat as a[0]. */ + const unsigned bxx, /* Treat as b[0]. */ + const unsigned ax, /* axx >> 16 & 0x7fff. */ + const unsigned bx) /* bxx >> 16 & 0x7fff. */ +{ + int ax_ismax, bx_ismax; + unsigned a1,a2,a3, b1,b2,b3; + int a_zeromant, b_zeromant; + + ax_ismax = ax == 0x7fff; + bx_ismax = bx == 0x7fff; + + assert(ax_ismax || bx_ismax); + + a1 = a[1]; a2 = a[2]; a3 = a[3]; + b1 = b[1]; b2 = b[2]; b3 = b[3]; + + a_zeromant = (axx & 0xffff | a1 | a2 | a3) == 0; + b_zeromant = (bxx & 0xffff | b1 | b2 | b3) == 0; + + /* Deal with SNaNs. */ + if ( ax_ismax && !a_zeromant && (axx & 0x8000) == 0 + || bx_ismax && !b_zeromant && (bxx & 0x8000) == 0) + { + set_fpscr_bit(FPSCR_VXSNAN); + axx |= 0x8000; /* Demote the SNaN to a QNaN (whichever of */ + bxx |= 0x8000; /* a or b it was). */ + } + /* Deal with Inf-Inf. */ + else if (a_zeromant && b_zeromant && (axx ^ bxx) == 0x80000000) + { + set_fpscr_bit(FPSCR_VXISI); + bxx |= 0x8000; /* Return an appropriate QNaN. */ + } + + /* Return the lexicographically larger of a or b, ignoring the sign + bits. */ + if ((axx & 0x7fffffff) > (bxx & 0x7fffffff)) goto return_a; + else if ((axx & 0x7fffffff) < (bxx & 0x7fffffff)) goto return_b; + else if (a1 > b1) goto return_a; + else if (a1 < b1) goto return_b; + else if (a2 > b2) goto return_a; + else if (a2 < b2) goto return_b; + else if (a3 > b3) goto return_a; /* I've clearly been writing too */ + else if (a3 < b3) goto return_b; /* much Fortran... */ + + /* If they are equal except for the sign bits, return 'b'. */ + +return_b: + result[0] = bxx; result[1] = b1; result[2] = b2; result[3] = b3; + return; + +return_a: + result[0] = axx; result[1] = a1; result[2] = a2; result[3] = a3; + return; +} + +/* Renormalise and output a FP number. */ +static void +renormalise_value(unsigned result[4], + const unsigned axx, + unsigned ax, + unsigned r0, + unsigned r1, + unsigned r2, + unsigned r3) +{ + int rshift; + if (r0 != 0 || cntlzw(a1) < 16 || 32 > ax-1) + { + rshift = cntlzw(r0)-15 + (-(cntlzw(r0) >> 5) & cntlzw(a1)); + assert(rshift < 32); + if (rshift > ax-1) + { + ax--; + rshift = ax; + } + + result[0] = (axx & 0x80000000 + | ax-rshift << 16 + | r0 << rshift & 0xffff + | a1 >> 32-rshift & 0xffff); + result[1] = a1 << rshift | a2 >> 32-rshift; + result[2] = a2 << rshift | a3 >> 32-rshift; + result[3] = a3 << rshift; + return; + } + result[3] = 0; + /* Special case for zero. */ + if (a1 == 0 && a2 == 0 && a3 == 0) + { + result[0] = axx & 0x80000000; + result[1] = result[2] = 0; + return; + } + while (a1 != 0 && cntlzw(a2) >= 16 && 64 <= ax-1) + { + ax -= 32; + a1 = a2; a2 = a3; a3 = 0; + } + rshift = cntlzw(a1)-15 + (-(cntlzw(a1) >> 5) & cntlzw(a2)); + assert(rshift < 32); + if (rshift > ax-1-32) + { + ax--; + rshift = ax-32; + } + + result[0] = (axx & 0x80000000 + | ax-rshift-32 << 16 + | a1 << rshift & 0xffff + | a2 >> 32-rshift & 0xffff); + result[1] = a2 << rshift | a3 >> 32-rshift; + result[2] = a3 << rshift; + return; +} + +/* Handle the case where one or both numbers are denormalised or zero. + This case almost never happens, so we don't slow the main code + with it. */ +static void +handle_min_exponent(unsigned result[4], + const unsigned a[4], const unsigned b[4], + const unsigned axx, /* Treat as a[0]. */ + const unsigned bxx, /* Treat as b[0]. */ + const unsigned ax, /* axx >> 16 & 0x7fff. */ + const unsigned bx) /* bxx >> 16 & 0x7fff. */ +{ + int ax_denorm, bx_denorm; + unsigned a1,a2,a3, b1,b2,b3; + int a_zeromant, b_zeromant; + + ax_denorm = ax == 0; + bx_denorm = bx == 0; + + assert(ax_denorm || bx_denorm); + + a1 = a[1]; a2 = a[2]; a3 = a[3]; + b1 = b[1]; b2 = b[2]; b3 = b[3]; + + +} + +/* Add a+b+cin modulo 2^32, put result in 'r' and carry in 'cout'. */ +#define addc(r,cout,a,b,cin) \ + do { \ + unsigned long long addc_tmp = (a)+(b)+(cin); + (cout) = addc_tmp >> 32; + (r) = addc_tmp; + } + +/* Calculate a+~b+cin modulo 2^32, put result in 'r' and carry in 'cout'. */ +#define subc(r,cout,a,b,cin) \ + do { \ + unsigned long long addc_tmp = (a)-(b)+(cin)-1; + (cout) = addc_tmp >> 63; + (r) = addc_tmp; + } + +/* Handle the case where both exponents are the same. This requires quite + a different algorithm than the general case. */ +static void +handle_equal_exponents(unsigned result[4], + const unsigned a[4], const unsigned b[4], + const unsigned axx, /* Treat as a[0]. */ + const unsigned bxx, /* Treat as b[0]. */ + unsigned ax) /* [ab]xx >> 16 & 0x7fff. */ +{ + unsigned a1,a2,a3, b1,b2,b3; + int roundmode; + unsigned carry, r0; + + a1 = a[1]; a2 = a[2]; a3 = a[3]; + b1 = b[1]; b2 = b[2]; b3 = b[3]; + + if ((int)(axx ^ bxx) >= 0) + { + int roundmode; + + /* Adding. */ + roundmode = fegetround(); + + /* What about overflow? */ + if (ax == 0x7ffe) + { + /* Oh no! Too big! */ + /* Result: + rounding result + -------- ------ + nearest return Inf with sign of a,b + zero return nearest possible non-Inf value with + sign of a,b + +Inf return +Inf if a,b>0, otherwise return + value just before -Inf. + -Inf return +Inf if a,b>0, otherwise return + value just before -Inf. + */ + set_fpscr_bit(FPSCR_OX); + /* Overflow always produces inexact result. */ + set_fpscr_bit(FPSCR_XX); + + if ( roundmode == FE_TONEAREST + || roundmode == FE_UPWARD && (int)axx >= 0 + || roundmode == FE_DOWNWARD && (int)axx < 0) + { + result[3] = result[2] = result[1] = 0; + result[0] = axx & 0xffff0000 | 0x7fff0000; + } + else + { + result[3] = result[2] = result[1] = 0xffffffff; + result[0] = axx & 0xfffe0000 | 0x7ffeffff; + } + return; + } + + /* We need to worry about rounding/inexact here. Do it like this: */ + if (a3 + b3 & 1) + { + /* Need to round. Upwards? */ + set_fpscr_bit(FPSCR_XX); + carry = ( roundmode == FE_NEAREST && (a3 + b3 & 2) != 0 + || roundmode == FE_UPWARD && (int)axx >= 0 + || roundmode == FE_DOWNWARD && (int)axx < 0); + } + else + carry = 0; /* Result will be exact. */ + + /* Perform the addition. */ + addc(a3,carry,a3,b3,carry); + addc(a2,carry,a2,b2,carry); + addc(a1,carry,a1,b1,carry); + r0 = (axx & 0xffff) + (bxx & 0xffff) + carry; + + /* Shift right by 1. */ + result[3] = a3 >> 1 | a2 << 31; + result[2] = a2 >> 1 | a1 << 31; + result[1] = a1 >> 1 | r0 << 31; + /* Exponent of result is exponent of inputs plus 1. + Sign of result is common sign of inputs. */ + result[0] = r0 >> 1 & 0xffff | axx + 0x10000 & 0xffff0000; + } + else + { + /* Subtracting. */ + + /* Perform the subtraction, a-b. */ + subc(a3,carry,a3,b3,0); + subc(a2,carry,a2,b2,carry); + subc(a1,carry,a1,b1,carry); + subc(r0,carry,a0&0xffff,b0&0xffff,carry); + + /* Maybe we should have calculated b-a... */ + if (carry) + { + subc(a3,carry,0,a3,0); + subc(a2,carry,0,a2,carry); + subc(a1,carry,0,a1,carry); + subc(r0,carry,0,r0,carry); + axx ^= 0x80000000; + } + + renormalise_value(result, axx, ax, r0, a1, a2, a3); + } +} + + +static void +add(unsigned result[4], const unsigned a[4], const unsigned b[4], + unsigned axx, unsigned bxx) +{ + int ax, bx, diff, carry; + unsigned a0,a1,a2,a3, b0,b1,b2,b3,b4, sdiff; + + ax = axx >> 16 & 0x7fff; + bx = bxx >> 16 & 0x7fff; + + /* Deal with NaNs and Inf. */ + if (ax == 0x7fff || bx == 0x7fff) + { + handle_max_exponent(result, a, b, axx, bxx, ax, bx); + return; + } + /* Deal with denorms and zero. */ + if (ax == 0 || bx == 0) + { + handle_min_exponent(result, a, b, axx, bxx, ax, bx); + return; + } + /* Finally, one special case, when both exponents are equal. */ + if (ax == bx) + { + handle_equal_exponents(result, a, b, axx, bxx, ax); + return; + } + + sdiff = axx ^ bxx; + /* Swap a and b if b has a larger magnitude than a, so that a will have + the larger magnitude. */ + if (ax < bx) + { + const unsigned *t; + t = b; b = a; a = t; + diff = bx - ax; + ax = bx; + axx = bxx; + } + else + diff = ax - bx; + + a0 = a[0] & 0xffff | 0x10000; a1 = a[1]; a2 = a[2]; a3 = a[3]; + b0 = b[0] & 0xffff | 0x10000; b1 = b[1]; b2 = b[2]; b3 = b[3]; + if (diff < 32) + { + b4 = b3 << 32-diff; + b3 = b3 >> diff | b2 << 32-biff; + b2 = b2 >> diff | b1 << 32-diff; + b1 = b1 >> diff | b0 << 32-diff; + b0 = b0 >> diff; + } + else if (diff < 64) + { + diff -= 32; + b4 = b3 & 1 | b3 >> (diff == 32) | b2 << 32-biff; + b3 = b2 >> diff | b1 << 32-diff; + b2 = b1 >> diff | b0 << 32-diff; + b1 = b0 >> diff; + b0 = 0; + } + else if (diff < 96) + { + b4 = b2 | b3 | b1 << 32-diff; + b3 = b1 >> diff | b0 << 32-diff; + b2 = b0 >> diff; + b1 = b0 = 0; + } + else if (diff < 128) + { + b4 = b1 | b2 | b3 | b0 << 32-diff; + b3 = b0 >> diff; + b2 = b1 = b0 = 0; + } + else + { + b4 = b0|b1|b2|b3; + b3 = b2 = b1 = b0 = 0; + } + + /* Now, two cases: one for addition, one for subtraction. */ + if ((int)sdiff >= 0) + { + /* Addition. */ + + /* + + /* Perform the addition. */ + addc(a3,carry,a3,b3,0); + addc(a2,carry,a2,b2,carry); + addc(a1,carry,a1,b1,carry); + addc(a0,carry,a0,b0,carry); + + + + if (a0 & 0x20000) + { + /* Need to renormalise by shifting right. */ + /* Shift right by 1. */ + b4 = b4 | a3 << 31; + a3 = a3 >> 1 | a2 << 31; + a2 = a2 >> 1 | a1 << 31; + result[1] = a1 >> 1 | r0 << 31; + /* Exponent of result is exponent of inputs plus 1. + Sign of result is common sign of inputs. */ + result[0] = r0 >> 1 & 0xffff | axx + 0x10000 & 0xffff0000; + } + + + } + else + { + /* Subtraction. */ + + } +} + +/* Add the absolute values of two 128-bit floating point values, + give the result the sign of one of them. The only exception this + can raise is for SNaN. */ +static void +aadd(unsigned result[4], const unsigned a[4], const unsigned b[4]) +{ + unsigned ax, bx, xd; + const unsigned *sml; + unsigned t0,t1,t2,t3,tx, s0,s1,s2,s3,s4, carry; + int rmode, xdelta, shift; + + ax = a[0] >> 16 & 0x7fff; + bx = b[0] >> 16 & 0x7fff; + + /* Deal with . */ + if (ax == 0x7fff) + { + t0 = a[0]; t1 = a[1]; t2 = a[2]; t3 = a[3]; + /* Check for SNaN. */ + if ((t0 & 0x8000) == 0 + && (t0 & 0x7fff | t1 | t2 | t3) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Return b. */ + result[0] = t0; result[1] = t1; result[2] = t2; result[3] = t3; + return; + } + /* Deal with b==Inf or b==NaN. */ + if (bx == 0x7fff) + { + t0 = b[0]; t1 = b[1]; t2 = b[2]; t3 = b[3]; + /* Check for SNaN. */ + if ((t0 & 0x8000) == 0 + && (t0 & 0x7fff | t1 | t2 | t3) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Return b. */ + result[0] = t0; result[1] = t1; result[2] = t2; result[3] = t3; + return; + } + + /* Choose the larger of the two to be 't', and the smaller to be 's'. */ + if (ax > bx) + { + t0 = a[0] & 0xffff | (ax != 0) << 16; + t1 = a[1]; t2 = a[2]; t3 = a[3]; tx = ax; + s0 = b[0] & 0xffff | (bx != 0) << 16; + s1 = b[1]; s2 = b[2]; s3 = b[3]; + xd = ax-bx; + } + else + { + t0 = b[0] & 0xffff | (bx != 0) << 16; + t1 = b[1]; t2 = b[2]; t3 = b[3]; tx = bx; + s0 = a[0] & 0xffff | (ax != 0) << 16; + s1 = a[1]; s2 = a[2]; s3 = a[3]; + sml = a; + xd = bx-ax; + } + + /* Shift 's2' right by 'xd' bits. */ + switch (xd >> 5) + { + case 0: + s4 = 0; + break; + case 1: + s4 = s3; s3 = s2; s2 = s1; s1 = s0; s0 = 0; + break; + case 2: + s4 = s2 | s3 != 0; + s3 = s1; s2 = s0; s1 = s0 = 0; + break; + case 3: + s4 = s1 | (s3|s2) != 0; + s3 = s0; s2 = s1 = s0 = 0; + break; + default: + s4 = s0 | (s3|s2|s1) != 0; + s3 = s2 = s1 = s0 = 0; + } + xd = xd & 0x1f; + if (xd != 0) + { + s4 = s4 >> xd | (s4 << 32-xd) != 0 | s3 << 32-xd; + s3 = s3 >> xd | s2 << 32-xd; + s2 = s2 >> xd | s1 << 32-xd; + s1 = s1 >> xd | s0 << 32-xd; + s0 = s0 >> xd; + } + + /* Do the addition. */ +#define addc(r,cout,a,b,cin) \ + do { \ + unsigned long long addc_tmp = (a)+(b)+(cin); + (cout) = addc_tmp >> 32; + (r) = addc_tmp; + } + addc(t3,carry,t3,s3,0); + addc(t2,carry,t2,s2,carry); + addc(t1,carry,t1,s1,carry); + t0 = t0 + s0 + carry; + + /* Renormalise. */ + xdelta = 15-cntlzw(t0); + if (tx + xdelta <= 0x7fff) + shift = xdelta; + else + { + } +} + +/* Add two 128-bit floating point values. */ +void +__q_add(unsigned result[4], const unsigned a[4], const unsigned b[4]) +{ + if ((a[0] ^ b[0]) >= 0) + aadd(result, a, b); + else + asubtract(result, a, b); +} + +/* Subtract two 128-bit floating point values. */ +void +__q_sub(unsigned result[4], const unsigned a[4], const unsigned b[4]) +{ + if ((a[0] ^ b[0]) < 0) + aadd(result, a, b); + else + asubtract(result, a, b); +} diff --git a/sysdeps/powerpc/q_dtoq.c b/sysdeps/powerpc/q_dtoq.c new file mode 100644 index 0000000000..8cab9e4689 --- /dev/null +++ b/sysdeps/powerpc/q_dtoq.c @@ -0,0 +1,66 @@ +/* 64-bit floating point to 128-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_dtoq(double a); + Convert 'a' to long double. Don't raise exceptions. + */ + +void +__q_dtoq(unsigned long long result[2], double a) +{ + unsigned ux, rx; + union { + double d; + unsigned long long u; + } u; + + u.d = a; + result[1] = u.u << 64-4; + result[0] = u.u >> 4; + /* correct exponent bias */ + rx = ((long long)u.u >> 52 & 0x87ff) + 16383-1023; + + ux = u.u >> 52 & 0x7ff; + if (ux == 0) + { + if ((u.u & 0x7fffffffffffffffULL) == 0) + { + /* +0.0 or -0.0. */ + rx &= 0x8000; + } + else + { + /* Denormalised number. Renormalise. */ + unsigned long long um = u.u & 0x000fffffffffffffULL; + int cs = cntlzd(um) - 12 + 1; + rx -= cs; + um <<= cs; + result[0] = um >> 4; + result[1] = um << 64-4; + } + } + else if (ux == 0x7ff) + { + /* Inf or NaN. */ + rx |= 0x7fff; + } + *(unsigned short *)result = rx; +} diff --git a/sysdeps/powerpc/q_feq.c b/sysdeps/powerpc/q_feq.c new file mode 100644 index 0000000000..3f5512a4a0 --- /dev/null +++ b/sysdeps/powerpc/q_feq.c @@ -0,0 +1,65 @@ +/* 128-bit floating point unordered equality. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <fenv_libc.h> + +/* int _q_feq(const long double *a, const long double *b); + Returns nonzero if a==b, 0 otherwise. + + Special cases: + NaNs are never equal to anything; + -0 == +0; + If either argument is a SNaN, we set FPSCR_VXSNAN to cause an + 'invalid operation' exception. + */ + +int +__q_feq(const unsigned a[4], const unsigned b[4]) +{ + unsigned a0, b0; + + a0 = a[0]; b0 = b[0]; + + if ((a0 >> 16 & 0x7fff) != 0x7fff && + (b0 >> 16 & 0x7fff) != 0x7fff) + { + unsigned a3,b3,a2,b2,a1,b1; + unsigned z, result; + + a3 = a[3]; b3 = b[3]; a2 = a[2]; + b2 = b[2]; a1 = a[1]; b1 = b[1]; + result = ~(a3 ^ b3); + result &= ~(a2 ^ b2); + result &= ~(a1 ^ b1); + z = a3 | a2; + z |= a1; + z = (z >> 1 | z | a0) & 0x7fffffff; + /* 'z' is 0 iff a==0.0, otherwise between 1 and 0x7fffffff */ + return (result & ~(a0^b0 & ~(-z & 0x80000000)))+1; + } + else + { + /* Deal with SNaNs */ + if (((a0|b0) & 0x8000) == 0) + { + set_fpscr_bit(FPSCR_VXSNAN); + } + return 0; + } +} diff --git a/sysdeps/powerpc/q_fne.c b/sysdeps/powerpc/q_fne.c new file mode 100644 index 0000000000..8f6429cd55 --- /dev/null +++ b/sysdeps/powerpc/q_fne.c @@ -0,0 +1,70 @@ +/* 128-bit floating point unordered not-equality. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <fenv_libc.h> + +/* int _q_fne(const long double *a, const long double *b); + Returns 0 if a==b + + Special cases: + NaNs return 1 always; + -0 == +0; + If either argument is a SNaN, we set FPSCR_VXSNAN to cause an + 'invalid operation' exception. + */ + +int +__q_fne(const unsigned a[4], const unsigned b[4]) +{ + unsigned a0, b0; + + a0 = a[0]; b0 = b[0]; + + if ((a0 >> 16 & 0x7fff) != 0x7fff && + (b0 >> 16 & 0x7fff) != 0x7fff) + { + unsigned a3,b3,a2,b2,a1,b1; + unsigned z, result; + + a3 = a[3]; b3 = b[3]; a2 = a[2]; + result = a3 ^ b3; + b2 = b[2]; + if (result != 0) + return result; + a1 = a[1]; b1 = b[1]; + result = a2 ^ b2; + result |= a1 ^ b1; + z = a3 | a2; + if (result != 0) + return result; + z |= a1; + z = (z >> 1 | z | a0) & 0x7fffffff; + /* 'z' is 0 iff a==0.0, otherwise between 1 and 0x7fffffff */ + return (a0^b0) & ~(-z & 0x80000000); + } + else + { + /* Deal with SNaNs */ + if (((a0|b0) & 0x8000) == 0) + { + set_fpscr_bit(FPSCR_VXSNAN); + } + return 1; + } +} diff --git a/sysdeps/powerpc/q_itoq.c b/sysdeps/powerpc/q_itoq.c new file mode 100644 index 0000000000..aa737391bb --- /dev/null +++ b/sysdeps/powerpc/q_itoq.c @@ -0,0 +1,50 @@ +/* 32-bit fixed point signed integer to 128-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_itoq(int a); + Convert 'a' to long double. + */ + +void +__q_itoq(unsigned int result[4], int a) +{ + unsigned rx; + int cs, css; + + /* Note that if a==-2^31, then ua will be 2^31. */ + unsigned int ua = abs(a); + + /* Normalize. */ + cs = cntlzw(ua); + ua <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 31-cs; + rx = 16383+css << 16 & ~css; + + /* Copy the sign bit from 'a'. */ + asm ("rlwimi %0,%1,0,0,0": "=r"(rx) : "r"(a), "0"(rx)); + + /* Put it all together. */ + result[2] = result[3] = 0; + asm ("rlwimi %0,%1,16,16,31": "=r"(result[0]) : "r"(ua), "0"(rx)); + result[1] = ua << 16; +} diff --git a/sysdeps/powerpc/q_lltoq.c b/sysdeps/powerpc/q_lltoq.c new file mode 100644 index 0000000000..6222eff9fc --- /dev/null +++ b/sysdeps/powerpc/q_lltoq.c @@ -0,0 +1,52 @@ +/* 64-bit fixed point signed integer to 128-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_ulltoq(long long a); + Convert 'a' to long double. + */ + +void +__q_lltoq(unsigned int result[4], long long a) +{ + unsigned rx; + int cs, css; + + /* Calculate absolute value of 'a'. */ + unsigned long long ua = (a ^ a >> 63) - (a >> 63); + + /* Normalize. */ + cs = cntlzd(a); + ua <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 63-cs; + rx = 16383+css << 16 & ~css; + + /* Copy the sign bit from 'a'. */ + asm ("rlwimi %0,%1,0,0,0": "=r"(rx) : "r"(a >> 32), "0"(rx)); + + /* Put it all together. */ + result[3] = 0; + asm ("rlwimi %0,%1,16,16,31": "=r"(result[0]) : "r"(ua >> 32), "0"(rx)); + ua <<= 16; + result[2] = ua; + result[1] = ua >> 32; +} diff --git a/sysdeps/powerpc/q_neg.c b/sysdeps/powerpc/q_neg.c new file mode 100644 index 0000000000..8e11afdbc6 --- /dev/null +++ b/sysdeps/powerpc/q_neg.c @@ -0,0 +1,38 @@ +/* Negate a 128-bit floating point value. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_neg(const long double *a); + Negate 'a'. Don't raise exceptions. + */ + +void +__q_neg(unsigned int result[4], unsigned int a[4]) +{ + unsigned int t1,t2; + t1 = a[0]; + t2 = a[1]; + result[0] = t1 ^ 0x80000000; + t1 = a[2]; + result[1] = t2; + t2 = a[3]; + result[2] = t1; + result[3] = t2; +} diff --git a/sysdeps/powerpc/q_qtoi.c b/sysdeps/powerpc/q_qtoi.c new file mode 100644 index 0000000000..a2b1b3fe56 --- /dev/null +++ b/sysdeps/powerpc/q_qtoi.c @@ -0,0 +1,65 @@ +/* 128-bit floating point to 32-bit fixed point signed integer. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* int _q_qtoi(const long double *a); + Convert 'a' to signed int by truncation. + + Special cases: + NaN: raise VXCVI, return 0x80000000 + SNaN: raise VXSNAN, VXCVI, and return 0x80000000 + >= 2^32: raise VXCVI, return 0x7fffffff + <= -2^32: raise VXCVI, return 0x80000000 + */ + +int +__q_qtoi(const unsigned long long a[2]) +{ + int ax, sgn; + unsigned long long a0; + + a0 = a[0]; + /* 'sgn' is -1 if 'a' is negative, 0 if positive. */ + sgn = (long long)a0 >> 63; + ax = (a0 >> 48 & 0x7fff) - 16383; + /* Deal with non-special cases. */ + if (ax <= 30) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. The '^ sgn) - sgn' part is + equivalent in this case to multiplication by 'sgn', but usually + faster. */ + return (((unsigned)(a0 >> 17 | 0x80000000) >> 31-ax & -(ax >> 31)) + ^ sgn) - sgn; + + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a[1] | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + + /* Treat all NaNs as large negative numbers. */ + sgn |= -cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + /* All the specials raise VXCVI. */ + set_fpscr_bit(FPSCR_VXCVI); + + /* Return 0x7fffffff (if a < 0) or 0x80000000 (otherwise). */ + return sgn ^ 0x7fffffff; +} diff --git a/sysdeps/powerpc/q_qtoll.c b/sysdeps/powerpc/q_qtoll.c new file mode 100644 index 0000000000..77a54f8bf9 --- /dev/null +++ b/sysdeps/powerpc/q_qtoll.c @@ -0,0 +1,64 @@ +/* 128-bit floating point to 64-bit fixed point signed integer. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long long _q_qtoll(const long double *a); + Convert 'a' to signed long long by truncation. + + Special cases: + NaN: raise VXCVI, return 0x8000000000000000 + SNaN: raise VXSNAN, VXCVI, and return 0x8000000000000000 + >= 2^32: raise VXCVI, return 0x7fffffffffffffff + <= -2^32: raise VXCVI, return 0x8000000000000000 + */ + +long long +__q_qtoll(const unsigned long long a[2]) +{ + int ax, sgn; + unsigned long long a0, a1; + + a0 = a[0]; a1 = a[1]; + /* 'sgn' is -1 if 'a' is negative, 0 if positive. */ + sgn = (long long)a0 >> 63; + ax = (a0 >> 48 & 0x7fff) - 16383; + /* Deal with non-special cases. */ + if (ax <= 62) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. The '^ sgn) - sgn' part is + equivalent in this case to multiplication by 'sgn', but faster. */ + return (((a0 << 15 | a1 >> 64-15 | 0x8000000000000000ULL) >> 63-ax + & -(unsigned long long)(ax >> 31)) + ^ (long long)sgn) - sgn; + + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a1 | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + + /* Treat all NaNs as large negative numbers. */ + sgn |= -cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + /* All the specials raise VXCVI. */ + set_fpscr_bit(FPSCR_VXCVI); + + return (long long)sgn ^ 0x7fffffffffffffffLL; +} diff --git a/sysdeps/powerpc/q_qtos.c b/sysdeps/powerpc/q_qtos.c new file mode 100644 index 0000000000..cd2715f8e9 --- /dev/null +++ b/sysdeps/powerpc/q_qtos.c @@ -0,0 +1,84 @@ +/* 128-bit floating point to 32-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* float _q_qtos(const long double *a); + Convert 'a' to float. Round as per current rounding flags. + + Input Rounding Output + +/-0 * +/-0 + +/-Inf * +/-Inf + +/-NaN * +/-NaN (with mantissa truncated) + +/-SNaN * +/-NaN (with mantissa truncated, MSB of mantissa <- 1) + && raise VXSNAN + [Note: just truncating the mantissa may not give you + a SNaN!] + |a|>=2^128 Nearest +/-Inf && raise overflow && raise inexact + |a|>=2^128 Truncate +/-(2^128-2^104) && raise overflow && raise inexact + a>=2^128 +Inf +Inf && raise overflow && raise inexact + a<=-2^128 +Inf -(2^128-2^104) && raise overflow && raise inexact + a>=2^128 -Inf +(2^128-2^104) && raise overflow && raise inexact + a<=-2^128 -Inf -Inf && raise overflow && raise inexact + + We also need to raise 'inexact' if the result will be inexact, which + depends on the current rounding mode. + + To avoid having to deal with all that, we convert to a 'double' + that will round correctly (but is not itself rounded correctly), + and convert that to a float. This makes this procedure much + simpler and much faster. */ + +float +__q_qtos(const unsigned long long a[2]) +{ + unsigned long long a0,d; + union { + double d; + unsigned long long ull; + } u; + + a0 = a[0]; + + /* Truncate the mantissa to 48 bits. */ + d = a0 << 4; + /* Set the low bit in the mantissa if any of the bits we are dropping + were 1. This ensures correct rounding, and also distinguishes + 0 and Inf from denormalised numbers and SNaN (respectively). */ + d |= a[1] != 0; + /* Copy the sign bit. */ + d = d & 0x7fffffffffffffffULL | a0 & 0x8000000000000000ULL; + + /* Now, we need to fix the exponent. If the exponent of a was in + the range +127 to -152, or was +16384 or -16383, it is already + correct in 'd'. Otherwise, we need to ensure that the new + exponent is in the range +1023 to +128, or -153 to -1022, with + the same sign as the exponent of 'a'. We can do this by setting + bits 1-3 (the second through fourth-most significant bit) of 'd' + to 101 if bit 1 of 'a' is 1, or 010 if bit 1 of 'a' is 0. */ + if ((a0 >> 56 & 0x7f) - 0x3f > 1) + { + unsigned t = (a0 >> 32+2 & 2 << 31-1-2)*3 + (2 << 31-2); + d = (d & 0x8fffffffffffffffULL + | (unsigned long long)t<<32 & 0x7000000000000000ULL); + } + + u.ull = d; + return (float)u.d; +} diff --git a/sysdeps/powerpc/q_qtou.c b/sysdeps/powerpc/q_qtou.c new file mode 100644 index 0000000000..a5583cc816 --- /dev/null +++ b/sysdeps/powerpc/q_qtou.c @@ -0,0 +1,64 @@ +/* 128-bit floating point to 32-bit fixed point unsigned integer. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* unsigned int _q_qtou(const long double *a); + Convert 'a' to unsigned int by truncation. + + Special cases: + -0: return 0 + NaN: raise VXCVI, return 0 + SNaN: raise VXSNAN, VXCVI, and return 0 + Negative numbers (other than -0, but including -Inf): raise VXCVI, return 0 + >= 2^32: raise VXCVI, return 0xffffffff + */ + +unsigned int +__q_qtou(const unsigned long long a[2]) +{ + int ax; + unsigned result; + unsigned long long a0; + + /* Deal with non-special cases. */ + a0 = a[0]; + ax = (a0 >> 48) - 16383; + if (ax <= 31) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. */ + return (unsigned)(a0 >> 17 | 0x80000000) >> 31-ax & -(ax >> 31); + + /* 'result' is 1 if a is negative, 0 otherwise. */ + result = a0 >> 63; + /* Check for -0, otherwise raise VXCVI. */ + if (a0 != 0x8000000000000000ULL || a[1] != 0) + { + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a[1] | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Treat all NaNs as large negative numbers. */ + result |= cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + set_fpscr_bit(FPSCR_VXCVI); + } + return result-1; +} diff --git a/sysdeps/powerpc/q_qtoull.c b/sysdeps/powerpc/q_qtoull.c new file mode 100644 index 0000000000..e0b84d3e84 --- /dev/null +++ b/sysdeps/powerpc/q_qtoull.c @@ -0,0 +1,65 @@ +/* 128-bit floating point to 64-bit fixed point unsigned integer. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* unsigned long long _q_qtoull(const long double *a); + Convert 'a' to unsigned long long by truncation. + + Special cases: + -0: return 0 + NaN: raise VXCVI, return 0 + SNaN: raise VXSNAN, VXCVI, and return 0 + Negative numbers (other than -0, but including -Inf): raise VXCVI, return 0 + >= 2^32: raise VXCVI, return 0xffffffffffffffff + */ + +unsigned long long +__q_qtoull(const unsigned long long a[2]) +{ + int ax; + unsigned result; + unsigned long long a0, a1; + + /* Deal with non-special cases. */ + a0 = a[0]; a1 = a[1]; + ax = (a0 >> 48) - 16383; + if (ax <= 63) + /* If we had a '>>' operator that behaved properly with respect to + large shifts, we wouldn't need the '& -(ax >> 31)' term, which + clears 'result' if ax is negative. */ + return ((a0 << 15 | a1 >> 64-15 | 0x8000000000000000ULL) >> 63-ax + & -(unsigned long long)(ax >> 31)); + + /* 'result' is 1 if a is negative, 0 otherwise. */ + result = a0 >> 63; + /* Check for -0, otherwise raise VXCVI. */ + if (a0 != 0x8000000000000000ULL || a[1] != 0) + { + /* Check for SNaN, if so raise VXSNAN. */ + if ((a0 >> 32 & 0x7fff8000) == 0x7fff0000 + && (a1 | a0 & 0x00007fffffffffffULL) != 0) + set_fpscr_bit(FPSCR_VXSNAN); + /* Treat all NaNs as large negative numbers. */ + result |= cntlzw(~(a0 >> 32) & 0x7fff0000) >> 5; + + set_fpscr_bit(FPSCR_VXCVI); + } + return result-1LL; +} diff --git a/sysdeps/powerpc/q_stoq.c b/sysdeps/powerpc/q_stoq.c new file mode 100644 index 0000000000..766997b97b --- /dev/null +++ b/sysdeps/powerpc/q_stoq.c @@ -0,0 +1,65 @@ +/* 32-bit floating point to 128-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_stoq(float a); + Convert 'a' to long double. Don't raise exceptions. + */ + +void +__q_stoq(unsigned long long result[2], float a) +{ + unsigned ux, rx; + union { + float d; + unsigned u; + } u; + + u.d = a; + result[1] = 0; + result[0] = u.u << 32-7; + /* correct exponent bias */ + rx = ((int)u.u >> 23 & 0x80ff) + 16383-127; + + ux = u.u >> 23 & 0xff; + if (ux == 0) + { + if ((u.u & 0x7fffffff) == 0) + { + /* +0.0 or -0.0. */ + rx &= 0x8000; + } + else + { + /* Denormalised number. Renormalise. */ + unsigned um = u.u & 0x007fffff; + int cs = cntlzw(um) - 9 + 1; + rx -= cs; + um <<= cs; + result[0] = um << 32-7; + } + } + else if (ux == 0xff) + { + /* Inf or NaN. */ + rx |= 0x7fff; + } + *(unsigned short *)result = rx; +} diff --git a/sysdeps/powerpc/q_ulltoq.c b/sysdeps/powerpc/q_ulltoq.c new file mode 100644 index 0000000000..caae124781 --- /dev/null +++ b/sysdeps/powerpc/q_ulltoq.c @@ -0,0 +1,46 @@ +/* 64-bit fixed point unsigned integer to 128-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_ulltoq(unsigned long long a); + Convert 'a' to long double. + */ + +void +__q_ulltoq(unsigned int result[4], unsigned long long a) +{ + unsigned rx; + int cs, css; + + /* Normalize. */ + cs = cntlzd(a); + a <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 63-cs; + rx = 16383+css << 16 & ~css; + + /* Put it all together. */ + result[3] = 0; + result[0] = rx & 0xffff0000 | a >> 48 & 0x0000ffff; + a <<= 16; + result[2] = a; + result[1] = a >> 32; +} diff --git a/sysdeps/powerpc/q_utoq.c b/sysdeps/powerpc/q_utoq.c new file mode 100644 index 0000000000..84ce215a00 --- /dev/null +++ b/sysdeps/powerpc/q_utoq.c @@ -0,0 +1,44 @@ +/* 32-bit fixed point unsigned integer to 128-bit floating point. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <quad_float.h> + +/* long double _q_utoq(unsigned int a); + Convert 'a' to long double. + */ + +void +__q_utoq(unsigned int result[4], unsigned int a) +{ + unsigned rx; + int cs, css; + + /* Normalize. */ + cs = cntlzw(a); + a <<= cs+1; + + /* Calculate the exponent, in 4 easy instructions. */ + css = 31-cs; + rx = 16383+css << 16 & ~css; + + /* Put it all together. */ + result[2] = result[3] = 0; + asm ("rlwimi %0,%1,16,16,31": "=r"(result[0]) : "r"(a), "0"(rx)); + result[1] = a << 16; +} diff --git a/sysdeps/powerpc/quad_float.h b/sysdeps/powerpc/quad_float.h new file mode 100644 index 0000000000..787e8d9ab9 --- /dev/null +++ b/sysdeps/powerpc/quad_float.h @@ -0,0 +1,44 @@ +/* Internal libc stuff for 128-bit IEEE FP emulation routines. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _QUAD_FLOAT_H +#define _QUAD_FLOAT_H 1 + +#include <fenv_libc.h> + +/* Returns the number of leading zero bits in 'x' (between 0 and 32 + inclusive). 'x' is treated as being 32 bits long. */ +#define cntlzw(x) \ + ({ unsigned p = (x); \ + unsigned r; \ + asm ("cntlzw %0,%1" : "=r"(r) : "r"(p)); \ + r; }) + +/* Returns the number of leading zero bits in 'x' (between 0 and 64 + inclusive). 'x' is treated as being 64 bits long. */ +#define cntlzd(x) \ + ({ unsigned long long q = (x); \ + unsigned int c1, c2; \ + c1 = cntlzw(q >> 32); \ + c2 = cntlzw(q); \ + c1 + (-(c1 >> 5) & c2); }) + +#define shift_and_or + +#endif /* quad_float.h */ diff --git a/sysdeps/powerpc/s_copysign.S b/sysdeps/powerpc/s_copysign.S new file mode 100644 index 0000000000..adc7df226a --- /dev/null +++ b/sysdeps/powerpc/s_copysign.S @@ -0,0 +1,60 @@ +/* Copy a sign bit between floating-point values. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This has been coded in assembler because GCC makes such a mess of it + when it's coded in C. */ + + .section ".text" + .align 2 + .globl __copysign + .type __copysign,@function +__copysign: +/* double [f1] copysign (double [f1] x, double [f2] y); + copysign(x,y) returns a value with the magnitude of x and + with the sign bit of y. */ + + stwu %r1,-16(%r1) + stfd %f2,8(%r1) + lwz %r3,8(%r1) + cmpwi %r3,0 + addi %r1,%r1,16 + blt 0f + fabs %f1,%f1 + blr +0: fnabs %f1,%f1 + blr +0: + .size __copysign,0b-__copysign + + .globl copysign + .globl copysignf + .globl __copysignf + .weak copysign + .weak copysignf + .set copysign,__copysign +/* It turns out that it's safe to use this code even for single-precision. */ + .set __copysignf,__copysign + .set copysignf,__copysign +#ifdef NO_LONG_DOUBLE + .globl copysignl + .globl __copysignl + .weak copysignl + .set __copysignl,__copysign + .set copysignl,__copysign +#endif diff --git a/sysdeps/powerpc/s_fabs.S b/sysdeps/powerpc/s_fabs.S new file mode 100644 index 0000000000..a52733568d --- /dev/null +++ b/sysdeps/powerpc/s_fabs.S @@ -0,0 +1,42 @@ +/* Floating-point absolute value. PowerPC version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + .section ".text" + .align 2 + .globl __fabs + .type __fabs,@function +__fabs: +/* double [f1] fabs (double [f1] x); */ + fabs %f1,%f1 + blr +0: + .size __fabs,0b-__fabs + + .globl fabs,fabsf,__fabsf + .weak fabs,fabsf + .set fabs,__fabs +/* It turns out that it's safe to use this code even for single-precision. */ + .set __fabsf,__fabs + .set fabsf,__fabs +#ifdef NO_LONG_DOUBLE + .globl fabsl,__fabsl + .weak fabsl + .set __fabsl,__fabs + .set fabsl,__fabs +#endif diff --git a/sysdeps/powerpc/s_isnan.c b/sysdeps/powerpc/s_isnan.c new file mode 100644 index 0000000000..34019fdbdb --- /dev/null +++ b/sysdeps/powerpc/s_isnan.c @@ -0,0 +1,47 @@ +/* Return 1 if argument is a NaN, else 0. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "math.h" +#include <fenv_libc.h> + +int __isnan(double x) +{ + fenv_t savedstate; + int result; + savedstate = fegetenv_register(); + reset_fpscr_bit(FPSCR_VE); + result = !(x == x); + fesetenv_register(savedstate); + return result; +} +weak_alias (__isnan, isnan) +/* It turns out that the 'double' version will also always work for + single-precision. Use explicit assembler to stop gcc complaining + that 'isnanf' takes a float parameter, not double. */ +asm ("\ + .globl __isnanf + .globl isnanf + .weak isnanf + .set __isnanf,__isnan + .set isnanf,__isnan +"); +#ifdef NO_LONG_DOUBLE +strong_alias (__isnan, __isnanl) +weak_alias (__isnan, isnanl) +#endif diff --git a/sysdeps/powerpc/s_llrint.c b/sysdeps/powerpc/s_llrint.c new file mode 100644 index 0000000000..7ca48c029a --- /dev/null +++ b/sysdeps/powerpc/s_llrint.c @@ -0,0 +1,28 @@ +/* Round a long long floating point value to an integer in the current + rounding mode. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "math.h" + +long long int +__llrint (long double x) +{ + return (long long int) __rintl (x); +} +weak_alias (__llrint, llrint) diff --git a/sysdeps/powerpc/s_llround.c b/sysdeps/powerpc/s_llround.c new file mode 100644 index 0000000000..fbe3a3217c --- /dev/null +++ b/sysdeps/powerpc/s_llround.c @@ -0,0 +1,46 @@ +/* Round long double value to long int. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + +/* I think that what this routine is supposed to do is round a value + to the nearest integer, with values exactly on the boundary rounded + away from zero. */ +/* This routine relies on (long long)x, when x is out of range of a long long, + clipping to MAX_LLONG or MIN_LLONG. */ + +long long int +__llround (long double x) +{ + long double xrf; + long long int xr; + xr = (long long int) x; + xrf = (long double) xr; + if (x >= 0.0) + if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0) + return x+1; + else + return x; + else + if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0) + return x-1; + else + return x; +} +weak_alias (__llround, llround) diff --git a/sysdeps/powerpc/s_lrint.c b/sysdeps/powerpc/s_lrint.c new file mode 100644 index 0000000000..647cf30c9c --- /dev/null +++ b/sysdeps/powerpc/s_lrint.c @@ -0,0 +1,44 @@ +/* Round floating-point to integer. PowerPC version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "math.h" + +#ifdef NO_LONG_DOUBLE + +long int +__lrint (long double x) +{ + return (long int) __rintl(x); +} + +#else + +long int +__lrint (long double x) +{ + union { + double d; + long int ll[2]; + } u; + asm ("fctiw %0,%1" : "=f"(u.d) : "f"(x)); + return d.ll[1]; +} + +#endif +weak_alias (__lrint, lrint) diff --git a/sysdeps/powerpc/s_lround.c b/sysdeps/powerpc/s_lround.c new file mode 100644 index 0000000000..a6cb6c96d2 --- /dev/null +++ b/sysdeps/powerpc/s_lround.c @@ -0,0 +1,46 @@ +/* Round long double value to long int. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <math.h> + +/* I think that what this routine is supposed to do is round a value + to the nearest integer, with values exactly on the boundary rounded + away from zero. */ +/* This routine relies on (long int)x, when x is out of range of a long int, + clipping to MAX_LONG or MIN_LONG. */ + +long int +__lround (long double x) +{ + long double xrf; + long int xr; + xr = (long int) x; + xrf = (long double) xr; + if (x >= 0.0) + if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0) + return x+1; + else + return x; + else + if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0) + return x-1; + else + return x; +} +weak_alias (__lround, lround) diff --git a/sysdeps/powerpc/s_rint.c b/sysdeps/powerpc/s_rint.c new file mode 100644 index 0000000000..d6d1dd2f76 --- /dev/null +++ b/sysdeps/powerpc/s_rint.c @@ -0,0 +1,45 @@ +/* Round a 64-bit floating point value to the nearest integer. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "math.h" + +double +__rint (double x) +{ + static const float TWO52 = 4503599627370496.0; + + if (fabs (x) < TWO52) + if (x > 0.0) + { + x += TWO52; + x -= TWO52; + } + else if (x < 0.0) + { + x -= TWO52; + x += TWO52; + } + + return x; +} +weak_alias (__rint, rint) +#ifdef NO_LONG_DOUBLE +strong_alias (__rint, __rintl) +weak_alias (__rint, rintl) +#endif diff --git a/sysdeps/powerpc/s_rintf.c b/sysdeps/powerpc/s_rintf.c new file mode 100644 index 0000000000..b95c0540bf --- /dev/null +++ b/sysdeps/powerpc/s_rintf.c @@ -0,0 +1,41 @@ +/* Round a 32-bit floating point value to the nearest integer. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "math.h" + +float +__rintf (float x) +{ + static const float TWO23 = 8388608.0; + + if (fabsf (x) < TWO23) + if (x > 0.0) + { + x += TWO23; + x -= TWO23; + } + else if (x < 0.0) + { + x -= TWO23; + x += TWO23; + } + + return x; +} +weak_alias (__rintf, rintf) diff --git a/sysdeps/powerpc/strlen.s b/sysdeps/powerpc/strlen.s index 9d671cabc3..ea809772eb 100644 --- a/sysdeps/powerpc/strlen.s +++ b/sysdeps/powerpc/strlen.s @@ -61,8 +61,8 @@ # Some notes on register usage: Under the SVR4 ABI, we can use registers # 0 and 3 through 12 (so long as we don't call any procedures) without # saving them. We can also use registers 14 through 31 if we save them. - # We can't use r1 (it's the stack pointer), nor r2 or r13 because the user - # program may expect them to be hold their usual value if we get sent + # We can't use r1 (it's the stack pointer), r2 nor r13 because the user + # program may expect them to hold their usual value if we get sent # a signal. Integer parameters are passed in r3 through r10. # We can use condition registers cr0, cr1, cr5, cr6, and cr7 without saving # them, the others we must save. @@ -80,14 +80,11 @@ strlen: # r9-12 are temporaries. r0 is used as a temporary and for discarded # results. clrrwi %r4,%r3,2 - lis %r6,0xfeff lis %r7,0x7f7f - rlwinm %r10,%r3,0,29,29 - lwz %r8,0(%r4) - addi %r7,%r7,0x7f7f rlwinm %r5,%r3,3,27,28 - cmpwi %cr1,%r10,0 + lwz %r8,0(%r4) li %r9,-1 + addi %r7,%r7,0x7f7f # That's the setup done, now do the first pair of words. # We make an exception and use method (2) on the first two words, to reduce # overhead. @@ -97,12 +94,14 @@ strlen: add %r0,%r0,%r7 nor %r0,%r10,%r0 and. %r8,%r0,%r9 + mtcrf 0x01,%r3 bne done0 - # Handle second word of pair. Put addi between branches to avoid hurting - # branch prediction. + lis %r6,0xfeff addi %r6,%r6,-0x101 + # Are we now aligned to a doubleword boundary? + bt 29,loop - bne %cr1,loop + # Handle second word of pair. lwzu %r8,4(%r4) and %r0,%r7,%r8 or %r10,%r7,%r8 diff --git a/sysdeps/powerpc/t_sqrt.c b/sysdeps/powerpc/t_sqrt.c new file mode 100644 index 0000000000..c49380c0fd --- /dev/null +++ b/sysdeps/powerpc/t_sqrt.c @@ -0,0 +1,144 @@ +const float __t_sqrt[1024] = { +0.7078,0.7064, 0.7092,0.7050, 0.7106,0.7037, 0.7119,0.7023, 0.7133,0.7010, +0.7147,0.6996, 0.7160,0.6983, 0.7174,0.6970, 0.7187,0.6957, 0.7201,0.6943, +0.7215,0.6930, 0.7228,0.6917, 0.7242,0.6905, 0.7255,0.6892, 0.7269,0.6879, +0.7282,0.6866, 0.7295,0.6854, 0.7309,0.6841, 0.7322,0.6829, 0.7335,0.6816, +0.7349,0.6804, 0.7362,0.6792, 0.7375,0.6779, 0.7388,0.6767, 0.7402,0.6755, +0.7415,0.6743, 0.7428,0.6731, 0.7441,0.6719, 0.7454,0.6708, 0.7467,0.6696, +0.7480,0.6684, 0.7493,0.6672, 0.7507,0.6661, 0.7520,0.6649, 0.7532,0.6638, +0.7545,0.6627, 0.7558,0.6615, 0.7571,0.6604, 0.7584,0.6593, 0.7597,0.6582, +0.7610,0.6570, 0.7623,0.6559, 0.7635,0.6548, 0.7648,0.6537, 0.7661,0.6527, +0.7674,0.6516, 0.7686,0.6505, 0.7699,0.6494, 0.7712,0.6484, 0.7725,0.6473, +0.7737,0.6462, 0.7750,0.6452, 0.7762,0.6441, 0.7775,0.6431, 0.7787,0.6421, +0.7800,0.6410, 0.7812,0.6400, 0.7825,0.6390, 0.7837,0.6380, 0.7850,0.6370, +0.7862,0.6359, 0.7875,0.6349, 0.7887,0.6339, 0.7900,0.6330, 0.7912,0.6320, +0.7924,0.6310, 0.7937,0.6300, 0.7949,0.6290, 0.7961,0.6281, 0.7973,0.6271, +0.7986,0.6261, 0.7998,0.6252, 0.8010,0.6242, 0.8022,0.6233, 0.8034,0.6223, +0.8046,0.6214, 0.8059,0.6205, 0.8071,0.6195, 0.8083,0.6186, 0.8095,0.6177, +0.8107,0.6168, 0.8119,0.6158, 0.8131,0.6149, 0.8143,0.6140, 0.8155,0.6131, +0.8167,0.6122, 0.8179,0.6113, 0.8191,0.6104, 0.8203,0.6096, 0.8215,0.6087, +0.8227,0.6078, 0.8238,0.6069, 0.8250,0.6060, 0.8262,0.6052, 0.8274,0.6043, +0.8286,0.6035, 0.8297,0.6026, 0.8309,0.6017, 0.8321,0.6009, 0.8333,0.6000, +0.8344,0.5992, 0.8356,0.5984, 0.8368,0.5975, 0.8379,0.5967, 0.8391,0.5959, +0.8403,0.5950, 0.8414,0.5942, 0.8426,0.5934, 0.8437,0.5926, 0.8449,0.5918, +0.8461,0.5910, 0.8472,0.5902, 0.8484,0.5894, 0.8495,0.5886, 0.8507,0.5878, +0.8518,0.5870, 0.8530,0.5862, 0.8541,0.5854, 0.8552,0.5846, 0.8564,0.5838, +0.8575,0.5831, 0.8587,0.5823, 0.8598,0.5815, 0.8609,0.5808, 0.8621,0.5800, +0.8632,0.5792, 0.8643,0.5785, 0.8655,0.5777, 0.8666,0.5770, 0.8677,0.5762, +0.8688,0.5755, 0.8700,0.5747, 0.8711,0.5740, 0.8722,0.5733, 0.8733,0.5725, +0.8744,0.5718, 0.8756,0.5711, 0.8767,0.5703, 0.8778,0.5696, 0.8789,0.5689, +0.8800,0.5682, 0.8811,0.5675, 0.8822,0.5667, 0.8833,0.5660, 0.8844,0.5653, +0.8855,0.5646, 0.8866,0.5639, 0.8877,0.5632, 0.8888,0.5625, 0.8899,0.5618, +0.8910,0.5611, 0.8921,0.5605, 0.8932,0.5598, 0.8943,0.5591, 0.8954,0.5584, +0.8965,0.5577, 0.8976,0.5570, 0.8987,0.5564, 0.8998,0.5557, 0.9008,0.5550, +0.9019,0.5544, 0.9030,0.5537, 0.9041,0.5530, 0.9052,0.5524, 0.9062,0.5517, +0.9073,0.5511, 0.9084,0.5504, 0.9095,0.5498, 0.9105,0.5491, 0.9116,0.5485, +0.9127,0.5478, 0.9138,0.5472, 0.9148,0.5465, 0.9159,0.5459, 0.9170,0.5453, +0.9180,0.5446, 0.9191,0.5440, 0.9202,0.5434, 0.9212,0.5428, 0.9223,0.5421, +0.9233,0.5415, 0.9244,0.5409, 0.9254,0.5403, 0.9265,0.5397, 0.9276,0.5391, +0.9286,0.5384, 0.9297,0.5378, 0.9307,0.5372, 0.9318,0.5366, 0.9328,0.5360, +0.9338,0.5354, 0.9349,0.5348, 0.9359,0.5342, 0.9370,0.5336, 0.9380,0.5330, +0.9391,0.5324, 0.9401,0.5319, 0.9411,0.5313, 0.9422,0.5307, 0.9432,0.5301, +0.9442,0.5295, 0.9453,0.5289, 0.9463,0.5284, 0.9473,0.5278, 0.9484,0.5272, +0.9494,0.5266, 0.9504,0.5261, 0.9515,0.5255, 0.9525,0.5249, 0.9535,0.5244, +0.9545,0.5238, 0.9556,0.5233, 0.9566,0.5227, 0.9576,0.5221, 0.9586,0.5216, +0.9596,0.5210, 0.9607,0.5205, 0.9617,0.5199, 0.9627,0.5194, 0.9637,0.5188, +0.9647,0.5183, 0.9657,0.5177, 0.9667,0.5172, 0.9677,0.5167, 0.9687,0.5161, +0.9698,0.5156, 0.9708,0.5151, 0.9718,0.5145, 0.9728,0.5140, 0.9738,0.5135, +0.9748,0.5129, 0.9758,0.5124, 0.9768,0.5119, 0.9778,0.5114, 0.9788,0.5108, +0.9798,0.5103, 0.9808,0.5098, 0.9818,0.5093, 0.9828,0.5088, 0.9838,0.5083, +0.9847,0.5077, 0.9857,0.5072, 0.9867,0.5067, 0.9877,0.5062, 0.9887,0.5057, +0.9897,0.5052, 0.9907,0.5047, 0.9917,0.5042, 0.9926,0.5037, 0.9936,0.5032, +0.9946,0.5027, 0.9956,0.5022, 0.9966,0.5017, 0.9976,0.5012, 0.9985,0.5007, +0.9995,0.5002, +1.0010,0.4995, 1.0029,0.4985, 1.0049,0.4976, 1.0068,0.4966, 1.0088,0.4957, +1.0107,0.4947, 1.0126,0.4938, 1.0145,0.4928, 1.0165,0.4919, 1.0184,0.4910, +1.0203,0.4901, 1.0222,0.4891, 1.0241,0.4882, 1.0260,0.4873, 1.0279,0.4864, +1.0298,0.4855, 1.0317,0.4846, 1.0336,0.4837, 1.0355,0.4829, 1.0374,0.4820, +1.0393,0.4811, 1.0411,0.4802, 1.0430,0.4794, 1.0449,0.4785, 1.0468,0.4777, +1.0486,0.4768, 1.0505,0.4760, 1.0523,0.4751, 1.0542,0.4743, 1.0560,0.4735, +1.0579,0.4726, 1.0597,0.4718, 1.0616,0.4710, 1.0634,0.4702, 1.0653,0.4694, +1.0671,0.4686, 1.0689,0.4678, 1.0707,0.4670, 1.0726,0.4662, 1.0744,0.4654, +1.0762,0.4646, 1.0780,0.4638, 1.0798,0.4630, 1.0816,0.4623, 1.0834,0.4615, +1.0852,0.4607, 1.0870,0.4600, 1.0888,0.4592, 1.0906,0.4585, 1.0924,0.4577, +1.0942,0.4570, 1.0960,0.4562, 1.0978,0.4555, 1.0995,0.4547, 1.1013,0.4540, +1.1031,0.4533, 1.1049,0.4525, 1.1066,0.4518, 1.1084,0.4511, 1.1101,0.4504, +1.1119,0.4497, 1.1137,0.4490, 1.1154,0.4483, 1.1172,0.4476, 1.1189,0.4469, +1.1207,0.4462, 1.1224,0.4455, 1.1241,0.4448, 1.1259,0.4441, 1.1276,0.4434, +1.1293,0.4427, 1.1311,0.4421, 1.1328,0.4414, 1.1345,0.4407, 1.1362,0.4401, +1.1379,0.4394, 1.1397,0.4387, 1.1414,0.4381, 1.1431,0.4374, 1.1448,0.4368, +1.1465,0.4361, 1.1482,0.4355, 1.1499,0.4348, 1.1516,0.4342, 1.1533,0.4335, +1.1550,0.4329, 1.1567,0.4323, 1.1584,0.4316, 1.1600,0.4310, 1.1617,0.4304, +1.1634,0.4298, 1.1651,0.4292, 1.1668,0.4285, 1.1684,0.4279, 1.1701,0.4273, +1.1718,0.4267, 1.1734,0.4261, 1.1751,0.4255, 1.1768,0.4249, 1.1784,0.4243, +1.1801,0.4237, 1.1817,0.4231, 1.1834,0.4225, 1.1850,0.4219, 1.1867,0.4213, +1.1883,0.4208, 1.1900,0.4202, 1.1916,0.4196, 1.1932,0.4190, 1.1949,0.4185, +1.1965,0.4179, 1.1981,0.4173, 1.1998,0.4167, 1.2014,0.4162, 1.2030,0.4156, +1.2046,0.4151, 1.2063,0.4145, 1.2079,0.4139, 1.2095,0.4134, 1.2111,0.4128, +1.2127,0.4123, 1.2143,0.4117, 1.2159,0.4112, 1.2175,0.4107, 1.2192,0.4101, +1.2208,0.4096, 1.2224,0.4090, 1.2239,0.4085, 1.2255,0.4080, 1.2271,0.4075, +1.2287,0.4069, 1.2303,0.4064, 1.2319,0.4059, 1.2335,0.4054, 1.2351,0.4048, +1.2366,0.4043, 1.2382,0.4038, 1.2398,0.4033, 1.2414,0.4028, 1.2429,0.4023, +1.2445,0.4018, 1.2461,0.4013, 1.2477,0.4008, 1.2492,0.4003, 1.2508,0.3998, +1.2523,0.3993, 1.2539,0.3988, 1.2555,0.3983, 1.2570,0.3978, 1.2586,0.3973, +1.2601,0.3968, 1.2617,0.3963, 1.2632,0.3958, 1.2648,0.3953, 1.2663,0.3949, +1.2678,0.3944, 1.2694,0.3939, 1.2709,0.3934, 1.2725,0.3929, 1.2740,0.3925, +1.2755,0.3920, 1.2771,0.3915, 1.2786,0.3911, 1.2801,0.3906, 1.2816,0.3901, +1.2832,0.3897, 1.2847,0.3892, 1.2862,0.3887, 1.2877,0.3883, 1.2892,0.3878, +1.2907,0.3874, 1.2923,0.3869, 1.2938,0.3865, 1.2953,0.3860, 1.2968,0.3856, +1.2983,0.3851, 1.2998,0.3847, 1.3013,0.3842, 1.3028,0.3838, 1.3043,0.3834, +1.3058,0.3829, 1.3073,0.3825, 1.3088,0.3820, 1.3103,0.3816, 1.3118,0.3812, +1.3132,0.3807, 1.3147,0.3803, 1.3162,0.3799, 1.3177,0.3794, 1.3192,0.3790, +1.3207,0.3786, 1.3221,0.3782, 1.3236,0.3778, 1.3251,0.3773, 1.3266,0.3769, +1.3280,0.3765, 1.3295,0.3761, 1.3310,0.3757, 1.3324,0.3753, 1.3339,0.3748, +1.3354,0.3744, 1.3368,0.3740, 1.3383,0.3736, 1.3397,0.3732, 1.3412,0.3728, +1.3427,0.3724, 1.3441,0.3720, 1.3456,0.3716, 1.3470,0.3712, 1.3485,0.3708, +1.3499,0.3704, 1.3514,0.3700, 1.3528,0.3696, 1.3542,0.3692, 1.3557,0.3688, +1.3571,0.3684, 1.3586,0.3680, 1.3600,0.3676, 1.3614,0.3673, 1.3629,0.3669, +1.3643,0.3665, 1.3657,0.3661, 1.3672,0.3657, 1.3686,0.3653, 1.3700,0.3650, +1.3714,0.3646, 1.3729,0.3642, 1.3743,0.3638, 1.3757,0.3634, 1.3771,0.3631, +1.3785,0.3627, 1.3800,0.3623, 1.3814,0.3620, 1.3828,0.3616, 1.3842,0.3612, +1.3856,0.3609, 1.3870,0.3605, 1.3884,0.3601, 1.3898,0.3598, 1.3912,0.3594, +1.3926,0.3590, 1.3940,0.3587, 1.3954,0.3583, 1.3968,0.3580, 1.3982,0.3576, +1.3996,0.3572, 1.4010,0.3569, 1.4024,0.3565, 1.4038,0.3562, 1.4052,0.3558, +1.4066,0.3555, 1.4080,0.3551, 1.4094,0.3548, 1.4108,0.3544, 1.4121,0.3541, +1.4135,0.3537 +}; + + +/* Generated by: */ +#if 0 +#include <math.h> +#include <stdio.h> +#include <assert.h> + +int +main(int argc, char **argv) +{ + int i, j; + + printf ("const float __t_sqrt[1024] = {"); + for (i = 0; i < 2; i++) + { + putchar('\n'); + for (j = 0; j < 256; j++) + { + double mval = j/512.0 + 0.5; + double eval = i==0 ? 1.0 : 2.0; + double ls = sqrt(mval*eval); + double hs = sqrt((mval+1/512.0)*eval); + double as = (ls+hs)*0.5; + double lx = 1/(2.0*ls); + double hx = 1/(2.0*hs); + double ax = (lx+hx)*0.5; + + printf("%.4f,%.4f%s",as,ax, + i*j==255 ? "\n" : j % 5 == 4 ? ",\n" : ", "); + assert((hs-ls)/as < 1/256.0); + assert((hx-lx)/ax < 1/256.0); + } + } + printf ("};\n"); + return 0; +} +#endif /* 0 */ diff --git a/sysdeps/powerpc/test-arith.c b/sysdeps/powerpc/test-arith.c new file mode 100644 index 0000000000..c846b0d0ec --- /dev/null +++ b/sysdeps/powerpc/test-arith.c @@ -0,0 +1,604 @@ +/* Test floating-point arithmetic operations. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fenv.h> +#include <assert.h> + +#ifndef ESIZE +typedef double tocheck_t; +#define ESIZE 11 +#define MSIZE 52 +#define FUNC(x) x +#endif + +#define R_NEAREST 1 +#define R_ZERO 2 +#define R_UP 4 +#define R_DOWN 8 +#define R_ALL (R_NEAREST|R_ZERO|R_UP|R_DOWN) +static fenv_t rmodes[4]; +static const char * const rmnames[4] = +{ "nearest","zero","+Inf","-Inf" }; + +typedef union { + tocheck_t tc; + unsigned char c[sizeof(tocheck_t)]; +} union_t; + +/* Don't try reading these in a font that doesn't distinguish + O and zero. */ +typedef enum { + P_Z = 0x0, /* 00000...0 */ + P_000O = 0x1, /* 00011...1 */ + P_001Z = 0x2, /* 00100...0 */ + P_00O = 0x3, /* 00111...1 */ + P_01Z = 0x4, /* 01000...0 */ + P_010O = 0x5, /* 01011...1 */ + P_011Z = 0x6, /* 01100...0 */ + P_0O = 0x7, /* 01111...1 */ + P_1Z = 0x8, /* 10000...0 */ + P_100O = 0x9, /* 10011...1 */ + P_101Z = 0xa, /* 10100...0 */ + P_10O = 0xb, /* 10111...1 */ + P_11Z = 0xc, /* 11000...0 */ + P_110O = 0xd, /* 11011...1 */ + P_111Z = 0xe, /* 11100...0 */ + P_O = 0xf, /* 11111...1 */ + P_Z1 = 0x11, /* 000...001 */ + P_Z10 = 0x12, /* 000...010 */ + P_Z11 = 0x13, /* 000...011 */ + P_0O00 = 0x14, /* 011...100 */ + P_0O01 = 0x15, /* 011...101 */ + P_0O0 = 0x16, /* 011...110 */ + P_1Z1 = 0x19, /* 100...001 */ + P_1Z10 = 0x1a, /* 100...010 */ + P_1Z11 = 0x1b, /* 100...011 */ + P_O00 = 0x1c, /* 111...100 */ + P_O01 = 0x1d, /* 111...101 */ + P_O0 = 0x1e, /* 111...110 */ + P_R = 0x20, /* rrr...rrr */ /* ('r' means random. ) */ + P_Ro = 0x21, /* rrr...rrr, with odd parity. */ + P_0R = 0x22, /* 0rr...rrr */ + P_1R = 0x23, /* 1rr...rrr */ + P_Rno = 0x24, /* rrr...rrr, but not all ones. */ +} pattern_t; + +static void +pattern_fill(pattern_t ptn, unsigned char *start, int bitoffset, int count) +{ +#define bitset(count, value) \ + start[(count)/8] = (start[(count)/8] & ~(1 << 7-(count)%8) \ + | (value) << 7-(count)%8) + int i; + + if (ptn >= 0 && ptn <= 0xf) + { + /* Patterns between 0 and 0xF have the following format: + The LSBit is used to fill the last n-3 bits of the pattern; + The next 3 bits are the first 3 bits of the pattern. */ + for (i = 0; i < count; i++) + if (i < 3) + bitset((bitoffset+i), ptn >> (3-i) & 1); + else + bitset((bitoffset+i), ptn >> 0 & 1); + } + else if (ptn <= 0x1f) + { + /* Patterns between 0x10 and 0x1F have the following format: + The two LSBits are the last two bits of the pattern; + The 0x8 bit is the first bit of the pattern; + The 0x4 bit is used to fill the remainder. */ + for (i = 0; i < count; i++) + if (i == 0) + bitset((bitoffset+i), ptn >> 3 & 1); + else if (i >= count-2) + bitset((bitoffset+i), ptn >> (count-1-i) & 1); + else + bitset((bitoffset+i), ptn >> 2 & 1); + } + else switch (ptn) + { + case P_0R: case P_1R: + assert(count > 0); + bitset(bitoffset, ptn & 1); + count--; + bitoffset++; + case P_R: + for (; count > 0; count--, bitoffset++) + bitset(bitoffset, rand() & 1); + break; + case P_Ro: + { + int op = 1; + assert(count > 0); + for (; count > 1; count--, bitoffset++) + bitset(bitoffset, op ^= (rand() & 1)); + bitset(bitoffset, op); + break; + } + case P_Rno: + { + int op = 1; + assert(count > 0); + for (; count > 1; count--, bitoffset++) + { + int r = rand() & 1; + op &= r; + bitset(bitoffset, r); + } + bitset(bitoffset, rand() & (op ^ 1)); + break; + } + + default: + assert(0); + } +#undef bitset +} + +static tocheck_t +pattern(int negative, pattern_t exp, pattern_t mant) +{ + union_t result; +#if 0 + int i; +#endif + + pattern_fill(negative ? P_O : P_Z, result.c, 0, 1); + pattern_fill(exp, result.c, 1, ESIZE); + pattern_fill(mant, result.c, ESIZE+1, MSIZE); +#if 0 + printf("neg=%d exp=%02x mant=%02x: ", negative, exp, mant); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", result.c[i]); + printf("\n"); +#endif + return result.tc; +} + +/* Return the closest different tocheck_t to 'x' in the direction of + 'direction', or 'x' if there is no such value. Assumes 'x' is not + a NaN. */ +static tocheck_t +delta(tocheck_t x, int direction) +{ + union_t xx; + int i; + + xx.tc = x; + if (xx.c[0] & 0x80) + direction = -direction; + if (direction == +1) + { + union_t tx; + tx.tc = pattern(xx.c[0] >> 7, P_O, P_Z); + if (memcmp(tx.c, xx.c, sizeof(tocheck_t)) == 0) + return x; + } + for (i = sizeof(tocheck_t)-1; i > 0; i--) + { + xx.c[i] += direction; + if (xx.c[i] != (direction > 0 ? 0 : 0xff)) + return xx.tc; + } + if (direction < 0 && (xx.c[0] & 0x7f) == 0) + return pattern(~(xx.c[0] >> 7) & 1, P_Z, P_Z1); + else + { + xx.c[0] += direction; + return xx.tc; + } +} + +static int nerrors = 0; + +#ifdef FE_ALL_INVALID +static const int all_exceptions = FE_ALL_INVALID | FE_ALL_EXCEPT; +#else +static const int all_exceptions = FE_ALL_EXCEPT; +#endif + +static void +check_result(int line, const char *rm, tocheck_t expected, tocheck_t actual) +{ + if (memcmp(&expected, &actual, sizeof(tocheck_t)) != 0) + { + unsigned char *ex, *ac; + int i; + + printf("%s:%d:round %s:result failed\n" + " expected result 0x", __FILE__, line, rm); + ex = (unsigned char *)&expected; + ac = (unsigned char *)&actual; + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", ex[i]); + printf(" got 0x"); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", ac[i]); + printf("\n"); + nerrors++; + } +} + +static const struct { + int except; + const char *name; +} excepts[] = { +#define except_entry(ex) { ex, #ex } , +#ifdef FE_INEXACT + except_entry(FE_INEXACT) +#else +# define FE_INEXACT 0 +#endif +#ifdef FE_DIVBYZERO + except_entry(FE_DIVBYZERO) +#else +# define FE_DIVBYZERO 0 +#endif +#ifdef FE_UNDERFLOW + except_entry(FE_UNDERFLOW) +#else +# define FE_UNDERFLOW 0 +#endif +#ifdef FE_OVERFLOW + except_entry(FE_OVERFLOW) +#else +# define FE_OVERFLOW 0 +#endif +#ifdef FE_INVALID + except_entry(FE_INVALID) +#else +# define FE_INVALID 0 +#endif +#ifdef FE_INVALID_SNAN + except_entry(FE_INVALID_SNAN) +#else +# define FE_INVALID_SNAN FE_INVALID +#endif +#ifdef FE_INVALID_ISI + except_entry(FE_INVALID_ISI) +#else +# define FE_INVALID_ISI FE_INVALID +#endif +#ifdef FE_INVALID_IDI + except_entry(FE_INVALID_IDI) +#else +# define FE_INVALID_IDI FE_INVALID +#endif +#ifdef FE_INVALID_ZDZ + except_entry(FE_INVALID_ZDZ) +#else +# define FE_INVALID_ZDZ FE_INVALID +#endif +#ifdef FE_INVALID_COMPARE + except_entry(FE_INVALID_COMPARE) +#else +# define FE_INVALID_COMPARE FE_INVALID +#endif +#ifdef FE_INVALID_SOFTWARE + except_entry(FE_INVALID_SOFTWARE) +#else +# define FE_INVALID_SOFTWARE FE_INVALID +#endif +#ifdef FE_INVALID_SQRT + except_entry(FE_INVALID_SQRT) +#else +# define FE_INVALID_SQRT FE_INVALID +#endif +#ifdef FE_INVALID_INTEGER_CONVERSION + except_entry(FE_INVALID_INTEGER_CONVERSION) +#else +# define FE_INVALID_INTEGER_CONVERSION FE_INVALID +#endif +}; + +static int excepts_missing = 0; + +static void +check_excepts(int line, const char *rm, int expected, int actual) +{ + if (expected & excepts_missing) + expected = expected & ~excepts_missing | FE_INVALID_SNAN; + if ((expected & all_exceptions) != actual) + { + int i; + printf("%s:%d:round %s:exceptions failed\n" + " expected exceptions ", __FILE__, line,rm); + for (i = 0; i < sizeof(excepts)/sizeof(excepts[0]); i++) + if (expected & excepts[i].except) + printf("%s ",excepts[i].name); + if ((expected & all_exceptions) == 0) + printf("- "); + printf("got"); + for (i = 0; i < sizeof(excepts)/sizeof(excepts[0]); i++) + if (actual & excepts[i].except) + printf(" %s",excepts[i].name); + if ((actual & all_exceptions) == 0) + printf("- "); + printf(".\n"); + nerrors++; + } +} + +typedef enum { + B_ADD, B_SUB, B_MUL, B_DIV, B_NEG, B_ABS, B_SQRT +} op_t; +typedef struct { + int line; + op_t op; + int a_sgn; + pattern_t a_exp, a_mant; + int b_sgn; + pattern_t b_exp, b_mant; + int rmode; + int excepts; + int x_sgn; + pattern_t x_exp, x_mant; +} optest_t; +static const optest_t optests[] = { + /* Additions of zero. */ + {__LINE__,B_ADD, 0,P_Z,P_Z, 0,P_Z,P_Z, R_ALL,0, 0,P_Z,P_Z }, + {__LINE__,B_ADD, 1,P_Z,P_Z, 0,P_Z,P_Z, R_ALL & ~R_DOWN,0, 0,P_Z,P_Z }, + {__LINE__,B_ADD, 1,P_Z,P_Z, 0,P_Z,P_Z, R_DOWN,0, 1,P_Z,P_Z }, + {__LINE__,B_ADD, 1,P_Z,P_Z, 1,P_Z,P_Z, R_ALL,0, 1,P_Z,P_Z }, + + /* Additions with NaN. */ + {__LINE__,B_ADD, 0,P_O,P_101Z, 0,P_Z,P_Z, R_ALL,0, 0,P_O,P_101Z }, + {__LINE__,B_ADD, 0,P_O,P_01Z, 0,P_Z,P_Z, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_11Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_O,P_0O, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_O }, + {__LINE__,B_ADD, 0,P_Z,P_Z, 0,P_O,P_11Z, R_ALL,0, 0,P_O,P_11Z }, + {__LINE__,B_ADD, 0,P_O,P_001Z, 0,P_O,P_001Z, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_101Z }, + {__LINE__,B_ADD, 0,P_O,P_1Z, 0,P_Z,P_Z, R_ALL,0, 0,P_O,P_1Z }, + {__LINE__,B_ADD, 0,P_0O,P_Z, 0,P_O,P_10O, R_ALL,0, 0,P_O,P_10O }, + + /* Additions with infinity. */ + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_Z,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 1,P_Z,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 0,P_Z,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 1,P_Z,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_O,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 1,P_O,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 1,P_O,P_Z, R_ALL, + FE_INVALID | FE_INVALID_ISI, 0,P_O,P_1Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 0,P_O,P_Z, R_ALL, + FE_INVALID | FE_INVALID_ISI, 0,P_O,P_1Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 0,P_0O,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 0,P_0O,P_Z, R_ALL,0, 1,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O,P_Z, 1,P_0O,P_Z, R_ALL,0, 0,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O,P_Z, 1,P_0O,P_Z, R_ALL,0, 1,P_O,P_Z }, + + /* Overflow (and zero). */ + {__LINE__,B_ADD, 0,P_O0,P_Z, 0,P_O0,P_Z, R_NEAREST | R_UP, + FE_INEXACT | FE_OVERFLOW, 0,P_O,P_Z }, + {__LINE__,B_ADD, 0,P_O0,P_Z, 0,P_O0,P_Z, R_ZERO | R_DOWN, + FE_INEXACT | FE_OVERFLOW, 0,P_O0,P_O }, + {__LINE__,B_ADD, 1,P_O0,P_Z, 1,P_O0,P_Z, R_NEAREST | R_DOWN, + FE_INEXACT | FE_OVERFLOW, 1,P_O,P_Z }, + {__LINE__,B_ADD, 1,P_O0,P_Z, 1,P_O0,P_Z, R_ZERO | R_UP, + FE_INEXACT | FE_OVERFLOW, 1,P_O0,P_O }, + {__LINE__,B_ADD, 0,P_O0,P_Z, 1,P_O0,P_Z, R_ALL & ~R_DOWN, + 0, 0,P_Z,P_Z }, + {__LINE__,B_ADD, 0,P_O0,P_Z, 1,P_O0,P_Z, R_DOWN, + 0, 1,P_Z,P_Z }, + + /* Negation. */ + {__LINE__,B_NEG, 0,P_Z,P_Z, 0,0,0, R_ALL, 0, 1,P_Z,P_Z }, + {__LINE__,B_NEG, 1,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_NEG, 0,P_O,P_Z, 0,0,0, R_ALL, 0, 1,P_O,P_Z }, + {__LINE__,B_NEG, 1,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_NEG, 0,P_O,P_1Z, 0,0,0, R_ALL, 0, 1,P_O,P_1Z }, + {__LINE__,B_NEG, 1,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_NEG, 0,P_O,P_01Z, 0,0,0, R_ALL, 0, 1,P_O,P_01Z }, + {__LINE__,B_NEG, 1,P_O,P_01Z, 0,0,0, R_ALL, 0, 0,P_O,P_01Z }, + {__LINE__,B_NEG, 0,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 1,P_1Z,P_1Z1 }, + {__LINE__,B_NEG, 1,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 0,P_1Z,P_1Z1 }, + {__LINE__,B_NEG, 0,P_Z,P_Z1, 0,0,0, R_ALL, 0, 1,P_Z,P_Z1 }, + {__LINE__,B_NEG, 1,P_Z,P_Z1, 0,0,0, R_ALL, 0, 0,P_Z,P_Z1 }, + + /* Absolute value. */ + {__LINE__,B_ABS, 0,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_ABS, 1,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_ABS, 0,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_ABS, 1,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_ABS, 0,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_ABS, 1,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_ABS, 0,P_O,P_01Z, 0,0,0, R_ALL, 0, 0,P_O,P_01Z }, + {__LINE__,B_ABS, 1,P_O,P_01Z, 0,0,0, R_ALL, 0, 0,P_O,P_01Z }, + {__LINE__,B_ABS, 0,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 0,P_1Z,P_1Z1 }, + {__LINE__,B_ABS, 1,P_1Z,P_1Z1, 0,0,0, R_ALL, 0, 0,P_1Z,P_1Z1 }, + {__LINE__,B_ABS, 0,P_Z,P_Z1, 0,0,0, R_ALL, 0, 0,P_Z,P_Z1 }, + {__LINE__,B_ABS, 1,P_Z,P_Z1, 0,0,0, R_ALL, 0, 0,P_Z,P_Z1 }, + + /* Square root. */ + {__LINE__,B_SQRT, 0,P_Z,P_Z, 0,0,0, R_ALL, 0, 0,P_Z,P_Z }, + {__LINE__,B_SQRT, 1,P_Z,P_Z, 0,0,0, R_ALL, 0, 1,P_Z,P_Z }, + {__LINE__,B_SQRT, 0,P_O,P_1Z, 0,0,0, R_ALL, 0, 0,P_O,P_1Z }, + {__LINE__,B_SQRT, 1,P_O,P_1Z, 0,0,0, R_ALL, 0, 1,P_O,P_1Z }, + {__LINE__,B_SQRT, 0,P_O,P_01Z, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 0,P_O,P_11Z }, + {__LINE__,B_SQRT, 1,P_O,P_01Z, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SNAN, 1,P_O,P_11Z }, + + {__LINE__,B_SQRT, 0,P_O,P_Z, 0,0,0, R_ALL, 0, 0,P_O,P_Z }, + {__LINE__,B_SQRT, 0,P_0O,P_Z, 0,0,0, R_ALL, 0, 0,P_0O,P_Z }, + + {__LINE__,B_SQRT, 1,P_O,P_Z, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SQRT, 0,P_O,P_1Z }, + {__LINE__,B_SQRT, 1,P_1Z,P_1Z1, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SQRT, 0,P_O,P_1Z }, + {__LINE__,B_SQRT, 1,P_Z,P_Z1, 0,0,0, R_ALL, + FE_INVALID | FE_INVALID_SQRT, 0,P_O,P_1Z }, + +}; + +static void +check_op(void) +{ + int i, j; + tocheck_t r, a, b, x; + int raised; + + for (i = 0; i < sizeof(optests)/sizeof(optests[0]); i++) + { + a = pattern(optests[i].a_sgn, optests[i].a_exp, + optests[i].a_mant); + b = pattern(optests[i].b_sgn, optests[i].b_exp, + optests[i].b_mant); + x = pattern(optests[i].x_sgn, optests[i].x_exp, + optests[i].x_mant); + for (j = 0; j < 4; j++) + if (optests[i].rmode & 1<<j) + { + fesetenv(rmodes+j); + switch (optests[i].op) + { + case B_ADD: r = a + b; break; + case B_SUB: r = a - b; break; + case B_MUL: r = a * b; break; + case B_DIV: r = a / b; break; + case B_NEG: r = -a; break; + case B_ABS: r = FUNC(fabs)(a); break; + case B_SQRT: r = FUNC(sqrt)(a); break; + } + raised = fetestexcept(all_exceptions); + check_result(optests[i].line,rmnames[j],x,r); + check_excepts(optests[i].line,rmnames[j], + optests[i].excepts,raised); + } + } +} + +static void +fail_xr(int line, const char *rm, tocheck_t x, tocheck_t r, tocheck_t xx, + int xflag) +{ + int i; + unsigned char *cx, *cr, *cxx; + + printf("%s:%d:round %s:fail\n with x=0x", __FILE__, line,rm); + cx = (unsigned char *)&x; + cr = (unsigned char *)&r; + cxx = (unsigned char *)&xx; + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", cx[i]); + printf(" r=0x"); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", cr[i]); + printf(" xx=0x"); + for (i = 0; i < sizeof(tocheck_t); i++) + printf("%02x", cxx[i]); + printf(" inexact=%d\n", xflag != 0); + nerrors++; +} + +static void +check_sqrt(tocheck_t a) +{ + int j; + tocheck_t r0, r1, r2, x0, x1, x2; + int raised = 0; + int ok; + + for (j = 0; j < 4; j++) + { + int excepts; + + fesetenv(rmodes+j); + r1 = FUNC(sqrt)(a); + excepts = fetestexcept(all_exceptions); + fesetenv(FE_DFL_ENV); + raised |= excepts & ~FE_INEXACT; + x1 = r1 * r1 - a; + if (excepts & FE_INEXACT) + { + r0 = delta(r1,-1); r2 = delta(r1,1); + switch (1 << j) + { + case R_NEAREST: + x0 = r0 * r0 - a; x2 = r2 * r2 - a; + ok = fabs(x0) >= fabs(x1) && fabs(x1) <= fabs(x2); + break; + case R_ZERO: case R_DOWN: + x2 = r2 * r2 - a; + ok = x1 <= 0 && x2 >= 0; + break; + case R_UP: + x0 = r0 * r0 - a; + ok = x1 >= 0 && x0 <= 0; + break; + default: + assert(0); + } + } + else + ok = x1 == 0; + if (!ok) + fail_xr(__LINE__,rmnames[j],a,r1,x1,excepts&FE_INEXACT); + } + check_excepts(__LINE__,"all",0,raised); +} + +int main(int argc, char **argv) +{ + int i; + + _LIB_VERSION = _IEEE_; + + /* Set up environments for rounding modes. */ + fesetenv(FE_DFL_ENV); + fesetround(FE_TONEAREST); + fegetenv(rmodes+0); + fesetround(FE_TOWARDSZERO); + fegetenv(rmodes+1); + fesetround(FE_UPWARD); + fegetenv(rmodes+2); + fesetround(FE_DOWNWARD); + fegetenv(rmodes+3); + +#if defined(FE_INVALID_SOFTWARE) || defined(FE_INVALID_SQRT) + /* There's this really stupid feature of the 601... */ + fesetenv(FE_DFL_ENV); + feraiseexcept(FE_INVALID_SOFTWARE); + if (!fetestexcept(FE_INVALID_SOFTWARE)) + excepts_missing |= FE_INVALID_SOFTWARE; + fesetenv(FE_DFL_ENV); + feraiseexcept(FE_INVALID_SQRT); + if (!fetestexcept(FE_INVALID_SQRT)) + excepts_missing |= FE_INVALID_SQRT; +#endif + + check_op(); + for (i = 0; i < 100000; i++) + check_sqrt(pattern(0, P_Rno, P_R)); + for (i = 0; i < 100; i++) + check_sqrt(pattern(0, P_Z, P_R)); + check_sqrt(pattern(0,P_Z,P_Z1)); + + printf("%d errors.\n", nerrors); + return nerrors == 0 ? 0 : 1; +} diff --git a/sysdeps/powerpc/test-arithf.c b/sysdeps/powerpc/test-arithf.c new file mode 100644 index 0000000000..d78ec49009 --- /dev/null +++ b/sysdeps/powerpc/test-arithf.c @@ -0,0 +1,6 @@ +typedef float tocheck_t; +#define ESIZE 8 +#define MSIZE 23 +#define FUNC(x) x##f + +#include "test-arith.c" diff --git a/sysdeps/sparc/Dist b/sysdeps/sparc/Dist index 8bd3729740..6c3b23baa5 100644 --- a/sysdeps/sparc/Dist +++ b/sysdeps/sparc/Dist @@ -1,3 +1,4 @@ dotmul.S umul.S divrem.m4 sdiv.S udiv.S rem.S urem.S alloca.S +sys/trap.h diff --git a/sysdeps/sparc64/elf/Dist b/sysdeps/sparc64/elf/Dist new file mode 100644 index 0000000000..d9338c8fd6 --- /dev/null +++ b/sysdeps/sparc64/elf/Dist @@ -0,0 +1,4 @@ +crtbegin.S +crtbeginS.S +crtend.S +crtendS.S diff --git a/sysdeps/standalone/arm/bits/errno.h b/sysdeps/standalone/arm/bits/errno.h index 362b43dacf..f5020dcb7e 100644 --- a/sysdeps/standalone/arm/bits/errno.h +++ b/sysdeps/standalone/arm/bits/errno.h @@ -38,17 +38,19 @@ # define EMFILE 10 # define ENAMETOOLONG 11 /* File name too long */ # define ELOOP 12 /* Too many symbolic links encountered */ -# define ENOMSG 13 /* No message of desired type */ +# define ENOMSG 13 /* No message of desired type */ # define E2BIG 14 /* Arg list too long */ # define EINTR 15 # define EILSEQ 16 -# define ENOEXEC 17 +# define ENOEXEC 17 # define ENOENT 18 # define EPROTOTYPE 19 # define ESRCH 20 # define EPERM 21 -# define ENOTDIR 22 -# define ESTALE 23 +# define ENOTDIR 22 +# define ESTALE 23 +# define EISDIR 24 +# define EOPNOTSUPP 25 /* Operation not supported. */ #endif #define __set_errno(val) errno = (val) diff --git a/sysdeps/stub/bits/libc-lock.h b/sysdeps/stub/bits/libc-lock.h index 9efd799dab..c24dcd047a 100644 --- a/sysdeps/stub/bits/libc-lock.h +++ b/sysdeps/stub/bits/libc-lock.h @@ -72,7 +72,7 @@ /* Define once control variable. */ -#define __libc_once_define(NAME) int NAME = 0 +#define __libc_once_define(CLASS, NAME) CLASS int NAME = 0 /* Call handler iff the first call. */ #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ diff --git a/sysdeps/stub/connect.c b/sysdeps/stub/connect.c index 7fbbc7fa31..9152a9449c 100644 --- a/sysdeps/stub/connect.c +++ b/sysdeps/stub/connect.c @@ -24,7 +24,7 @@ and the only address from which to accept transmissions. Return 0 on success, -1 for errors. */ int -connect (fd, addr, len) +__connect (fd, addr, len) int fd; __CONST_SOCKADDR_ARG addr; size_t len; @@ -32,6 +32,7 @@ connect (fd, addr, len) __set_errno (ENOSYS); return -1; } +weak_alias (__connect, connect) stub_warning (connect) diff --git a/sysdeps/stub/init-first.c b/sysdeps/stub/init-first.c index 5e2cd121f1..4fcc67ddbe 100644 --- a/sysdeps/stub/init-first.c +++ b/sysdeps/stub/init-first.c @@ -1,5 +1,5 @@ /* Initialization code run first thing by the ELF startup code. Stub version. - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,12 +18,15 @@ Boston, MA 02111-1307, USA. */ #include <unistd.h> +#include <sys/types.h> int __libc_multiple_libcs = 1; extern void __libc_init (int, char **, char **); extern void __getopt_clean_environment (void); +pid_t __libc_pid; + #ifdef PIC void __libc_init_first (void) diff --git a/sysdeps/stub/s_exp2f.c b/sysdeps/stub/s_exp2f.c index 51b268c9e0..f763efbe69 100644 --- a/sysdeps/stub/s_exp2f.c +++ b/sysdeps/stub/s_exp2f.c @@ -11,4 +11,4 @@ __exp2f (float x) } weak_alias (__exp2f, exp2f) -stub_warning (exp2) +stub_warning (exp2f) diff --git a/sysdeps/stub/send.c b/sysdeps/stub/send.c index 262818e8a9..a25eb72822 100644 --- a/sysdeps/stub/send.c +++ b/sysdeps/stub/send.c @@ -21,7 +21,7 @@ /* Send N bytes of BUF to socket FD. Returns the number sent or -1. */ int -send (fd, buf, n, flags) +__send (fd, buf, n, flags) int fd; __const __ptr_t buf; size_t n; @@ -30,6 +30,7 @@ send (fd, buf, n, flags) __set_errno (ENOSYS); return -1; } +weak_alias (__send, send) stub_warning (send) diff --git a/sysdeps/stub/statfs.c b/sysdeps/stub/statfs.c index df13f73c57..bae8eaa8ee 100644 --- a/sysdeps/stub/statfs.c +++ b/sysdeps/stub/statfs.c @@ -28,6 +28,6 @@ __statfs (const char *file, struct statfs *buf) __set_errno (ENOSYS); return -1; } -stub_warning (statfs) - weak_alias (__statfs, statfs) + +stub_warning (statfs) diff --git a/sysdeps/unix/Subdirs b/sysdeps/unix/Subdirs new file mode 100644 index 0000000000..a46884d4f8 --- /dev/null +++ b/sysdeps/unix/Subdirs @@ -0,0 +1 @@ +login diff --git a/sysdeps/unix/bsd/osf/sys/mman.h b/sysdeps/unix/bsd/osf/sys/mman.h index 72846195d2..816f271e30 100644 --- a/sysdeps/unix/bsd/osf/sys/mman.h +++ b/sysdeps/unix/bsd/osf/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. OSF/1 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -32,46 +32,53 @@ without PROT_READ. The only guarantees are that no writing will be allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ -#define PROT_NONE 0x00 /* No access. */ -#define PROT_READ 0x01 /* Pages can be read. */ -#define PROT_WRITE 0x02 /* Pages can be written. */ -#define PROT_EXEC 0x04 /* Pages can be executed. */ +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x01 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x04 /* Pages can be executed. */ /* Flags contain mapping type, sharing type and options. */ /* Mapping type (must choose one and only one of these). */ -#define MAP_FILE 0x00 /* Mapped from a file or device. */ -#define MAP_ANON 0x10 /* Allocated from anonymous virtual memory. */ -#define MAP_ANONYMOUS MAP_ANON -#define MAP_TYPE 0xf0 /* Mask for type field. */ +#ifdef __USE_BSD +# define MAP_FILE 0x00 /* Mapped from a file or device. */ +# define MAP_ANON 0x10 /* Allocated from anonymous virtual memory. */ +# define MAP_ANONYMOUS MAP_ANON +# define MAP_TYPE 0xf0 /* Mask for type field. */ +#endif /* Sharing types (must choose one and only one of these). */ -#define MAP_SHARED 0x01 /* Share changes. */ -#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ /* Other flags. */ -#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ -#define MAP_VARIABLE 0 /* Absence of MAP_FIXED. */ -#define MAP_HASSEMPHORE 0x0200 /* Region may contain semaphores. */ -#define MAP_INHERIT 0x0400 /* Region is retained after exec. */ -#define MAP_UNALIGNED 0x0800 /* File offset need not be page-aligned. */ +#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */ +#ifdef __USE_BSD +# define MAP_VARIABLE 0 /* Absence of MAP_FIXED. */ +# define MAP_HASSEMPHORE 0x0200 /* Region may contain semaphores. */ +# define MAP_INHERIT 0x0400 /* Region is retained after exec. */ +# define MAP_UNALIGNED 0x0800 /* File offset need not be page-aligned. */ +#endif /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ -#define MADV_SPACEAVAIL 5 /* Ensure that resources are available. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_SPACEAVAIL 5 /* Ensure that resources are available. */ +#endif /* Flags to `msync'. */ #define MS_ASYNC 1 /* Asynchronous cache flush. */ #define MS_SYNC 3 /* Synchronous cache flush. */ #define MS_INVALIDATE 4 /* Invalidate cached pages. */ +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -79,34 +86,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/bsd/sun/sunos4/sys/mman.h b/sysdeps/unix/bsd/sun/sunos4/sys/mman.h index 65771a2aac..d2a8998d9a 100644 --- a/sysdeps/unix/bsd/sun/sunos4/sys/mman.h +++ b/sysdeps/unix/bsd/sun/sunos4/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. SunOS 4 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -41,14 +41,18 @@ /* Sharing types (must choose one and only one of these). */ #define MAP_SHARED 0x01 /* Share changes. */ #define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ -#define MAP_TYPE 0x0f /* Mask for sharing type. */ +#ifdef __USE_BSD +# define MAP_TYPE 0x0f /* Mask for sharing type. */ +#endif /* Other flags. */ #define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ /* The following three flags are not actually implemented in SunOS 4.1. */ -#define MAP_RENAME 0x20 /* Rename private pages to file. */ -#define MAP_NORESERVE 0x40 /* Don't reserve needed swap area. */ -#define MAP_INHERIT 0x80 /* Region is retained after exec. */ +#ifdef __USE_BSD +# define MAP_RENAME 0x20 /* Rename private pages to file. */ +# define MAP_NORESERVE 0x40 /* Don't reserve needed swap area. */ +# define MAP_INHERIT 0x80 /* Region is retained after exec. */ +#endif /* This is an internal flag that is always set in `mmap' system calls. In older versions of SunOS 4 `mmap' did not return the actual mapping @@ -57,18 +61,21 @@ #define _MAP_NEW 0x80000000 /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif /* Flags to `msync'. */ #define MS_ASYNC 0x1 /* Return immediately, don't fsync. */ #define MS_INVALIDATE 0x2 /* Invalidate caches. */ +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -76,34 +83,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/bsd/ultrix4/sys/mman.h b/sysdeps/unix/bsd/ultrix4/sys/mman.h index 989bf21754..4262fce438 100644 --- a/sysdeps/unix/bsd/ultrix4/sys/mman.h +++ b/sysdeps/unix/bsd/ultrix4/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. Ultrix 4 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -41,20 +41,25 @@ /* Sharing types (must choose one and only one of these). */ #define MAP_SHARED 0x01 /* Share changes. */ #define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ -#define MAP_TYPE 0x0f /* Mask for sharing type. */ +#ifdef __USE_BSD +# define MAP_TYPE 0x0f /* Mask for sharing type. */ +#endif /* Other flags. */ #define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -62,36 +67,38 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Ultrix 4 does not implement `msync' or `madvise'. */ /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((caddr_t __addr, size_t __len)); +extern int msync __P ((caddr_t __addr, size_t __len)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/sysv/irix4/sys/mman.h b/sysdeps/unix/sysv/irix4/sys/mman.h index f42a9f67aa..c3a923832a 100644 --- a/sysdeps/unix/sysv/irix4/sys/mman.h +++ b/sysdeps/unix/sysv/irix4/sys/mman.h @@ -1,5 +1,5 @@ /* Definitions for BSD-style memory management. Irix 4 version. - Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -23,8 +23,6 @@ #include <features.h> #include <bits/types.h> -#define __need_size_t -#include <stddef.h> /* Protections are chosen from these bits, OR'd together. The @@ -32,37 +30,46 @@ without PROT_READ. The only guarantees are that no writing will be allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ -#define PROT_NONE 0x00 /* No access. */ -#define PROT_READ 0x04 /* Pages can be read. */ -#define PROT_WRITE 0x02 /* Pages can be written. */ -#define PROT_EXEC 0x01 /* Pages can be executed. */ -#define PROT_EXECUTE PROT_EXEC +#define PROT_NONE 0x00 /* No access. */ +#define PROT_READ 0x04 /* Pages can be read. */ +#define PROT_WRITE 0x02 /* Pages can be written. */ +#define PROT_EXEC 0x01 /* Pages can be executed. */ +#ifdef __USE_MISC +# define PROT_EXECUTE PROT_EXEC +#endif /* Sharing types (must choose one and only one of these). */ -#define MAP_SHARED 0x01 /* Share changes. */ -#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ -#define MAP_TYPE 0x0f /* Mask for sharing type. */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes private; copy pages on write. */ +#ifdef __USE_BSD +# define MAP_TYPE 0x0f /* Mask for sharing type. */ +#endif /* Other flags. */ -#define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ -#define MAP_RENAME 0x20 /* Rename private pages to file. */ -#define MAP_AUTOGROW 0x40 /* Grow file as pages are written. */ -#define MAP_LOCAL 0x80 /* Copy the mapped region on fork. */ +#define MAP_FIXED 0x10 /* Map address must be exactly as requested. */ +#ifdef __USE_MISC +# define MAP_RENAME 0x20 /* Rename private pages to file. */ +# define MAP_AUTOGROW 0x40 /* Grow file as pages are written. */ +# define MAP_LOCAL 0x80 /* Copy the mapped region on fork. */ +#endif /* Advice to `madvise'. */ -#define MADV_NORMAL 0 /* No further special treatment. */ -#define MADV_RANDOM 1 /* Expect random page references. */ -#define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ -#define MADV_WILLNEED 3 /* Will need these pages. */ -#define MADV_DONTNEED 4 /* Don't need these pages. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +#endif /* Flags to `msync'. */ -#define MS_ASYNC 0x1 /* Return immediately, don't fsync. */ -#define MS_INVALIDATE 0x2 /* Invalidate caches. */ +#define MS_ASYNC 0x1 /* Return immediately, don't fsync. */ +#define MS_INVALIDATE 0x2 /* Invalidate caches. */ +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) -#include <sys/cdefs.h> __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -70,34 +77,36 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ -__caddr_t __mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); -__caddr_t mmap __P ((__caddr_t __addr, size_t __len, - int __prot, int __flags, int __fd, __off_t __offset)); +extern __caddr_t __mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); +extern __caddr_t mmap __P ((__caddr_t __addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset)); /* Deallocate any mapping for the region starting at ADDR and extending LEN bytes. Returns 0 if successful, -1 for errors (and sets errno). */ -int __munmap __P ((__caddr_t __addr, size_t __len)); -int munmap __P ((__caddr_t __addr, size_t __len)); +extern int __munmap __P ((__caddr_t __addr, size_t __len)); +extern int munmap __P ((__caddr_t __addr, size_t __len)); /* Change the memory protection of the region starting at ADDR and extending LEN bytes to PROT. Returns 0 if successful, -1 for errors (and sets errno). */ -int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); -int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int __mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); +extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); /* Synchronize the region starting at ADDR and extending LEN bytes with the file it maps. Filesystem operations on a file being mapped are unpredictable before this is done. */ -int msync __P ((caddr_t __addr, size_t __len, int __flags)); +extern int msync __P ((caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ -int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif __END_DECLS diff --git a/sysdeps/unix/sysv/linux/alpha/Dist b/sysdeps/unix/sysv/linux/alpha/Dist index 1b1f771853..ae71c2feb3 100644 --- a/sysdeps/unix/sysv/linux/alpha/Dist +++ b/sysdeps/unix/sysv/linux/alpha/Dist @@ -1,11 +1,14 @@ -alpha/ptrace.h alpha/regdef.h -ieee_get_fp_control.S ieee_set_fp_control.S -ioperm.c -init-first.h +alpha/ptrace.h +alpha/regdef.h +bits/mman.h clone.S +ieee_get_fp_control.S +ieee_set_fp_control.S +init-first.h +ioperm.c kernel_sigaction.h kernel_stat.h kernel_termios.h -sys/io.h sys/acct.h +sys/io.h sys/procfs.h diff --git a/sysdeps/unix/sysv/linux/alpha/bits/mman.h b/sysdeps/unix/sysv/linux/alpha/bits/mman.h new file mode 100644 index 0000000000..1bef0cb525 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/bits/mman.h @@ -0,0 +1,83 @@ +/* Definitions for POSIX memory map inerface. Linux/Alpha version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x100 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x10 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* Not used by Linux, but here to make sure we don't clash with OSF/1 + defines. */ +#ifdef __USE_BSD +# define MAP_HASSEMAPHORE 0x0200 +# define MAP_INHERIT 0x0400 +# define MAP_UNALIGNED 0x0800 +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x1000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x8000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x10000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 2 /* Synchronous memory sync. */ +#define MS_INVALIDATE 4 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 8192 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 16384 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h index fd13e124a8..2a8d6ed004 100644 --- a/sysdeps/unix/sysv/linux/bits/socket.h +++ b/sysdeps/unix/sysv/linux/bits/socket.h @@ -136,7 +136,7 @@ struct msghdr socklen_t msg_namelen; /* Length of address data. */ struct iovec *msg_iov; /* Vector of data to send/receive into. */ - size_t msg_iovlen; /* Number of elements in the vector. */ + int msg_iovlen; /* Number of elements in the vector. */ __ptr_t msg_control; /* Ancillary data (eg BSD filedesc passing). */ socklen_t msg_controllen; /* Ancillary data buffer length. */ diff --git a/sysdeps/unix/sysv/linux/i386/Dist b/sysdeps/unix/sysv/linux/i386/Dist index d5cc620549..d762dc9416 100644 --- a/sysdeps/unix/sysv/linux/i386/Dist +++ b/sysdeps/unix/sysv/linux/i386/Dist @@ -1,2 +1,4 @@ -sys/perm.h sys/vm86.h +bits/mman.h clone.S +sys/perm.h +sys/vm86.h diff --git a/sysdeps/unix/sysv/linux/i386/bits/mman.h b/sysdeps/unix/sysv/linux/i386/bits/mman.h new file mode 100644 index 0000000000..e70b220f9f --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/bits/mman.h @@ -0,0 +1,75 @@ +/* Definitions for POSIX memory map inerface. Linux/i386 version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x2000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x4000 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c index c8eefa9b98..f64fe1e1ca 100644 --- a/sysdeps/unix/sysv/linux/if_index.c +++ b/sysdeps/unix/sysv/linux/if_index.c @@ -182,11 +182,9 @@ if_indextoname (unsigned int ifindex, char *ifname) #else struct if_nameindex *idx = if_nameindex (); struct if_nameindex *p; - char *result; + char *result = NULL; - if (idx == NULL) - result = NULL; - else + if (idx != NULL) { for (p = idx; p->if_index || p->if_name; ++p) if (p->if_index == ifindex) diff --git a/sysdeps/unix/sysv/linux/m68k/Dist b/sysdeps/unix/sysv/linux/m68k/Dist index e7d5949d51..25aa20bcfa 100644 --- a/sysdeps/unix/sysv/linux/m68k/Dist +++ b/sysdeps/unix/sysv/linux/m68k/Dist @@ -1,2 +1,3 @@ +bits/mman.h clone.S mremap.S diff --git a/sysdeps/unix/sysv/linux/mips/Dist b/sysdeps/unix/sysv/linux/mips/Dist index a205c94f95..6be6876fe7 100644 --- a/sysdeps/unix/sysv/linux/mips/Dist +++ b/sysdeps/unix/sysv/linux/mips/Dist @@ -1,3 +1,15 @@ +bits/mman.h clone.S kernel_sigaction.h kernel_stat.h +kernel_termios.h +entry.h +regdef.h +fpregdef.h +sys/acct.h +sys/asm.h +sys/cachectl.h +sys/fpregdef.h +sys/procfs.h +sys/regdef.h +sys/sysmips.h diff --git a/sysdeps/unix/sysv/linux/mips/bits/mman.h b/sysdeps/unix/sysv/linux/mips/bits/mman.h new file mode 100644 index 0000000000..15a343ff76 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/bits/mman.h @@ -0,0 +1,75 @@ +/* Definitions for POSIX memory map inerface. Linux/PowerPC version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/Dist b/sysdeps/unix/sysv/linux/powerpc/Dist index cd6d6d12e5..0213c45f51 100644 --- a/sysdeps/unix/sysv/linux/powerpc/Dist +++ b/sysdeps/unix/sysv/linux/powerpc/Dist @@ -1,3 +1,4 @@ +bits/mman.h clone.S kernel_stat.h kernel_termios.h diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/mman.h b/sysdeps/unix/sysv/linux/powerpc/bits/mman.h new file mode 100644 index 0000000000..da5ad0eb45 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/bits/mman.h @@ -0,0 +1,84 @@ +/* Definitions for POSIX memory map inerface. Linux/MIPS version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x001 /* Share changes. */ +#define MAP_PRIVATE 0x002 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x00f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x010 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x000 +# define MAP_ANONYMOUS 0x800 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* Not used by Linux, but here to make sure we don't clash with ABI + defines. */ +#ifdef __USE_MISC +# define MAP_RENAME 0x020 /* Assign page to file. */ +# define MAP_AUTOGROW 0x040 /* File may grow by writing. */ +# define MAP_LOCAL 0x080 /* Copy on fork/sproc. */ +# define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand. */ +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x1000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x8000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0400 /* Don't check for reservations. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 0 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h index 9a5e830c31..49460661e2 100644 --- a/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h +++ b/sysdeps/unix/sysv/linux/powerpc/kernel_termios.h @@ -18,7 +18,6 @@ #ifndef _KERNEL_TERMIOS_H #define _KERNEL_TERMIOS_H 1 -/* The following corresponds to the values from the Linux 2.0.28 kernel. */ /* We need the definition of tcflag_t, cc_t, and speed_t. */ #include <bits/termios.h> @@ -33,8 +32,8 @@ struct __kernel_termios tcflag_t c_lflag; /* local mode flags */ cc_t c_cc[__KERNEL_NCCS]; /* control characters */ cc_t c_line; /* line discipline */ - int c_ispeed; /* input speed */ - int c_ospeed; /* output speed */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ }; #define _HAVE_C_ISPEED 1 diff --git a/sysdeps/unix/sysv/linux/powerpc/profil-counter.h b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h new file mode 100644 index 0000000000..fed0913574 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/profil-counter.h @@ -0,0 +1,26 @@ +/* Low-level statistical profiling support function. Linux/PowerPC version. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <signal.h> + +void +profil_counter (int signo, struct sigcontext sc) +{ + profil_count ((void *) sc.regs->nip); +} diff --git a/sysdeps/unix/sysv/linux/powerpc/profil.c b/sysdeps/unix/sysv/linux/powerpc/profil.c deleted file mode 100644 index 6ab8065da3..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/profil.c +++ /dev/null @@ -1,2 +0,0 @@ -/* For now. */ -#include <sysdeps/stub/profil.c> diff --git a/sysdeps/unix/sysv/linux/sparc/Dist b/sysdeps/unix/sysv/linux/sparc/Dist index d93c648651..9729f0709b 100644 --- a/sysdeps/unix/sysv/linux/sparc/Dist +++ b/sysdeps/unix/sysv/linux/sparc/Dist @@ -1,7 +1,8 @@ __sigtrampoline.S +bits/mman.h clone.S pipe.S fork.S kernel_stat.h -kernel_sigaction.h init-first.h +sys/trap.h diff --git a/sysdeps/unix/sysv/linux/sparc/bits/mman.h b/sysdeps/unix/sysv/linux/sparc/bits/mman.h new file mode 100644 index 0000000000..3e7f2900fa --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/bits/mman.h @@ -0,0 +1,77 @@ +/* Definitions for POSIX memory map inerface. Linux/SPARC version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x0100 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +# define _MAP_NEW 0x80000000 /* Binary compatibility with SunOS. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/sparc64/Dist b/sysdeps/unix/sysv/linux/sparc64/Dist new file mode 100644 index 0000000000..e770e20eb9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc64/Dist @@ -0,0 +1,7 @@ +bits/mman.h +clone.S +kernel_stat.h +getcontext.S +setcontext.S +ucontext.h +init-first.h diff --git a/sysdeps/unix/sysv/linux/sparc64/bits/mman.h b/sysdeps/unix/sysv/linux/sparc64/bits/mman.h new file mode 100644 index 0000000000..3e7f2900fa --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc64/bits/mman.h @@ -0,0 +1,77 @@ +/* Definitions for POSIX memory map inerface. Linux/SPARC version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never include this file directly. Use <sys/mman.h> instead" +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x0100 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +# define _MAP_NEW 0x80000000 /* Binary compatibility with SunOS. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +#endif diff --git a/sysdeps/unix/sysv/linux/sys/mman.h b/sysdeps/unix/sysv/linux/sys/mman.h index dc9f8f7e48..0f56a70c32 100644 --- a/sysdeps/unix/sysv/linux/sys/mman.h +++ b/sysdeps/unix/sysv/linux/sys/mman.h @@ -23,20 +23,12 @@ #include <features.h> #include <bits/types.h> -#define __need_size_t -#include <stddef.h> - -#include <sys/cdefs.h> /* Get the bit values from the kernel header file. */ -#include <linux/mman.h> +#include <bits/mman.h> -#ifndef MAP_ANON -#define MAP_ANON MAP_ANONYMOUS -#endif -#ifndef MAP_FILE -#define MAP_FILE 0 -#endif +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((__caddr_t) -1) __BEGIN_DECLS /* Map addresses starting near ADDR and extending for LEN bytes. from @@ -44,7 +36,7 @@ __BEGIN_DECLS is nonzero, it is the desired mapping address. If the MAP_FIXED bit is set in FLAGS, the mapping will be at ADDR exactly (which must be page-aligned); otherwise the system chooses a convenient nearby address. - The return value is the actual mapping address chosen or (caddr_t) -1 + The return value is the actual mapping address chosen or MAP_FAILED for errors (in which case `errno' is set). A successful `mmap' call deallocates any previous mapping for the affected region. */ @@ -69,9 +61,11 @@ extern int mprotect __P ((__caddr_t __addr, size_t __len, int __prot)); unpredictable before this is done. Flags are from the MS_* set. */ extern int msync __P ((__caddr_t __addr, size_t __len, int __flags)); +#ifdef __USE_BSD /* Advise the system about particular usage patterns the program follows for the region starting at ADDR and extending LEN bytes. */ extern int madvise __P ((__caddr_t __addr, size_t __len, int __advice)); +#endif /* Cause all currently mapped pages of the process to be memory resident until unlocked by a call to the `munlockall', until the process exits, @@ -89,6 +83,7 @@ extern int mlock __P ((__caddr_t __addr, size_t __len)); /* Unlock whole pages previously mapped by the range [ADDR,ADDR+LEN). */ extern int munlock __P ((__caddr_t __addr, size_t __len)); +#ifdef __USE_MISC /* Remap pages mapped by the range [ADDR,ADDR+OLD_LEN) to new length NEW_LEN. If MAY_MOVE is MREMAP_MAYMOVE the returned address may differ from ADDR. */ @@ -96,6 +91,7 @@ extern __caddr_t __mremap __P ((__caddr_t __addr, size_t __old_len, size_t __new_len, int __may_move)); extern __caddr_t mremap __P ((__caddr_t __addr, size_t __old_len, size_t __new_len, int __may_move)); +#endif __END_DECLS diff --git a/sysdeps/unix/sysv/linux/sys/sysmacros.h b/sysdeps/unix/sysv/linux/sys/sysmacros.h index 85b1b85d2e..5c1e1f7441 100644 --- a/sysdeps/unix/sysv/linux/sys/sysmacros.h +++ b/sysdeps/unix/sysv/linux/sys/sysmacros.h @@ -22,8 +22,8 @@ #define _SYS_SYSMACROS_H 1 /* For compatibility we provide alternative names. */ -#define major(dev) (((dev) >> 8) & 0xff) -#define minor(dev) ((dev) & 0xff) +#define major(dev) ((int)(((dev) >> 8) & 0xff)) +#define minor(dev) ((int)((dev) & 0xff)) #define makedev(major, minor) (((major) << 8) | (minor)) #endif /* _SYS_SYSMACROS_H */ diff --git a/time/tzfile.c b/time/tzfile.c index 88e86e33b1..aeec637b3b 100644 --- a/time/tzfile.c +++ b/time/tzfile.c @@ -43,7 +43,7 @@ struct leap long int change; /* Seconds of correction to apply. */ }; -extern const char * __tzstring (const char *); /* Defined in tzset.c. */ +extern char * __tzstring (const char *); /* Defined in tzset.c. */ static struct ttinfo *find_transition (time_t timer); static void compute_tzname_max (size_t); diff --git a/time/tzset.c b/time/tzset.c index d1c2c091a5..d3625fe9dd 100644 --- a/time/tzset.c +++ b/time/tzset.c @@ -33,7 +33,7 @@ extern int __use_tzfile; extern void __tzfile_read __P ((const char *file)); extern void __tzfile_default __P ((const char *std, const char *dst, long int stdoff, long int dstoff)); -extern const char * __tzstring __P ((const char *string)); +extern char * __tzstring __P ((const char *string)); extern int __tz_compute __P ((time_t timer, const struct tm *tm)); char *__tzname[2] = { (char *) "GMT", (char *) "GMT" }; @@ -76,7 +76,7 @@ static tz_rule tz_rules[2]; static int compute_change __P ((tz_rule *rule, int year)); /* Header for a list of buffers containing time zone strings. */ -struct tzstring_head +struct tzstring_head { struct tzstring_head *next; /* The buffer itself immediately follows the header. @@ -98,7 +98,7 @@ static size_t tzstring_last_buffer_size = sizeof tzstring_list.data; /* Allocate a time zone string with given contents. The string will never be moved or deallocated. However, its contents may be shared with other such strings. */ -const char * +char * __tzstring (string) const char *string; { @@ -109,7 +109,7 @@ __tzstring (string) /* Look through time zone string list for a duplicate of this one. */ for (h = &tzstring_list.head; ; h = h->next) { - for (p = (char *) (h + 1); p[0] | p[1]; p++) + for (p = (char *) (h + 1); p[0] | p[1]; ++p) if (strcmp (p, string) == 0) return p; if (! h->next) @@ -118,7 +118,7 @@ __tzstring (string) /* No duplicate was found. Copy to the end of this buffer if there's room; otherwise, append a large-enough new buffer to the list and use it. */ - p++; + ++p; needed = strlen (string) + 2; /* Need 2 trailing '\0's after last string. */ if ((size_t) ((char *) (h + 1) + tzstring_last_buffer_size - p) < needed) @@ -133,8 +133,7 @@ __tzstring (string) p = (char *) (h + 1); } - strncpy (p, string, needed); - return p; + return strncpy (p, string, needed); } static char *old_tz = NULL; @@ -304,6 +303,18 @@ __tzset_internal (always) if (l < 2 && *tz == ':') ++tz; } + if (*tz == '\0' || (tz[0] == ',' && tz[1] == '\0')) + { + /* There is no rule. See if there is a default rule file. */ + __tzfile_default (tz_rules[0].name, tz_rules[1].name, + tz_rules[0].offset, tz_rules[1].offset); + if (__use_tzfile) + { + free (old_tz); + old_tz = NULL; + return; + } + } } else /* There is no DST. */ @@ -312,19 +323,6 @@ __tzset_internal (always) done_names: free (tzbuf); - if (*tz == '\0' || (tz[0] == ',' && tz[1] == '\0')) - { - /* There is no rule. See if there is a default rule file. */ - __tzfile_default (tz_rules[0].name, tz_rules[1].name, - tz_rules[0].offset, tz_rules[1].offset); - if (__use_tzfile) - { - free (old_tz); - old_tz = NULL; - return; - } - } - /* Figure out the standard <-> DST rules. */ for (whichrule = 0; whichrule < 2; ++whichrule) { |