Compare commits

...

38 commits

Author SHA1 Message Date
Jeff Epler
4f29a48653 rtai_math: finite was defined, not exported 2014-09-19 19:59:56 -05:00
Jeff Epler
ce81999e66 rtai_math: get rid of use of userspace headers in kernel modules 2014-09-19 19:59:50 -05:00
Alec Ari
fa71c0c76d Update README.md
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-09-14 02:53:12 -05:00
Alec Ari
a29b0bee30 Fix 32-bit build
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-09-14 02:52:06 -05:00
Alec Ari
3b1a9dd0f2 Trim configs
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-09-11 23:01:35 -05:00
Alec Ari
08618bbf48 Add big generic kernel configs
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-09-10 23:16:56 -05:00
Alec Ari
c0282fe4ea Optimize FORTIFY_SOURCE
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-28 12:34:32 -05:00
Alec Ari
47a1f7f74b Bump 3.10 kernel support
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-27 13:59:21 -05:00
Alec Ari
2f749c34ce Fix spurious APIC interrupts
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-26 08:41:47 -05:00
Alec Ari
d4cf50bee7 Trim it down
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-26 08:29:44 -05:00
Alec Ari
2df23cc0de Fix latency bug for my board (trivial)
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-26 08:16:07 -05:00
Alec Ari
037c704ccc Remove bits and tbx
Not needed for LinuxCNC

Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-26 07:39:47 -05:00
Alec Ari
783893c929 Remove dead code in xn.h
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-26 07:39:47 -05:00
Alec Ari
2fb9c58762 Remove last bit of RTDM
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-26 07:39:46 -05:00
Alec Ari
3086517cd2 Too old to matter
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-23 12:04:35 -05:00
Alec Ari
d897f9c2d7 Silences some warnings, not sure why
If problems arise I will revert this

Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-23 11:57:53 -05:00
Alec Ari
9839efa96b Force FPU, clean-up FPU headers
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-23 08:06:36 -05:00
Alec Ari
edb6c1a7ce Modify kernel kconfig for ipipe
Fixes kernel panic for timer IO-APIC bug

Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-23 07:43:05 -05:00
Alec Ari
ea85023591 Merge branch 'master' of github.com:NTULINUX/RTAI 2014-08-23 04:18:33 -05:00
Alec Ari
b39e77aaf7 Merge pull request #2 from jepler/remove-nonfree-code-harder
Remove cut & paste copies of non-free code
2014-08-23 08:50:18 -05:00
Jeff Epler
de529b0c0d Remove cut & paste copies of non-free code
.. rather than using this implementation of isinf with dubious
provenance, we can depend on __builtin_isinf, which compiles to
an inline instruction sequence on i386, x86_64, and armhf.
2014-08-23 08:40:11 -05:00
Alec Ari
26da62c969 Re-work RTDM includes
Remove RTDM as well

Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-23 04:17:44 -05:00
Alec Ari
5c10841066 Whitespace fixes
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 21:02:41 -05:00
Alec Ari
b01be3d331 Clean up math, force IEEE
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 20:24:32 -05:00
Alec Ari
e2bb11fcf5 Mention SSE2 as requirement
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 18:00:29 -05:00
Alec Ari
c98c84fe9b Modify my own license
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 17:46:40 -05:00
Alec Ari
d2deb6292b Merge branch 'remove-nonfree-code' of github.com:jepler/RTAI
Signed-off-by: Alec Ari <neotheuser@ymail.com>

Conflicts:
	base/math/GNUmakefile.am
2014-08-22 17:44:06 -05:00
Alec Ari
550aeaed4b More clean-up, rework more defaults
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:43:27 -05:00
Alec Ari
96857bcbae Add m4 dir
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:24:44 -05:00
Alec Ari
7960e1643b Add m4 dir to .gitignore
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:16:21 -05:00
Alec Ari
3e171e8003 Remove m4 files in dir
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:13:32 -05:00
Alec Ari
0adf90be69 Also remove rtai_config* upon distclean
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:11:43 -05:00
Alec Ari
3e16737bf2 Remove GNUmakefile.in upon distclean
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:06:25 -05:00
Alec Ari
42ab605bfa Minor cleanup
Fixes distclean and forces MATH and C99

Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 05:02:39 -05:00
Alec Ari
24815b03e9 Remove redundant CFLAGS
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 04:41:16 -05:00
Alec Ari
659fd69c1b Rework Kconfig defaults
Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-22 04:40:37 -05:00
Alec Ari
fbb1f385cd Add fmix / fmax functions
Required for LinuxCNC on 3.14+

Signed-off-by: Alec Ari <neotheuser@ymail.com>
2014-08-20 07:12:14 -05:00
Jeff Epler
04c0b06102 Remove files that do not have a distributable license
These files do not carry a licences that makes them distributable.
However, all of them appear to be either unused or not required by
linuxcnc, based on my analysis at
    http://mid.gmane.org/20131101024943.GA31516%40unpythonic.net
2014-08-20 07:04:33 -05:00
232 changed files with 11304 additions and 29457 deletions

1
.gitignore vendored
View file

@ -25,6 +25,7 @@ configure
aclocal.m4 aclocal.m4
ltversion.m4 ltversion.m4
bin/ bin/
m4/*
doc/guide/*.html doc/guide/*.html
addons/drivers/16550A/FORCE addons/drivers/16550A/FORCE

View file

@ -1,12 +1,6 @@
OPTDIRS = SUBDIRS = base
OPTDIRS += addons DIST_SUBDIRS = base
SUBDIRS = base $(OPTDIRS)
DIST_SUBDIRS = \
base \
addons
EXTRA_DIST = \ EXTRA_DIST = \
README.INSTALL \ README.INSTALL \
@ -76,7 +70,8 @@ clean-local:
distclean-local: distclean-local:
$(MAKE) -C $(srcdir)/base/config/kconfig \ $(MAKE) -C $(srcdir)/base/config/kconfig \
-f Makefile.kconfig distclean srctree=$(srcdir) -f Makefile.kconfig distclean srctree=$(srcdir)
find . -name autom4te.cache | xargs rm -fr find . -name GNUmakefile.in | xargs rm -fr
rm -rf rtai_config* autom4te.cache
else else
clean-local: clean-local:
rm -f .cfchanged rm -f .cfchanged
@ -98,9 +93,7 @@ install-exec-local: devices
dist-hook: dist-hook:
$(MAKE) -C $(distdir)/base/config/kconfig \ $(MAKE) -C $(distdir)/base/config/kconfig \
-f Makefile.kconfig distclean srctree=$(distdir) -f Makefile.kconfig distclean srctree=$(srcdir)
rm -fr `find $(distdir) -name CVS`
test -e $(srcdir)/doc || rm -fr $(distdir)/doc
dev devices: dev devices:
@if test -r $(DESTDIR)/etc/udev/udev.rules ; then \ @if test -r $(DESTDIR)/etc/udev/udev.rules ; then \

View file

@ -1,333 +1,39 @@
Installing RTAI-3.x === Installing RTAI ===
===================
0. RTAI 3.6 Commands marked with # specify root, commands marked with $ are user commands.
================================
RTAI uses only the leanest and fastest RTAI+Linux combination now, i.e. it 1.) Download the RTAI source
dispatches real time interrupts immediately. Moreover within such a scheme
i386 has the possibility of completely avoiding the dispatching of critical
internal timers and interprocessor scheduling interrupts by vectoring them
directly to their handlers. Such an option strongly enhances performances
on low end machines and comes by default. You can disable it while configuring
RTAI though. See the related configuration helper.
What above requires you to patch Linux just with patches found wihin this
distribution.
Notice also that this release is for use with:
- i386,
- x86_64,
- PPC.
On recent distributions, managing udev/sysfs, devices created by following $ cd ~/ && git clone https://github.com/NTULINUX/RTAI.git
this installation procedure will disappear at each machine halting. Then they $ sudo cp -v base/arch/x86/patches/hal-linux-3.14.17-x86-1.patch /usr/src/
will be available nomore at the next reboot. RTAI should manage udev/sysfs
support but in case something weird will impede it you can solve your problem
quickly by restoring RTAI devices before running your application. For that
the following short script containing:
------------------------------ cut here -------------------------------------
if test \! -c /dev/rtai_shm; then
mknod -m 666 /dev/rtai_shm c 10 254
fi
for n in `seq 0 9`; do
f=/dev/rtf$n
if test \! -c $f; then
mknod -m 666 $f c 150 $n
fi
done
------------------------------ cut here -------------------------------------
should suffice.
1. How to build 2.) Patch kernel with IPIPE, in this case we use 3.14.17
===============
1.1 Standard procedure # cd /usr/src
---------------------- # rm -rf linux
# wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.14.17.tar.xz
# cd linux-3.14.17
# patch -p1 < ../hal-linux-3.14.17-x86-1.patch
# make menuconfig
The RTAI build system is a merge of Linux's Kconfig with Configure to your needs
autoconf/automake/libtool. Therefore, you can either build RTAI:
1.1.1 Interactive configuration # make
------------------------------- # make modules_install
1) Into the source tree like with 24.1.x (your_source_dir == 3.) Update grub
your_build_dir). Just run either:
$ make xconfig # (Qt-based) Refer to your distribution documentation to do this
$ make gconfig # (GTK-based)
$ make menuconfig (dialog-based as in 24.1.x)
Save your configuration, wait for the shell prompt to come back after 4.) Compile, configure and install RTAI (MUST BE BOOTED INTO YOUR NEW KERNEL)
the configuration script has fully finished, then run "make".
2) Outside the source tree. From your fresh build directory, $ cd ~/RTAI
either run: $ ./autogen.sh
$ make menuconfig
$ make -f $source_tree/makefile srctree=$source_tree xconfig Configure to your needs
$ make -f $source_tree/makefile srctree=$source_tree gconfig
$ make -f $source_tree/makefile srctree=$source_tree menuconfig
If you are using a version of make >= 3.80, then you can even get rid $ make
of the "srctree=$source_tree" setting. The makefile will infere its $ sudo make install
value properly.
1.1.2 Non-interactive configuration 5.) Go get LinuxCNC and compile that.
-----------------------------------
Since RTAI 3.x has autoconf inside, people needing automatic
non-interactive configuration can directly use the provided GNU
configure script for this purpose. The available configuration
switches can be listed by running ./configure --help. The
RTAI-specific switches are:
--enable-trace Enable trace support
--enable-math Enable math support
--enable-bits Enable bits IPC support
--enable-fifos Enable fifo IPC support
--enable-netrpc Enable netrpc support
--enable-netrpc-rtnet Enable use of RTNet
--enable-sem Enable semaphore support
--enable-msg Enable messaging support
--enable-mbx Enable mailbox support
--enable-tbx Enable typed mailbox support
--enable-mq Enable POSIX-like message queue support
--enable-shm Enable shared memory support
--enable-malloc Enable real-time malloc support
--enable-tasklets Enable tasklets support
--enable-usi Enable user-space interrupt support
--enable-watchdog Enable watchdog support
--enable-leds Enable leds-based debugging support
--enable-sched-lxrt Enable scheduler support without RTAI own ktasks
--enable-ktasks-sched-lxrt Enable scheduler support with RTAI own ktasks
--enable-sched-lock-isr Enable scheduler lock in ISRs
--enable-sched-8254-latency= Set 8254 tuning latency
--enable-sched-apic-latency= Set APIC tuning latency
--enable-sched-lxrt-numslots= Set number of LXRT slots
--enable-cplusplus Build in-kernel C++ support
--enable-comedi-lxrt Enable comedi/LXRT support
--enable-serial Build real-time serial driver
--enable-testsuite Build RTAI testsuite
--enable-rtailab Build RTAI-Lab
--enable-fpu Enable FPU support
--enable-math-c99 Enable math C99 support
--enable-malloc-vmalloc Enable vmalloc support in malloc
--enable-malloc-heap-size Set size of real-time malloc heap
--enable-cpus Enable CPUs
--enable-dox-doc Build Doxygen documentation
--enable-dbx Build Docbook XML documentation.
--enable-dbx-network Try to access Docbook DTD and XSL stylesheets through
network.
--enable-latex-doc Build LaTeX documentation
--enable-verbose-latex Uses LaTeX non-stop mode
--enable-compat Enable compatibility mode
--enable-module-debug Enable debug information in kernel modules
--enable-user-debug Enable debug information in user-space programs
Some configuration targets in base/ can either produce a module,
or be statically linked to the RTAI schedulers. Either pass "m" for
the modular build to their respective --enable-xxx switch, or "y" for
selecting the built-in mode.
1.1.3 Recycling a configuration file
------------------------------------
You can also recycle an existing .rtai_config file from a previous
build by running:
$ cp -rp $old_builddir/.rtai_config \
$new_builddir/.rtai_config
$ cd $new_builddir
$ make -f $source_tree/makefile srctree=$source_tree oldconfig
1.1.4 Selecting alternate compilers
-----------------------------------
Compiler selection must be done at _configuration_ time. One only
needs to pass the right values for the standard environment variables
CC and CXX, respectively for compiling C and C++ source files. In any
case, using a GCC toolchain is mandatory. When unspecified, these
variables's values respectively default to "gcc" and "g++".
WARNING: this selection is not aimed at toggling the cross-compilation
mode on. In order to do so, please refer to 1.2.
Examples:
# Start configuring using the Qt-based GUI with alternate compilers
$ make xconfig CC=/my/favourite/c/compiler CXX=/my/favourite/c++/compiler
# Reconfiguring a previous build tree, changing the compilers on-the-fly.
$ make reconfig CC=/my/favourite/c/compiler CXX=/my/favourite/c++/compiler
# Rebuild all [and optionally install]
$ make [all [install]]
CAVEAT: Since the autoconf-based engine needs to analyze the
compilers's features and crams the CC and CXX values into the
Makefiles it produces, passing CC and CXX variables at build time
simply does _not_ work for the purpose of selecting alternate compiler
toolchains. Again, you need to let the configuration engine know about
these new settings as explained above.
1.2 Installing the software
---------------------------
When the standard (or cross-) compilation has finished:
$ cd $builddir
$ make install
Everything needed to use the RTAI distribution will be copied there
out of the build tree. From now on, you should be able to refer to the
installation directory as the root of a complete standalone binary
RTAI distribution.
One may also choose to install the RTAI programs under a temporary
staging tree by passing the standard DESTDIR variable to "make" while
installing. e.g.
$ make install DESTDIR=/mnt/target
will create a standard RTAI hierarchy under /mnt/target, keeping the
original prefix information unmodified. If the installation directory
selected at configuration time was "/usr/realtime", then the command
above will put the RTAI binary distribution under
/mnt/target/usr/realtime.
WARNING: running "make install" is required to run several standard
RTAI programs correctly. RTAI 3.x enforces the actual split between
the source distribution tree, the build tree where RTAI is going to be
compiled, and the final installation directory where RTAI programs can
be run eventually. In any case, you should only rely on the
installation directory contents to run RTAI programs.
NOTE: Do not pay attention to the "*** Warning" messages appearing on
module compilation output. They are harmless and will be fixed later.
1.3 Compiling parts of the tree
-------------------------------
RTAI developers may want to recompile parts of the tree from times to
times. This automake-based build system allows it: just go to the
proper directory level, then issue "make", as usual. This process will
recurse as needed.
The "makefile" (small caps) found in the root source directory is used
to bootstrap the build system when it is about to be configured for
the first time. After the first configuration has been successful, one
just need to run "make xconfig|gconfig|menuconfig|..." as usual.
1.4 Changing the configuration
------------------------------
Each time you want to change your configuration, just run "make
xconfig|gconfig|menuconfig" in your build dir, then "make" (or "make
all").
If you only want to rerun the "configure" script using the current
RTAI configuration, just run "make reconfig", there is no need to
restart any GUI for that.
When invoked for the first time in an empty build directory, the
default "make" goal is "menuconfig" in a regular terminal, or
"xconfig" in an emacs-term.
1.5 Modifying the autotool template files
-----------------------------------------
If you have to change some template files used by any of the autotools
(i.e. Makefile.am, configure.in, acinclude.m4), then you will need the
following pack to rebuild the derived files:
o autoconf 2.59
o automake 1.9.2
o aclocal 1.9.2
o libtool 1.5.8
1.6 Using the integrated calibration tool
-----------------------------------------
RTAI 3.x comes with a brand new calibration tool which should help you
determining if your hardware platform is up to the hard real-time
duties. You can find this tool under $installdir/calibration. Here is
the output of this tool's help message for x86-based platforms:
$ ./calibration --help
OPTIONS:
-h, --help
print usage
-r, --r8254
calibrate 8254 oneshot programming type
-k, --kernel
oneshot latency calibrated for scheduling kernel space tasks
-u, --user
oneshot latency calibrated for scheduling user space tasks
-p <period (us)>, --period <period (us)>
the period of the underlying hard real time task/intr, default 100 (us)
-t <duration (s)>, --time <duration (s)>
set the duration of the requested calibration, default 5 (s)
-c, --cpufreq
calibrate cpu frequency
-a, --apic
calibrate apic frequency
-b, --both
calibrate both apic and cpu frequency
-i, --interrupt
check worst case interrupt locking/contention on your PC
-s<y/n>, --scope<y/n>
toggle parport bit to monitor scheduling on a scope, default y(es)
2. Bootstrapping with vulcano in 7 steps
========================================
>1. patch and build a vanilla Linux kernel tree with the RTAI support as
usual. Patches for x86 are available from
vulcano/base/arch/i386/patches/. Apply only one of them
that matches the Linux kernel version, like this:
$ cd $linux-src-dir
$ patch -p1 < base/arch/$arch/patches/patchfile
>2. $ mkdir $builddir && cd $builddir
>3. $ make -f ../vulcano/makefile srctree=../vulcano
>4. a GUI should pop up, allowing you to configure RTAI:
o default settings should be ok for most platforms
o in the "General" section, set your site values for the RTAI
installation directory (defaults to /usr/realtime) and
Linux kernel tree (defaults to /usr/src/linux).
o save and exit.
--
At this point, you should see the typical output of a GNU configure
script. Your RTAI settings are being used to setup the
autoconf/automake-based build system.
--
>5. $ make install
RTAI will be compiled then installed under the directory you specified
at configuration time (ensure that your shell can write to the
destination directory).
Remember to add $installdir/bin to your shell PATH variable, where
$installdir is your site value for the RTAI installation directory.
--
>6. $ cd $installdir/testsuite/kern/latency
>7. $ ./run
If "sudo" is installed on your box, the application loader script
(rtai-load) will attempt to use it for running privileged commands
(e.g. insmod, rmmod et al.) If sudo is not available, just "su"
manually before running the run script. You should then see the
typical output of the latency calibration program running in kernel
space. Hit ^C to stop it.
--
<rpm@xenomai.org>
12/5/2004

View file

@ -1 +1,7 @@
RTAI for LinuxCNC RTAI for LinuxCNC
Tested and confirmed working on AMD64 and i686 platforms.
SSE, SSE2, and FPU support required.
For more information, visit https://gcc.gnu.org/wiki/FloatingPointMath

View file

@ -1,5 +0,0 @@
OPTDIRS =
OPTDIRS += rtdm
SUBDIRS = $(OPTDIRS)

View file

@ -1,81 +0,0 @@
moduledir = @RTAI_MODULE_DIR@
includedir = $(prefix)/include/rtdm
modext = @RTAI_MODULE_EXT@
librtdm_a_SOURCES = \
core.c \
device.c \
drvlib.c \
module.c \
proc.c \
rtai_taskq.c \
select.c \
vfile.c
include_HEADERS = \
rtdm.h \
rtdm_driver.h \
rtserial.h \
xn.h \
rtai_taskq.h \
select.h \
vfile.h
if CONFIG_KBUILD
rtai_rtdm$(modext): @RTAI_KBUILD_ENV@
rtai_rtdm$(modext): $(librtdm_a_SOURCES) FORCE
@RTAI_KBUILD_TOP@ \
@RTAI_KBUILD_CMD@ rtai_extradef="@RTAI_KMOD_CFLAGS@" \
@RTAI_KBUILD_BOTTOM@
clean-local:
@RTAI_KBUILD_CLEAN@
rm -f FORCE
distclean-local:
@RTAI_KBUILD_DISTCLEAN@
else
noinst_LIBRARIES = librtdm.a
librtdm_a_AR = ar cru
AM_CPPFLAGS = \
@RTAI_KMOD_CFLAGS@ \
-I$(top_srcdir)/base/include \
-I$(top_srcdir)/addons \
-I../../base/include \
-I../.. \
-I..
rtai_rtdm.o: librtdm.a
$(LD) --whole-archive $< -r -o $@
endif
all-local: rtai_rtdm$(modext)
if CONFIG_RTAI_OLD_FASHIONED_BUILD
$(mkinstalldirs) $(top_srcdir)/modules
$(INSTALL_DATA) $^ $(top_srcdir)/modules
endif
install-exec-local: rtai_rtdm$(modext)
$(mkinstalldirs) $(DESTDIR)$(moduledir) $(DESTDIR)$(includedir)
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
uninstall-local:
$(RM) $(DESTDIR)$(moduledir)/rtai_rtdm$(modext)
.PHONY: FORCE
EXTRA_DIST = $(libmodule_SRC) Makefile.kbuild \
internal.h
# Always build if CONFIG_RTAI_RTDM is enabled
if CONFIG_RTAI_RTDM
OPTDIRS = lib
endif
SUBDIRS = $(OPTDIRS)

View file

@ -1,12 +0,0 @@
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
-I$(rtai_srctree)/addons/rtdm \
-I$(rtai_srcdir)/.. \
-I$(src)/../../base/include \
-I$(src) \
-I$(src)/../.. \
$(rtai_extradef)
obj-m += $(rtai_target).o
$(rtai_target)-objs := $(rtai_objs)

File diff suppressed because it is too large Load diff

View file

@ -1,522 +0,0 @@
/**
* @file
* Real-Time Driver Model for RTAI, device management
*
* @note Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>
* @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
*
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*!
* @addtogroup driverapi
* @{
*/
#include <linux/module.h>
#include <linux/delay.h>
#include "rtdm/internal.h"
#define SET_DEFAULT_OP(device, operation) \
(device).operation##_rt = (void *)rtdm_no_support; \
(device).operation##_nrt = (void *)rtdm_no_support
#define SET_DEFAULT_OP_IF_NULL(device, operation) \
if (!(device).operation##_rt) \
(device).operation##_rt = (void *)rtdm_no_support; \
if (!(device).operation##_nrt) \
(device).operation##_nrt = (void *)rtdm_no_support
#define ANY_HANDLER(device, operation) \
((device).operation##_rt || (device).operation##_nrt)
unsigned int devname_hashtab_size = DEF_DEVNAME_HASHTAB_SIZE;
unsigned int protocol_hashtab_size = DEF_PROTO_HASHTAB_SIZE;
module_param(devname_hashtab_size, uint, 0400);
module_param(protocol_hashtab_size, uint, 0400);
MODULE_PARM_DESC(devname_hashtab_size,
"Size of hash table for named devices (must be power of 2)");
MODULE_PARM_DESC(protocol_hashtab_size,
"Size of hash table for protocol devices "
"(must be power of 2)");
struct list_head *rtdm_named_devices; /* hash table */
struct list_head *rtdm_protocol_devices; /* hash table */
static int name_hashkey_mask;
static int proto_hashkey_mask;
int rtdm_apc;
EXPORT_SYMBOL(rtdm_apc);
struct semaphore nrt_dev_lock;
DEFINE_XNLOCK(rt_dev_lock);
#ifndef MODULE
int rtdm_initialised = 0;
#endif /* !MODULE */
int rtdm_no_support(void)
{
return -ENOSYS;
}
int rtdm_select_bind_no_support(struct rtdm_dev_context *context,
struct xnselector *selector,
unsigned type,
unsigned index)
{
return -EBADF;
}
static inline int get_name_hash(const char *str, int limit, int hashkey_mask)
{
int hash = 0;
while (*str != 0) {
hash += *str++;
if (--limit == 0)
break;
}
return hash & hashkey_mask;
}
static inline int get_proto_hash(int protocol_family, int socket_type)
{
return protocol_family & proto_hashkey_mask;
}
static inline void rtdm_reference_device(struct rtdm_device *device)
{
atomic_inc(&device->reserved.refcount);
}
struct rtdm_device *get_named_device(const char *name)
{
struct list_head *entry;
struct rtdm_device *device;
int hashkey;
spl_t s;
hashkey = get_name_hash(name, RTDM_MAX_DEVNAME_LEN, name_hashkey_mask);
xnlock_get_irqsave(&rt_dev_lock, s);
list_for_each(entry, &rtdm_named_devices[hashkey]) {
device = list_entry(entry, struct rtdm_device, reserved.entry);
if (strcmp(name, device->device_name) == 0) {
rtdm_reference_device(device);
xnlock_put_irqrestore(&rt_dev_lock, s);
return device;
}
}
xnlock_put_irqrestore(&rt_dev_lock, s);
return NULL;
}
struct rtdm_device *get_protocol_device(int protocol_family, int socket_type)
{
struct list_head *entry;
struct rtdm_device *device;
int hashkey;
spl_t s;
hashkey = get_proto_hash(protocol_family, socket_type);
xnlock_get_irqsave(&rt_dev_lock, s);
list_for_each(entry, &rtdm_protocol_devices[hashkey]) {
device = list_entry(entry, struct rtdm_device, reserved.entry);
if ((device->protocol_family == protocol_family) &&
(device->socket_type == socket_type)) {
rtdm_reference_device(device);
xnlock_put_irqrestore(&rt_dev_lock, s);
return device;
}
}
xnlock_put_irqrestore(&rt_dev_lock, s);
return NULL;
}
/*!
* @ingroup driverapi
* @defgroup devregister Device Registration Services
* @{
*/
/**
* @brief Register a RTDM device
*
* @param[in] device Pointer to structure describing the new device.
*
* @return 0 is returned upon success. Otherwise:
*
* - -EINVAL is returned if the device structure contains invalid entries.
* Check kernel log in this case.
*
* - -ENOMEM is returned if the context for an exclusive device cannot be
* allocated.
*
* - -EEXIST is returned if the specified device name of protocol ID is
* already in use.
*
* - -EAGAIN is returned if some /proc entry cannot be created.
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
*
* Rescheduling: never.
*/
int rtdm_dev_register(struct rtdm_device *device)
{
int hashkey;
spl_t s;
struct list_head *entry;
struct rtdm_device *existing_dev;
int ret;
/* Catch unsuccessful initialisation */
if (!rtdm_initialised)
return -ENOSYS;
/* Sanity check: structure version */
RTAI_ASSERT(RTDM, device->struct_version == RTDM_DEVICE_STRUCT_VER,
xnlogerr("RTDM: invalid rtdm_device version (%d, "
"required %d)\n", device->struct_version,
RTDM_DEVICE_STRUCT_VER);
return -EINVAL;);
/* Sanity check: proc_name specified? */
RTAI_ASSERT(RTDM, device->proc_name,
xnlogerr("RTDM: no /proc entry name specified\n");
return -EINVAL;);
switch (device->device_flags & RTDM_DEVICE_TYPE_MASK) {
case RTDM_NAMED_DEVICE:
/* Sanity check: any open handler? */
RTAI_ASSERT(RTDM, ANY_HANDLER(*device, open),
xnlogerr("RTDM: missing open handler\n");
return -EINVAL;);
if (device->open_rt &&
device->socket_rt != (void *)rtdm_no_support)
xnlogerr("RTDM: RT open handler is deprecated, "
"driver requires update.\n");
SET_DEFAULT_OP_IF_NULL(*device, open);
SET_DEFAULT_OP(*device, socket);
break;
case RTDM_PROTOCOL_DEVICE:
/* Sanity check: any socket handler? */
RTAI_ASSERT(RTDM, ANY_HANDLER(*device, socket),
xnlogerr("RTDM: missing socket handler\n");
return -EINVAL;);
if (device->socket_rt &&
device->socket_rt != (void *)rtdm_no_support)
xnlogerr("RTDM: RT socket creation handler is "
"deprecated, driver requires update.\n");
SET_DEFAULT_OP_IF_NULL(*device, socket);
SET_DEFAULT_OP(*device, open);
break;
default:
return -EINVAL;
}
/* Sanity check: non-RT close handler?
* (Always required for forced cleanup) */
if (!device->ops.close_nrt) {
xnlogerr("RTDM: missing non-RT close handler\n");
return -EINVAL;
}
if (device->ops.close_rt &&
device->ops.close_rt != (void *)rtdm_no_support)
xnlogerr("RTDM: RT close handler is deprecated, driver "
"requires update.\n");
else
device->ops.close_rt = (void *)rtdm_no_support;
SET_DEFAULT_OP_IF_NULL(device->ops, ioctl);
SET_DEFAULT_OP_IF_NULL(device->ops, read);
SET_DEFAULT_OP_IF_NULL(device->ops, write);
SET_DEFAULT_OP_IF_NULL(device->ops, recvmsg);
SET_DEFAULT_OP_IF_NULL(device->ops, sendmsg);
if (!device->ops.select_bind)
device->ops.select_bind = rtdm_select_bind_no_support;
atomic_set(&device->reserved.refcount, 0);
device->reserved.exclusive_context = NULL;
if (device->device_flags & RTDM_EXCLUSIVE) {
device->reserved.exclusive_context =
kmalloc(sizeof(struct rtdm_dev_context) +
device->context_size, GFP_KERNEL);
if (!device->reserved.exclusive_context) {
xnlogerr("RTDM: no memory for exclusive context "
"(context size: %ld)\n",
(long)device->context_size);
return -ENOMEM;
}
/* mark exclusive context as unused */
device->reserved.exclusive_context->device = NULL;
}
down(&nrt_dev_lock);
if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE) {
trace_mark(xn_rtdm, nameddev_register, "device %p name %s "
"flags %d class %d sub_class %d profile_version %d "
"driver_version %d", device, device->device_name,
device->device_flags, device->device_class,
device->device_sub_class, device->profile_version,
device->driver_version);
hashkey =
get_name_hash(device->device_name, RTDM_MAX_DEVNAME_LEN,
name_hashkey_mask);
list_for_each(entry, &rtdm_named_devices[hashkey]) {
existing_dev =
list_entry(entry, struct rtdm_device,
reserved.entry);
if (strcmp(device->device_name,
existing_dev->device_name) == 0) {
ret = -EEXIST;
goto err;
}
}
ret = rtdm_proc_register_device(device);
if (ret)
goto err;
xnlock_get_irqsave(&rt_dev_lock, s);
list_add_tail(&device->reserved.entry,
&rtdm_named_devices[hashkey]);
xnlock_put_irqrestore(&rt_dev_lock, s);
up(&nrt_dev_lock);
} else {
trace_mark(xn_rtdm, protocol_register, "device %p "
"protocol_family %d socket_type %d flags %d "
"class %d sub_class %d profile_version %d "
"driver_version %d", device,
device->protocol_family, device->socket_type,
device->device_flags, device->device_class,
device->device_sub_class, device->profile_version,
device->driver_version);
hashkey = get_proto_hash(device->protocol_family,
device->socket_type);
list_for_each(entry, &rtdm_protocol_devices[hashkey]) {
existing_dev =
list_entry(entry, struct rtdm_device,
reserved.entry);
if ((device->protocol_family ==
existing_dev->protocol_family)
&& (device->socket_type ==
existing_dev->socket_type)) {
xnlogerr("RTDM: protocol %u:%u already "
"exists\n", device->protocol_family,
device->socket_type);
ret = -EEXIST;
goto err;
}
}
ret = rtdm_proc_register_device(device);
if (ret)
goto err;
xnlock_get_irqsave(&rt_dev_lock, s);
list_add_tail(&device->reserved.entry,
&rtdm_protocol_devices[hashkey]);
xnlock_put_irqrestore(&rt_dev_lock, s);
up(&nrt_dev_lock);
}
return 0;
err:
up(&nrt_dev_lock);
if (device->reserved.exclusive_context)
kfree(device->reserved.exclusive_context);
return ret;
}
EXPORT_SYMBOL(rtdm_dev_register);
/**
* @brief Unregisters a RTDM device
*
* @param[in] device Pointer to structure describing the device to be
* unregistered.
* @param[in] poll_delay Polling delay in milliseconds to check repeatedly for
* open instances of @a device, or 0 for non-blocking mode.
*
* @return 0 is returned upon success. Otherwise:
*
* - -ENODEV is returned if the device was not registered.
*
* - -EAGAIN is returned if the device is busy with open instances and 0 has
* been passed for @a poll_delay.
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
*
* Rescheduling: never.
*/
int rtdm_dev_unregister(struct rtdm_device *device, unsigned int poll_delay)
{
spl_t s;
struct rtdm_device *reg_dev;
unsigned long warned = 0;
if (!rtdm_initialised)
return -ENOSYS;
if ((device->device_flags & RTDM_DEVICE_TYPE_MASK) == RTDM_NAMED_DEVICE)
reg_dev = get_named_device(device->device_name);
else
reg_dev = get_protocol_device(device->protocol_family,
device->socket_type);
if (!reg_dev)
return -ENODEV;
trace_mark(xn_rtdm, dev_unregister, "device %p poll_delay %u",
device, poll_delay);
down(&nrt_dev_lock);
xnlock_get_irqsave(&rt_dev_lock, s);
while (atomic_read(&reg_dev->reserved.refcount) > 1) {
xnlock_put_irqrestore(&rt_dev_lock, s);
up(&nrt_dev_lock);
if (!poll_delay) {
rtdm_dereference_device(reg_dev);
trace_mark(xn_rtdm, dev_busy, "device %p", device);
return -EAGAIN;
}
if (!__test_and_set_bit(0, &warned))
xnlogwarn("RTDM: device %s still in use - waiting for "
"release...\n", reg_dev->device_name);
msleep(poll_delay);
trace_mark(xn_rtdm, dev_poll, "device %p", device);
down(&nrt_dev_lock);
xnlock_get_irqsave(&rt_dev_lock, s);
}
list_del(&reg_dev->reserved.entry);
xnlock_put_irqrestore(&rt_dev_lock, s);
rtdm_proc_unregister_device(device);
up(&nrt_dev_lock);
if (reg_dev->reserved.exclusive_context)
kfree(device->reserved.exclusive_context);
return 0;
}
EXPORT_SYMBOL(rtdm_dev_unregister);
/** @} */
int __init rtdm_dev_init(void)
{
int err, i;
sema_init(&nrt_dev_lock, 1);
rtdm_apc = rthal_apc_alloc("deferred RTDM close", rtdm_apc_handler,
NULL);
if (rtdm_apc < 0)
return rtdm_apc;
name_hashkey_mask = devname_hashtab_size - 1;
proto_hashkey_mask = protocol_hashtab_size - 1;
if (((devname_hashtab_size & name_hashkey_mask) != 0) ||
((protocol_hashtab_size & proto_hashkey_mask) != 0)) {
err = -EINVAL;
goto err_out1;
}
rtdm_named_devices = (struct list_head *)
kmalloc(devname_hashtab_size * sizeof(struct list_head),
GFP_KERNEL);
if (!rtdm_named_devices) {
err = -ENOMEM;
goto err_out1;
}
for (i = 0; i < devname_hashtab_size; i++)
INIT_LIST_HEAD(&rtdm_named_devices[i]);
rtdm_protocol_devices = (struct list_head *)
kmalloc(protocol_hashtab_size * sizeof(struct list_head),
GFP_KERNEL);
if (!rtdm_protocol_devices) {
err = -ENOMEM;
goto err_out2;
}
for (i = 0; i < protocol_hashtab_size; i++)
INIT_LIST_HEAD(&rtdm_protocol_devices[i]);
return 0;
err_out2:
kfree(rtdm_named_devices);
err_out1:
rthal_apc_free(rtdm_apc);
return err;
}
void rtdm_dev_cleanup(void)
{
/*
* Note: no need to flush the cleanup_queue as no device is allowed
* to deregister as long as there are references.
*/
rthal_apc_free(rtdm_apc);
kfree(rtdm_named_devices);
kfree(rtdm_protocol_devices);
}
/*@}*/

View file

@ -1,67 +0,0 @@
/*
* Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>.
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
*
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _RTDM_DEVICE_H
#define _RTDM_DEVICE_H
#include <rtdm/rtdm_driver.h>
#include <linux/sem.h>
#define DEF_DEVNAME_HASHTAB_SIZE 256 /* entries in name hash table */
#define DEF_PROTO_HASHTAB_SIZE 256 /* entries in protocol hash table */
extern struct semaphore nrt_dev_lock;
extern xnlock_t rt_dev_lock;
extern unsigned int devname_hashtab_size;
extern unsigned int protocol_hashtab_size;
extern struct list_head *rtdm_named_devices;
extern struct list_head *rtdm_protocol_devices;
#ifdef MODULE
#define rtdm_initialised 1
#else /* !MODULE */
extern int rtdm_initialised;
#endif /* MODULE */
int rtdm_no_support(void);
struct rtdm_device *get_named_device(const char *name);
struct rtdm_device *get_protocol_device(int protocol_family, int socket_type);
static inline void rtdm_dereference_device(struct rtdm_device *device)
{
atomic_dec(&device->reserved.refcount);
}
int __init rtdm_dev_init(void);
static inline void rtdm_dev_cleanup(void)
{
kfree(rtdm_named_devices);
kfree(rtdm_protocol_devices);
}
#endif /* _RTDM_DEVICE_H */

File diff suppressed because it is too large Load diff

View file

@ -1,106 +0,0 @@
/*
* Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de>.
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
*
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _RTDM_INTERNAL_H
#define _RTDM_INTERNAL_H
#include <linux/list.h>
#include <linux/proc_fs.h>
#include <linux/sem.h>
#include <rtdm/rtdm_driver.h>
#define RTDM_FD_MAX CONFIG_RTAI_RTDM_FD_MAX
#define DEF_DEVNAME_HASHTAB_SIZE 256 /* entries in name hash table */
#define DEF_PROTO_HASHTAB_SIZE 256 /* entries in protocol hash table */
struct rtdm_fildes {
struct rtdm_dev_context *context;
};
struct rtdm_process {
#ifdef CONFIG_PROC_FS
char name[32];
pid_t pid;
#endif /* CONFIG_PROC_FS */
};
DECLARE_EXTERN_XNLOCK(rt_fildes_lock);
DECLARE_EXTERN_XNLOCK(rt_dev_lock);
extern int __rtdm_muxid;
extern struct rtdm_fildes fildes_table[];
extern int open_fildes;
extern struct semaphore nrt_dev_lock;
extern unsigned int devname_hashtab_size;
extern unsigned int protocol_hashtab_size;
extern struct list_head *rtdm_named_devices;
extern struct list_head *rtdm_protocol_devices;
#ifdef MODULE
#define rtdm_initialised 1
#else /* !MODULE */
extern int rtdm_initialised;
#endif /* MODULE */
void cleanup_owned_contexts(void *user_info);
int rtdm_no_support(void);
struct rtdm_device *get_named_device(const char *name);
struct rtdm_device *get_protocol_device(int protocol_family, int socket_type);
static inline void rtdm_dereference_device(struct rtdm_device *device)
{
atomic_dec(&device->reserved.refcount);
}
int __init rtdm_dev_init(void);
void rtdm_dev_cleanup(void);
#ifdef CONFIG_PROC_FS
int __init rtdm_proc_init(void);
void rtdm_proc_cleanup(void);
int rtdm_proc_register_device(struct rtdm_device *device);
void rtdm_proc_unregister_device(struct rtdm_device *device);
#else
static inline int rtdm_proc_init(void)
{
return 0;
}
void rtdm_proc_cleanup(void)
{
}
static int rtdm_proc_register_device(struct rtdm_device *device)
{
return 0;
}
static void rtdm_proc_unregister_device(struct rtdm_device *device)
{
}
#endif
void rtdm_apc_handler(void *cookie);
#endif /* _RTDM_INTERNAL_H */

View file

@ -1,14 +0,0 @@
lib_LTLIBRARIES = librtdm.la
librtdm_la_LDFLAGS = -module -version-info 0:0:0
librtdm_la_SOURCES = \
services.c
AM_CPPFLAGS = \
@RTAI_REAL_USER_CFLAGS@ \
-fno-inline \
-I../../../base/include \
-I$(top_srcdir)/base/include \
-I$(top_srcdir)/addons \
-I$(srcdir)/../..

View file

@ -1,19 +0,0 @@
/*
* Copyright (C) Pierre Cloutier <pcloutier@PoseidonControls.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the version 2 of the GNU Lesser
* General Public License as published by the Free Software
* Foundation.
*
* This 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
#include <rtdm/rtdm.h>

View file

@ -1,977 +0,0 @@
/**
* @file
* Real-Time Driver Model for RTAI
*
* @note Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>
* @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
* @note Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
* only for the adaption to RTAI.
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*!
* @defgroup rtdm Real-Time Driver Model
*
* The Real-Time Driver Model (RTDM) provides a unified interface to
* both users and developers of real-time device
* drivers. Specifically, it addresses the constraints of mixed
* RT/non-RT systems like RTAI. RTDM conforms to POSIX
* semantics (IEEE Std 1003.1) where available and applicable.
*/
/*!
* @ingroup rtdm
* @defgroup profiles Device Profiles
*
* Device profiles define which operation handlers a driver of a certain class
* has to implement, which name or protocol it has to register, which IOCTLs
* it has to provide, and further details. Sub-classes can be defined in order
* to extend a device profile with more hardware-specific functions.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <rtdm/rtdm.h>
#include <rtdm/internal.h>
#include <rtdm/rtdm_driver.h>
MODULE_DESCRIPTION("Real-Time Driver Model");
MODULE_AUTHOR("jan.kiszka@web.de");
MODULE_LICENSE("GPL");
static RTAI_SYSCALL_MODE int sys_rtdm_fdcount(void)
{
return RTDM_FD_MAX;
}
static RTAI_SYSCALL_MODE int sys_rtdm_open(const char *path, long oflag)
{
struct task_struct *curr = current;
char krnl_path[RTDM_MAX_DEVNAME_LEN + 1];
if (unlikely(!__xn_access_ok(curr, VERIFY_READ, path, sizeof(krnl_path)))) {
return -EFAULT;
}
__xn_copy_from_user(curr, krnl_path, path, sizeof(krnl_path) - 1);
krnl_path[sizeof(krnl_path) - 1] = '\0';
return __rt_dev_open(curr, (const char *)krnl_path, oflag);
}
static RTAI_SYSCALL_MODE int sys_rtdm_socket(long protocol_family, long socket_type, long protocol)
{
return __rt_dev_socket(current, protocol_family, socket_type, protocol);
}
static RTAI_SYSCALL_MODE int sys_rtdm_close(long fd, long forced)
{
return __rt_dev_close(current, fd);
}
static RTAI_SYSCALL_MODE int sys_rtdm_ioctl(long fd, long request, void *arg)
{
return __rt_dev_ioctl(current, fd, request, arg);
}
static RTAI_SYSCALL_MODE int sys_rtdm_read(long fd, void *buf, long nbytes)
{
return __rt_dev_read(current, fd, buf, nbytes);
}
static RTAI_SYSCALL_MODE int sys_rtdm_write(long fd, void *buf, long nbytes)
{
return __rt_dev_write(current, fd, buf, nbytes);
}
static RTAI_SYSCALL_MODE int sys_rtdm_recvmsg(long fd, struct msghdr *msg, long flags)
{
struct msghdr krnl_msg;
struct task_struct *curr = current;
int ret;
if (unlikely(!__xn_access_ok(curr, VERIFY_WRITE, msg, sizeof(krnl_msg)))) {
return -EFAULT;
}
__xn_copy_from_user(curr, &krnl_msg, msg, sizeof(krnl_msg));
if ((ret = __rt_dev_recvmsg(curr, fd, &krnl_msg, flags)) >= 0) {
__xn_copy_to_user(curr, msg, &krnl_msg, sizeof(krnl_msg));
}
return ret;
}
static RTAI_SYSCALL_MODE int sys_rtdm_sendmsg(long fd, const struct msghdr *msg, long flags)
{
struct msghdr krnl_msg;
struct task_struct *curr = current;
if (unlikely(!__xn_access_ok(curr, VERIFY_READ, msg, sizeof(krnl_msg)))) {
return -EFAULT;
}
__xn_copy_from_user(curr, &krnl_msg, msg, sizeof(krnl_msg));
return __rt_dev_sendmsg(curr, fd, &krnl_msg, flags);
}
static RTAI_SYSCALL_MODE int sys_rtdm_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
{
return rt_dev_select(nfds, rfds, wfds, efds, timeout);
}
static struct rt_fun_entry rtdm[] = {
[__rtdm_fdcount] = { 0, sys_rtdm_fdcount },
[__rtdm_open] = { 0, sys_rtdm_open },
[__rtdm_socket] = { 0, sys_rtdm_socket },
[__rtdm_close] = { 0, sys_rtdm_close },
[__rtdm_ioctl] = { 0, sys_rtdm_ioctl },
[__rtdm_read] = { 0, sys_rtdm_read },
[__rtdm_write] = { 0, sys_rtdm_write },
[__rtdm_recvmsg] = { 0, sys_rtdm_recvmsg },
[__rtdm_sendmsg] = { 0, sys_rtdm_sendmsg },
[__rtdm_select] = { 0, sys_rtdm_select },
};
/* This is needed because RTDM interrupt handlers:
* - do no want immediate in handler rescheduling, RTAI can be configured
* to act in the same, way but might not have been enabled to do so;
* - may not reenable the PIC directly, assuming it will be done here;
* - may not propagate, assuming it will be done here as well.
* - might use shared interrupts its own way;
* REMARK: RTDM irqs management is as generic as its pet system dictates
* and there is no choice but doing the same as closely as possible;
* so this is an as verbatim as possible copy of what is needed from
* the RTDM pet system.
* REMINDER: the RTAI dispatcher cares mask/ack-ing anyhow, but RTDM will
* (must) provide the most suitable one for the shared case. */
#ifndef CONFIG_RTAI_SCHED_ISR_LOCK
extern struct { volatile int locked, rqsted; } rt_scheduling[];
extern void rtai_isr_sched_handle(int);
#define RTAI_SCHED_ISR_LOCK() \
do { \
int cpuid = rtai_cpuid(); \
if (!rt_scheduling[cpuid].locked++) { \
rt_scheduling[cpuid].rqsted = 0; \
}
#define RTAI_SCHED_ISR_UNLOCK() \
rtai_cli(); \
if (rt_scheduling[cpuid].locked && !(--rt_scheduling[cpuid].locked)) { \
if (rt_scheduling[cpuid].rqsted > 0) { \
rtai_isr_sched_handle(cpuid); \
} \
} \
} while (0)
#else /* !CONFIG_RTAI_SCHED_ISR_LOCK */
#define RTAI_SCHED_ISR_LOCK() \
do { } while (0)
#define RTAI_SCHED_ISR_UNLOCK() \
do { rtai_cli(); } while (0)
#endif /* CONFIG_RTAI_SCHED_ISR_LOCK */
#define XNINTR_MAX_UNHANDLED 1000
DEFINE_PRIVATE_XNLOCK(intrlock);
static void xnintr_irq_handler(unsigned irq, void *cookie);
#ifdef CONFIG_RTAI_RTDM_SHIRQ
typedef struct xnintr_irq {
DECLARE_XNLOCK(lock);
xnintr_t *handlers;
int unhandled;
} ____cacheline_aligned_in_smp xnintr_irq_t;
static xnintr_irq_t xnirqs[RTHAL_NR_IRQS];
static inline xnintr_t *xnintr_shirq_first(unsigned irq)
{
return xnirqs[irq].handlers;
}
static inline xnintr_t *xnintr_shirq_next(xnintr_t *prev)
{
return prev->next;
}
/*
* Low-level interrupt handler dispatching the user-defined ISRs for
* shared interrupts -- Called with interrupts off.
*/
static void xnintr_shirq_handler(unsigned irq, void *cookie)
{
xnintr_irq_t *shirq = &xnirqs[irq];
xnintr_t *intr;
int s = 0, ret;
RTAI_SCHED_ISR_LOCK();
xnlock_get(&shirq->lock);
intr = shirq->handlers;
while (intr) {
ret = intr->isr(intr);
s |= ret;
if (ret & XN_ISR_HANDLED) {
xnstat_counter_inc(
&intr->stat[xnsched_cpu(sched)].hits);
}
intr = intr->next;
}
xnlock_put(&shirq->lock);
if (unlikely(s == XN_ISR_NONE)) {
if (++shirq->unhandled == XNINTR_MAX_UNHANDLED) {
xnlogerr("%s: IRQ%d not handled. Disabling IRQ "
"line.\n", __FUNCTION__, irq);
s |= XN_ISR_NOENABLE;
}
} else
shirq->unhandled = 0;
if (s & XN_ISR_PROPAGATE)
xnarch_chain_irq(irq);
else if (!(s & XN_ISR_NOENABLE))
xnarch_end_irq(irq);
RTAI_SCHED_ISR_UNLOCK();
}
/*
* Low-level interrupt handler dispatching the user-defined ISRs for
* shared edge-triggered interrupts -- Called with interrupts off.
*/
static void xnintr_edge_shirq_handler(unsigned irq, void *cookie)
{
const int MAX_EDGEIRQ_COUNTER = 128;
xnintr_irq_t *shirq = &xnirqs[irq];
int s = 0, counter = 0, ret, code;
struct xnintr *intr, *end = NULL;
RTAI_SCHED_ISR_LOCK();
xnlock_get(&shirq->lock);
intr = shirq->handlers;
while (intr != end) {
ret = intr->isr(intr);
code = ret & ~XN_ISR_BITMASK;
s |= ret;
if (code == XN_ISR_HANDLED) {
end = NULL;
xnstat_counter_inc(
&intr->stat[xnsched_cpu(sched)].hits);
} else if (end == NULL)
end = intr;
if (counter++ > MAX_EDGEIRQ_COUNTER)
break;
if (!(intr = intr->next))
intr = shirq->handlers;
}
xnlock_put(&shirq->lock);
if (counter > MAX_EDGEIRQ_COUNTER)
xnlogerr
("xnintr_edge_shirq_handler() : failed to get the IRQ%d line free.\n",
irq);
if (unlikely(s == XN_ISR_NONE)) {
if (++shirq->unhandled == XNINTR_MAX_UNHANDLED) {
xnlogerr("%s: IRQ%d not handled. Disabling IRQ "
"line.\n", __FUNCTION__, irq);
s |= XN_ISR_NOENABLE;
}
} else
shirq->unhandled = 0;
if (s & XN_ISR_PROPAGATE)
xnarch_chain_irq(irq);
else if (!(s & XN_ISR_NOENABLE))
xnarch_end_irq(irq);
RTAI_SCHED_ISR_UNLOCK();
}
static inline int xnintr_irq_attach(xnintr_t *intr)
{
xnintr_irq_t *shirq = &xnirqs[intr->irq];
xnintr_t *prev, **p = &shirq->handlers;
int err;
if ((prev = *p) != NULL) {
/* Check on whether the shared mode is allowed. */
if (!(prev->flags & intr->flags & XN_ISR_SHARED) ||
(prev->iack != intr->iack)
|| ((prev->flags & XN_ISR_EDGE) !=
(intr->flags & XN_ISR_EDGE)))
return -EBUSY;
/* Get a position at the end of the list to insert the new element. */
while (prev) {
p = &prev->next;
prev = *p;
}
} else {
/* Initialize the corresponding interrupt channel */
void (*handler) (unsigned, void *) = &xnintr_irq_handler;
if (intr->flags & XN_ISR_SHARED) {
if (intr->flags & XN_ISR_EDGE)
handler = &xnintr_edge_shirq_handler;
else
handler = &xnintr_shirq_handler;
}
shirq->unhandled = 0;
err = xnarch_hook_irq(intr->irq, handler,
intr->iack, intr);
if (err)
return err;
}
intr->next = NULL;
/* Add the given interrupt object. No need to synchronise with the IRQ
handler, we are only extending the chain. */
*p = intr;
return 0;
}
static inline int xnintr_irq_detach(xnintr_t *intr)
{
xnintr_irq_t *shirq = &xnirqs[intr->irq];
xnintr_t *e, **p = &shirq->handlers;
int err = 0;
while ((e = *p) != NULL) {
if (e == intr) {
/* Remove the given interrupt object from the list. */
xnlock_get(&shirq->lock);
*p = e->next;
xnlock_put(&shirq->lock);
/* Release the IRQ line if this was the last user */
if (shirq->handlers == NULL)
err = xnarch_release_irq(intr->irq);
return err;
}
p = &e->next;
}
xnlogerr("attempted to detach a non previously attached interrupt "
"object.\n");
return err;
}
#else /* !CONFIG_RTAI_RTDM_SHIRQ */
#ifdef CONFIG_SMP
typedef struct xnintr_irq {
DECLARE_XNLOCK(lock);
} ____cacheline_aligned_in_smp xnintr_irq_t;
static xnintr_irq_t xnirqs[RTHAL_NR_IRQS];
#endif /* CONFIG_SMP */
static inline xnintr_t *xnintr_shirq_first(unsigned irq)
{
return xnarch_get_irq_cookie(irq);
}
static inline xnintr_t *xnintr_shirq_next(xnintr_t *prev)
{
return NULL;
}
static inline int xnintr_irq_attach(xnintr_t *intr)
{
return xnarch_hook_irq(intr->irq, &xnintr_irq_handler,
intr->iack, intr);
}
static inline int xnintr_irq_detach(xnintr_t *intr)
{
int irq = intr->irq, ret;
xnlock_get(&xnirqs[irq].lock);
ret = xnarch_release_irq(irq);
xnlock_put(&xnirqs[irq].lock);
return ret;
}
#endif /* !CONFIG_RTAI_RTDM_SHIRQ */
/*
* Low-level interrupt handler dispatching non-shared ISRs -- Called with
* interrupts off.
*/
static void xnintr_irq_handler(unsigned irq, void *cookie)
{
struct xnintr *intr;
int s;
RTAI_SCHED_ISR_LOCK();
xnlock_get(&xnirqs[irq].lock);
#ifdef CONFIG_SMP
/*
* In SMP case, we have to reload the cookie under the per-IRQ
* lock to avoid racing with xnintr_detach. However, we
* assume that no CPU migration will occur while running the
* interrupt service routine, so the scheduler pointer will
* remain valid throughout this function.
*/
intr = xnarch_get_irq_cookie(irq);
if (unlikely(!intr)) {
s = 0;
goto unlock_and_exit;
}
#else
/* cookie always valid, attach/detach happens with IRQs disabled */
intr = cookie;
#endif
s = intr->isr(intr);
if (unlikely(s == XN_ISR_NONE)) {
if (++intr->unhandled == XNINTR_MAX_UNHANDLED) {
xnlogerr("%s: IRQ%d not handled. Disabling IRQ "
"line.\n", __FUNCTION__, irq);
s |= XN_ISR_NOENABLE;
}
} else {
xnstat_counter_inc(&intr->stat[xnsched_cpu(sched)].hits);
intr->unhandled = 0;
}
#ifdef CONFIG_SMP
unlock_and_exit:
#endif
xnlock_put(&xnirqs[irq].lock);
if (s & XN_ISR_PROPAGATE)
xnarch_chain_irq(irq);
else if (!(s & XN_ISR_NOENABLE))
xnarch_end_irq(irq);
RTAI_SCHED_ISR_UNLOCK();
}
int xnintr_mount(void)
{
int i;
for (i = 0; i < RTHAL_NR_IRQS; ++i)
xnlock_init(&xnirqs[i].lock);
return 0;
}
int xnintr_init(xnintr_t *intr,
const char *name,
unsigned irq, xnisr_t isr, xniack_t iack, xnflags_t flags)
{
if (irq >= RTHAL_NR_IRQS)
return -EINVAL;
intr->irq = irq;
intr->isr = isr;
intr->iack = iack;
intr->cookie = NULL;
intr->name = name ? : "<unknown>";
intr->flags = flags;
intr->unhandled = 0;
memset(&intr->stat, 0, sizeof(intr->stat));
#ifdef CONFIG_RTAI_RTDM_SHIRQ
intr->next = NULL;
#endif
return 0;
}
EXPORT_SYMBOL_GPL(xnintr_init);
int xnintr_destroy(xnintr_t *intr)
{
return xnintr_detach(intr);
}
EXPORT_SYMBOL_GPL(xnintr_destroy);
int xnintr_attach(xnintr_t *intr, void *cookie)
{
int ret;
spl_t s;
intr->cookie = cookie;
memset(&intr->stat, 0, sizeof(intr->stat));
#ifdef CONFIG_SMP
xnarch_set_irq_affinity(intr->irq, nkaffinity);
#endif /* CONFIG_SMP */
xnlock_get_irqsave(&intrlock, s);
if (__testbits(intr->flags, XN_ISR_ATTACHED)) {
ret = -EBUSY;
goto out;
}
ret = xnintr_irq_attach(intr);
if (ret)
goto out;
__setbits(intr->flags, XN_ISR_ATTACHED);
out:
xnlock_put_irqrestore(&intrlock, s);
return ret;
}
EXPORT_SYMBOL_GPL(xnintr_attach);
int xnintr_detach(xnintr_t *intr)
{
int ret;
spl_t s;
xnlock_get_irqsave(&intrlock, s);
if (!__testbits(intr->flags, XN_ISR_ATTACHED)) {
ret = -EINVAL;
goto out;
}
__clrbits(intr->flags, XN_ISR_ATTACHED);
ret = xnintr_irq_detach(intr);
if (ret)
goto out;
out:
xnlock_put_irqrestore(&intrlock, s);
return ret;
}
EXPORT_SYMBOL_GPL(xnintr_detach);
int xnintr_enable(xnintr_t *intr)
{
rt_enable_irq(intr->irq);
return 0;
}
EXPORT_SYMBOL_GPL(xnintr_enable);
int xnintr_disable(xnintr_t *intr)
{
rt_disable_irq(intr->irq);
return 0;
}
EXPORT_SYMBOL_GPL(xnintr_disable);
typedef cpumask_t xnarch_cpumask_t;
void xnintr_affinity(xnintr_t *intr, xnarch_cpumask_t cpumask)
{
trace_mark(xn_nucleus, irq_affinity, "irq %u %lu",
intr->irq, *(unsigned long *)&cpumask);
xnarch_set_irq_affinity(intr->irq, cpumask);
}
EXPORT_SYMBOL_GPL(xnintr_affinity);
extern struct epoch_struct boot_epoch;
#ifdef CONFIG_SMP
#define NUM_CPUS RTAI_NR_CPUS
#define TIMED_TIMER_CPUID (timed_timer->cpuid)
#define TIMER_CPUID (timer->cpuid)
#define LIST_CPUID (cpuid)
#else
#define NUM_CPUS 1
#define TIMED_TIMER_CPUID (0)
#define TIMER_CPUID (0)
#define LIST_CPUID (0)
#endif
static struct rtdm_timer_struct timers_list[NUM_CPUS] =
{ { &timers_list[0], &timers_list[0], RT_SCHED_LOWEST_PRIORITY, 0, RT_TIME_END, 0LL, NULL, 0UL,
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
{ NULL }
#endif
}, };
//static spinlock_t timers_lock[NUM_CPUS] = { SPIN_LOCK_UNLOCKED, };
static spinlock_t timers_lock[NUM_CPUS] = { __SPIN_LOCK_UNLOCKED(timers_lock[0]), };
#ifdef CONFIG_RTAI_LONG_TIMED_LIST
/* BINARY TREE */
static inline void enq_timer(struct rtdm_timer_struct *timed_timer)
{
struct rtdm_timer_struct *timerh, *tmrnxt, *timer;
rb_node_t **rbtn, *rbtpn = NULL;
timer = timerh = &timers_list[TIMED_TIMER_CPUID];
rbtn = &timerh->rbr.rb_node;
while (*rbtn) {
rbtpn = *rbtn;
tmrnxt = rb_entry(rbtpn, struct rtdm_timer_struct, rbn);
if (timer->firing_time > tmrnxt->firing_time) {
rbtn = &(rbtpn)->rb_right;
} else {
rbtn = &(rbtpn)->rb_left;
timer = tmrnxt;
}
}
rb_link_node(&timed_timer->rbn, rbtpn, rbtn);
rb_insert_color(&timed_timer->rbn, &timerh->rbr);
timer->prev = (timed_timer->prev = timer->prev)->next = timed_timer;
timed_timer->next = timer;
}
#define rb_erase_timer(timer) \
rb_erase(&(timer)->rbn, &timers_list[NUM_CPUS > 1 ? (timer)->cpuid : 0].rbr)
#else /* !CONFIG_RTAI_LONG_TIMED_LIST */
/* LINEAR */
static inline void enq_timer(struct rtdm_timer_struct *timed_timer)
{
struct rtdm_timer_struct *timer;
timer = &timers_list[TIMED_TIMER_CPUID];
while (timed_timer->firing_time > (timer = timer->next)->firing_time);
timer->prev = (timed_timer->prev = timer->prev)->next = timed_timer;
timed_timer->next = timer;
}
#define rb_erase_timer(timer)
#endif /* CONFIG_RTAI_LONG_TIMED_LIST */
static inline void rem_timer(struct rtdm_timer_struct *timer)
{
(timer->next)->prev = timer->prev;
(timer->prev)->next = timer->next;
timer->next = timer->prev = timer;
rb_erase_timer(timer);
}
static RT_TASK timers_manager[NUM_CPUS];
static inline void asgn_min_prio(int cpuid)
{
RT_TASK *timer_manager;
struct rtdm_timer_struct *timer, *timerl;
spinlock_t *lock;
unsigned long flags;
int priority;
priority = (timer = (timerl = &timers_list[LIST_CPUID])->next)->priority;
flags = rt_spin_lock_irqsave(lock = &timers_lock[LIST_CPUID]);
while ((timer = timer->next) != timerl) {
if (timer->priority < priority) {
priority = timer->priority;
}
rt_spin_unlock_irqrestore(flags, lock);
flags = rt_spin_lock_irqsave(lock);
}
rt_spin_unlock_irqrestore(flags, lock);
flags = rt_global_save_flags_and_cli();
if ((timer_manager = &timers_manager[LIST_CPUID])->priority > priority) {
timer_manager->priority = priority;
if (timer_manager->state == RT_SCHED_READY) {
rem_ready_task(timer_manager);
enq_ready_task(timer_manager);
}
}
rt_global_restore_flags(flags);
}
RTAI_SYSCALL_MODE int rt_timer_insert(struct rtdm_timer_struct *timer, int priority, RTIME firing_time, RTIME period, void (*handler)(unsigned long), unsigned long data)
{
spinlock_t *lock;
unsigned long flags, cpuid;
RT_TASK *timer_manager;
if (!handler) {
return -EINVAL;
}
timer->handler = handler;
timer->data = data;
timer->priority = priority;
timer->firing_time = firing_time;
timer->period = period;
REALTIME2COUNT(firing_time)
timer->cpuid = cpuid = NUM_CPUS > 1 ? rtai_cpuid() : 0;
// timer insertion in timers_list
flags = rt_spin_lock_irqsave(lock = &timers_lock[LIST_CPUID]);
enq_timer(timer);
rt_spin_unlock_irqrestore(flags, lock);
// timers_manager priority inheritance
if (timer->priority < (timer_manager = &timers_manager[LIST_CPUID])->priority) {
timer_manager->priority = timer->priority;
}
// timers_task deadline inheritance
flags = rt_global_save_flags_and_cli();
if (timers_list[LIST_CPUID].next == timer && (timer_manager->state & RT_SCHED_DELAYED) && firing_time < timer_manager->resume_time) {
timer_manager->resume_time = firing_time;
rem_timed_task(timer_manager);
enq_timed_task(timer_manager);
rt_schedule();
}
rt_global_restore_flags(flags);
return 0;
}
RTAI_SYSCALL_MODE void rt_timer_remove(struct rtdm_timer_struct *timer)
{
if (timer->next != timer && timer->prev != timer) {
spinlock_t *lock;
unsigned long flags;
flags = rt_spin_lock_irqsave(lock = &timers_lock[TIMER_CPUID]);
rem_timer(timer);
rt_spin_unlock_irqrestore(flags, lock);
asgn_min_prio(TIMER_CPUID);
}
}
static int TimersManagerPrio = 0;
RTAI_MODULE_PARM(TimersManagerPrio, int);
static void rt_timers_manager(long cpuid)
{
RTIME now;
RT_TASK *timer_manager;
struct rtdm_timer_struct *tmr, *timer, *timerl;
spinlock_t *lock;
unsigned long flags, timer_tol;
int priority;
timer_manager = &timers_manager[LIST_CPUID];
timerl = &timers_list[LIST_CPUID];
lock = &timers_lock[LIST_CPUID];
timer_tol = tuned.timers_tol[LIST_CPUID];
while (1) {
rt_sleep_until((timerl->next)->firing_time);
now = rt_get_time() + timer_tol;
while (1) {
tmr = timer = timerl;
priority = RT_SCHED_LOWEST_PRIORITY;
flags = rt_spin_lock_irqsave(lock);
while ((tmr = tmr->next)->firing_time <= now) {
if (tmr->priority < priority) {
priority = (timer = tmr)->priority;
}
}
rt_spin_unlock_irqrestore(flags, lock);
if (timer == timerl) {
if (timer_manager->priority > TimersManagerPrio) {
timer_manager->priority = TimersManagerPrio;
}
break;
}
timer_manager->priority = priority;
flags = rt_spin_lock_irqsave(lock);
rem_timer(timer);
if (timer->period) {
timer->firing_time += timer->period;
enq_timer(timer);
}
rt_spin_unlock_irqrestore(flags, lock);
timer->handler(timer->data);
}
asgn_min_prio(LIST_CPUID);
}
}
static int TimersManagerStacksize = 8192;
RTAI_MODULE_PARM(TimersManagerStacksize, int);
static int rtai_timers_init(void)
{
int cpuid;
for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
timers_lock[cpuid] = timers_lock[0];
timers_list[cpuid] = timers_list[0];
timers_list[cpuid].cpuid = cpuid;
timers_list[cpuid].next = timers_list[cpuid].prev = &timers_list[cpuid];
}
for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
rt_task_init_cpuid(&timers_manager[cpuid], rt_timers_manager, cpuid, TimersManagerStacksize, TimersManagerPrio, 0, NULL, cpuid);
rt_task_resume(&timers_manager[cpuid]);
}
return 0;
}
static void rtai_timers_cleanup(void)
{
int cpuid;
for (cpuid = 0; cpuid < num_online_cpus(); cpuid++) {
rt_task_delete(&timers_manager[cpuid]);
}
}
EXPORT_SYMBOL(rt_timer_insert);
EXPORT_SYMBOL(rt_timer_remove);
int __init rtdm_skin_init(void)
{
int err;
rtai_timers_init();
if(set_rt_fun_ext_index(rtdm, RTDM_INDX)) {
printk("LXRT extension %d already in use. Recompile RTDM with a different extension index\n", RTDM_INDX);
return -EACCES;
}
if ((err = rtdm_dev_init())) {
goto fail;
}
xnintr_mount();
#ifdef CONFIG_RTAI_RTDM_SELECT
if (xnselect_mount()) {
goto cleanup_core;
}
#endif
#ifdef CONFIG_PROC_FS
if ((err = rtdm_proc_init())) {
goto cleanup_core;
}
#endif /* CONFIG_PROC_FS */
printk("RTDM started.\n");
return 0;
cleanup_core:
#ifdef CONFIG_RTAI_RTDM_SELECT
xnselect_umount();
#endif
rtdm_dev_cleanup();
#ifdef CONFIG_PROC_FS
rtdm_proc_cleanup();
#endif /* CONFIG_PROC_FS */
fail:
return err;
}
void __exit rtdm_skin_exit(void)
{
#ifdef CONFIG_RTAI_RTDM_SELECT
xnselect_umount();
#endif
rtai_timers_cleanup();
rtdm_dev_cleanup();
reset_rt_fun_ext_index(rtdm, RTDM_INDX);
#ifdef CONFIG_PROC_FS
rtdm_proc_cleanup();
#endif /* CONFIG_PROC_FS */
printk("RTDM stopped.\n");
}
module_init(rtdm_skin_init);
module_exit(rtdm_skin_exit);

View file

@ -1,445 +0,0 @@
/*
* Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>.
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
*
* adapted to RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "rtdm/internal.h"
#include <rtdm/vfile.h>
struct xnvfile_directory rtdm_vfroot; /* /proc/rtai/rtdm */
struct vfile_device_data {
int h;
int hmax;
struct list_head *devmap;
struct list_head *curr;
};
static int get_nrt_lock(struct xnvfile *vfile)
{
return down_interruptible(&nrt_dev_lock) ? -ERESTARTSYS : 0;
}
static void put_nrt_lock(struct xnvfile *vfile)
{
up(&nrt_dev_lock);
}
static struct xnvfile_lock_ops lockops = {
.get = get_nrt_lock,
.put = put_nrt_lock,
};
static struct list_head *next_devlist(struct vfile_device_data *priv)
{
struct list_head *head;
while (priv->h < priv->hmax) {
head = priv->devmap + priv->h;
if (!list_empty(head))
return head;
priv->h++;
}
return NULL;
}
static void *next_dev(struct xnvfile_regular_iterator *it)
{
struct vfile_device_data *priv = xnvfile_iterator_priv(it);
struct list_head *next;
next = priv->curr->next;
seek:
if (next == priv->devmap + priv->h) {
/* Done with the current hash slot, let's progress. */
if (priv->h >= priv->hmax) {
next = NULL; /* all done. */
goto out;
}
priv->h++;
next = next_devlist(priv);
if (next) {
next = next->next; /* skip head. */
goto seek;
}
}
out:
priv->curr = next;
return next;
}
static void *named_begin(struct xnvfile_regular_iterator *it)
{
struct vfile_device_data *priv = xnvfile_iterator_priv(it);
struct list_head *devlist;
loff_t pos = 0;
priv->devmap = rtdm_named_devices;
priv->hmax = devname_hashtab_size;
priv->h = 0;
devlist = next_devlist(priv);
if (devlist == NULL)
return NULL; /* All devlists empty. */
priv->curr = devlist->next; /* Skip head. */
/*
* priv->curr now points to the first device; advance to the requested
* position from there.
*/
while (priv->curr && pos++ < it->pos)
priv->curr = next_dev(it);
if (pos == 1)
/* Output the header once, only if some device follows. */
xnvfile_puts(it, "Hash\tName\t\t\t\tDriver\t\t/proc\n");
return priv->curr;
}
static int named_show(struct xnvfile_regular_iterator *it, void *data)
{
struct vfile_device_data *priv = xnvfile_iterator_priv(it);
struct list_head *curr = data;
struct rtdm_device *device;
device = list_entry(curr, struct rtdm_device, reserved.entry);
xnvfile_printf(it, "%02X\t%-31s\t%-15s\t%s\n",
priv->h, device->device_name,
device->driver_name,
device->proc_name);
return 0;
}
static struct xnvfile_regular_ops named_vfile_ops = {
.begin = named_begin,
.next = next_dev,
.show = named_show,
};
static struct xnvfile_regular named_vfile = {
.privsz = sizeof(struct vfile_device_data),
.ops = &named_vfile_ops,
.entry = { .lockops = &lockops }
};
static void *proto_begin(struct xnvfile_regular_iterator *it)
{
struct vfile_device_data *priv = xnvfile_iterator_priv(it);
struct list_head *devlist;
loff_t pos = 0;
priv->devmap = rtdm_protocol_devices;
priv->hmax = protocol_hashtab_size;
priv->h = 0;
devlist = next_devlist(priv);
if (devlist == NULL)
return NULL; /* All devlists empty. */
priv->curr = devlist->next; /* Skip head. */
/*
* priv->curr now points to the first device; advance to the requested
* position from there.
*/
while (priv->curr && pos++ < it->pos)
priv->curr = next_dev(it);
if (pos == 1)
/* Output the header once, only if some device follows. */
xnvfile_puts(it, "Hash\tName\t\t\t\tDriver\t\t/proc\n");
return priv->curr;
}
static int proto_show(struct xnvfile_regular_iterator *it, void *data)
{
struct vfile_device_data *priv = xnvfile_iterator_priv(it);
struct list_head *curr = data;
struct rtdm_device *device;
char pnum[32];
device = list_entry(curr, struct rtdm_device, reserved.entry);
snprintf(pnum, sizeof(pnum), "%u:%u",
device->protocol_family, device->socket_type);
xnvfile_printf(it, "%02X\t%-31s\t%-15s\t%s\n",
priv->h,
pnum, device->driver_name,
device->proc_name);
return 0;
}
static struct xnvfile_regular_ops proto_vfile_ops = {
.begin = proto_begin,
.next = next_dev,
.show = proto_show,
};
static struct xnvfile_regular proto_vfile = {
.privsz = sizeof(struct vfile_device_data),
.ops = &proto_vfile_ops,
.entry = { .lockops = &lockops }
};
static void *openfd_begin(struct xnvfile_regular_iterator *it)
{
if (it->pos == 0)
return VFILE_SEQ_START;
return it->pos <= RTDM_FD_MAX ? it : NULL;
}
static void *openfd_next(struct xnvfile_regular_iterator *it)
{
if (it->pos > RTDM_FD_MAX)
return NULL;
return it;
}
static int openfd_show(struct xnvfile_regular_iterator *it, void *data)
{
struct rtdm_dev_context *context;
struct rtdm_device *device;
struct rtdm_process owner;
int close_lock_count, fd;
spl_t s;
if (data == NULL) {
xnvfile_puts(it, "Index\tLocked\tDevice\t\t\t\tOwner [PID]\n");
return 0;
}
fd = (int)it->pos - 1;
xnlock_get_irqsave(&rt_fildes_lock, s);
context = fildes_table[fd].context;
if (context == NULL) {
xnlock_put_irqrestore(&rt_fildes_lock, s);
return VFILE_SEQ_SKIP;
}
close_lock_count = atomic_read(&context->close_lock_count);
device = context->device;
if (context->reserved.owner)
memcpy(&owner, context->reserved.owner, sizeof(owner));
else {
strcpy(owner.name, "<kernel>");
owner.pid = -1;
}
xnlock_put_irqrestore(&rt_fildes_lock, s);
xnvfile_printf(it, "%d\t%d\t%-31s %s [%d]\n", fd,
close_lock_count,
(device->device_flags & RTDM_NAMED_DEVICE) ?
device->device_name : device->proc_name,
owner.name, owner.pid);
return 0;
}
static ssize_t openfd_store(struct xnvfile_input *input)
{
ssize_t ret, cret;
long val;
ret = xnvfile_get_integer(input, &val);
if (ret < 0)
return ret;
cret = __rt_dev_close(current, (int)val);
if (cret < 0)
return cret;
return ret;
}
static struct xnvfile_regular_ops openfd_vfile_ops = {
.begin = openfd_begin,
.next = openfd_next,
.show = openfd_show,
.store = openfd_store,
};
static struct xnvfile_regular openfd_vfile = {
.ops = &openfd_vfile_ops,
.entry = { .lockops = &lockops }
};
static int allfd_vfile_show(struct xnvfile_regular_iterator *it, void *data)
{
xnvfile_printf(it, "total=%d:open=%d:free=%d\n", RTDM_FD_MAX,
open_fildes, RTDM_FD_MAX - open_fildes);
return 0;
}
static struct xnvfile_regular_ops allfd_vfile_ops = {
.show = allfd_vfile_show,
};
static struct xnvfile_regular allfd_vfile = {
.ops = &allfd_vfile_ops,
};
static int devinfo_vfile_show(struct xnvfile_regular_iterator *it, void *data)
{
struct rtdm_device *device;
int i;
if (down_interruptible(&nrt_dev_lock))
return -ERESTARTSYS;
/*
* As the device may have disappeared while the handler was called,
* first match the pointer against registered devices.
*/
for (i = 0; i < devname_hashtab_size; i++)
list_for_each_entry(device, &rtdm_named_devices[i],
reserved.entry)
if (device == xnvfile_priv(it->vfile))
goto found;
for (i = 0; i < protocol_hashtab_size; i++)
list_for_each_entry(device, &rtdm_protocol_devices[i],
reserved.entry)
if (device == xnvfile_priv(it->vfile))
goto found;
up(&nrt_dev_lock);
return -ENODEV;
found:
xnvfile_printf(it, "driver:\t\t%s\nversion:\t%d.%d.%d\n",
device->driver_name,
RTDM_DRIVER_MAJOR_VER(device->driver_version),
RTDM_DRIVER_MINOR_VER(device->driver_version),
RTDM_DRIVER_PATCH_VER(device->driver_version));
xnvfile_printf(it, "peripheral:\t%s\nprovider:\t%s\n",
device->peripheral_name, device->provider_name);
xnvfile_printf(it, "class:\t\t%d\nsub-class:\t%d\n",
device->device_class, device->device_sub_class);
xnvfile_printf(it, "flags:\t\t%s%s%s\n",
(device->device_flags & RTDM_EXCLUSIVE) ?
"EXCLUSIVE " : "",
(device->device_flags & RTDM_NAMED_DEVICE) ?
"NAMED_DEVICE " : "",
(device->device_flags & RTDM_PROTOCOL_DEVICE) ?
"PROTOCOL_DEVICE " : "");
xnvfile_printf(it, "lock count:\t%d\n",
atomic_read(&device->reserved.refcount));
up(&nrt_dev_lock);
return 0;
}
static struct xnvfile_regular_ops devinfo_vfile_ops = {
.show = devinfo_vfile_show,
};
int rtdm_proc_register_device(struct rtdm_device *device)
{
int ret;
ret = xnvfile_init_dir(device->proc_name,
&device->vfroot, &rtdm_vfroot);
if (ret)
goto err_out;
memset(&device->info_vfile, 0, sizeof(device->info_vfile));
device->info_vfile.ops = &devinfo_vfile_ops;
ret = xnvfile_init_regular("information", &device->info_vfile,
&device->vfroot);
if (ret) {
xnvfile_destroy_dir(&device->vfroot);
goto err_out;
}
xnvfile_priv(&device->info_vfile) = device;
return 0;
err_out:
xnlogerr("RTDM: error while creating device vfile\n");
return ret;
}
void rtdm_proc_unregister_device(struct rtdm_device *device)
{
xnvfile_destroy_regular(&device->info_vfile);
xnvfile_destroy_dir(&device->vfroot);
}
int __init rtdm_proc_init(void)
{
int ret;
/* Initialise vfiles */
// ret = xnvfile_init_root(); /proc/rtai is initted elsewhere
ret = xnvfile_init_dir("rtai/rtdm", &rtdm_vfroot, &nkvfroot);
if (ret)
goto error;
ret = xnvfile_init_regular("named_devices", &named_vfile, &rtdm_vfroot);
if (ret)
goto error;
ret = xnvfile_init_regular("protocol_devices", &proto_vfile, &rtdm_vfroot);
if (ret)
goto error;
ret = xnvfile_init_regular("open_fildes", &openfd_vfile, &rtdm_vfroot);
if (ret)
goto error;
ret = xnvfile_init_regular("fildes", &allfd_vfile, &rtdm_vfroot);
if (ret)
goto error;
return 0;
error:
rtdm_proc_cleanup();
return ret;
}
void rtdm_proc_cleanup(void)
{
xnvfile_destroy_regular(&allfd_vfile);
xnvfile_destroy_regular(&openfd_vfile);
xnvfile_destroy_regular(&proto_vfile);
xnvfile_destroy_regular(&named_vfile);
xnvfile_destroy_dir(&rtdm_vfroot);
// xnvfile_destroy_root(); /proc/rtai is destroyed elsewhere
}

View file

@ -1,32 +0,0 @@
/*
* Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>.
* Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>.
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _RTDM_PROC_H
#define _RTDM_PROC_H
extern struct proc_dir_entry *rtdm_proc_root;
int rtdm_proc_register_device(struct rtdm_device* device);
int __init rtdm_proc_init(void);
void rtdm_proc_cleanup(void);
#endif /* _RTDM_PROC_H */

View file

@ -1,164 +0,0 @@
/*
* Copyright (C) 2008-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include "rtai_taskq.h"
#ifdef CONFIG_SMP
volatile unsigned long tosched_mask;
#endif
void rt_schedule_readied(void)
{
unsigned long flags;
#ifdef CONFIG_SMP
unsigned long cpumask, rmask, lmask;
flags = rt_global_save_flags_and_cli();
lmask = tosched_mask;
tosched_mask = 0;
rt_global_restore_flags(flags);
rmask = lmask & ~(cpumask = (1 << rtai_cpuid()));
if (rmask) {
rtai_save_flags_and_cli(flags);
send_sched_ipi(rmask);
rtai_restore_flags(flags);
}
if (lmask | cpumask)
#endif
{
flags = rt_global_save_flags_and_cli();
rt_schedule();
rt_global_restore_flags(flags);
}
}
EXPORT_SYMBOL(rt_schedule_readied);
void rt_taskq_init(TASKQ *taskq, unsigned long type)
{
taskq->qtype = (type & TASKQ_FIFO) ? 1 : 0;
taskq->queue = (QUEUE) { &taskq->queue, &taskq->queue, NULL };
}
EXPORT_SYMBOL(rt_taskq_init);
RT_TASK *rt_taskq_ready_one(TASKQ *taskq)
{
unsigned long flags;
RT_TASK *task = NULL;
flags = rt_global_save_flags_and_cli();
if ((task = (taskq->queue.next)->task)) {
dequeue_blocked(task);
rem_timed_task(task);
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_TASKQ | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
enq_ready_task(task);
TOSCHED_TASK(task);
}
}
rt_global_restore_flags(flags);
return task;
}
EXPORT_SYMBOL(rt_taskq_ready_one);
int rt_taskq_ready_all(TASKQ *taskq, unsigned long why)
{
unsigned long flags, tosched;
RT_TASK *task;
QUEUE *q;
tosched = 0;
q = &(taskq->queue);
flags = rt_global_save_flags_and_cli();
while ((q = q->next) != &(taskq->queue)) {
if ((task = q->task)) {
dequeue_blocked(task = q->task);
rem_timed_task(task);
task->retval = why;
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_TASKQ | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
enq_ready_task(task);
TOSCHED_TASK(task);
tosched = 1;
}
}
rt_global_restore_flags(flags);
flags = rt_global_save_flags_and_cli();
}
rt_global_restore_flags(flags);
return tosched;
}
EXPORT_SYMBOL(rt_taskq_ready_all);
void rt_taskq_wait(TASKQ *taskq)
{
RT_TASK *rt_current;
unsigned long flags;
void *retp;
flags = rt_global_save_flags_and_cli();
rt_current = RT_CURRENT;
rt_current->retval = 0;
rt_current->state |= RT_SCHED_TASKQ;
rem_ready_current(rt_current);
enqueue_blocked(rt_current, &taskq->queue, taskq->qtype);
rt_schedule();
if (unlikely((retp = rt_current->blocked_on) != NULL)) {
if (likely(retp != RTP_OBJREM)) {
dequeue_blocked(rt_current);
rt_current->retval = XNBREAK;
} else {
rt_current->prio_passed_to = NULL;
rt_current->retval = XNRMID;
}
}
rt_global_restore_flags(flags);
}
EXPORT_SYMBOL(rt_taskq_wait);
void rt_taskq_wait_until(TASKQ *taskq, RTIME time)
{
DECLARE_RT_CURRENT;
unsigned long flags;
void *retp;
REALTIME2COUNT(time);
flags = rt_global_save_flags_and_cli();
ASSIGN_RT_CURRENT;
rt_current->retval = 0;
rt_current->blocked_on = &taskq->queue;
if ((rt_current->resume_time = time) > rt_time_h) {
rt_current->state |= (RT_SCHED_TASKQ | RT_SCHED_DELAYED);
rem_ready_current(rt_current);
enqueue_blocked(rt_current, &taskq->queue, taskq->qtype);
enq_timed_task(rt_current);
rt_schedule();
}
if (unlikely((retp = rt_current->blocked_on) != NULL)) {
if (likely(retp != RTP_OBJREM)) {
dequeue_blocked(rt_current);
rt_current->retval = retp > RTP_HIGERR ? XNTIMEO : XNBREAK;
} else {
rt_current->prio_passed_to = NULL;
rt_current->retval = XNRMID;
}
}
rt_global_restore_flags(flags);
}
EXPORT_SYMBOL(rt_taskq_wait_until);

File diff suppressed because it is too large Load diff

View file

@ -1,522 +0,0 @@
/**
* @file
* Real-Time Driver Model for RTAI, serial device profile header
*
* @note Copyright (C) 2005-2007 Jan Kiszka <jan.kiszka@web.de>
*
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* RTAI is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @ingroup rtserial
*/
/*!
* @ingroup profiles
* @defgroup rtserial Serial Devices
*
* This is the common interface a RTDM-compliant serial device has to provide.
* Feel free to comment on this profile via the RTAI mailing list
* (rtai@rtai.org) or directly to the author (jan.kiszka@web.de).
*
* @b Profile @b Revision: 3
* @n
* @n
* @par Device Characteristics
* @ref rtdm_device.device_flags "Device Flags": @c RTDM_NAMED_DEVICE, @c RTDM_EXCLUSIVE @n
* @n
* @ref rtdm_device.device_name "Device Name": @c "rtser<N>", N >= 0 @n
* @n
* @ref rtdm_device.device_class "Device Class": @c RTDM_CLASS_SERIAL @n
* @n
*
* @par Supported Operations
* @b Open @n
* Environments: non-RT (RT optional, deprecated)@n
* Specific return values: none @n
* @n
* @b Close @n
* Environments: non-RT (RT optional, deprecated)@n
* Specific return values: none @n
* @n
* @b IOCTL @n
* Mandatory Environments: see @ref SERIOCTLs "below" @n
* Specific return values: see @ref SERIOCTLs "below" @n
* @n
* @b Read @n
* Environments: RT (non-RT optional)@n
* Specific return values:
* - -ETIMEDOUT
* - -EINTR (interrupted explicitly or by signal)
* - -EAGAIN (no data available in non-blocking mode)
* - -EBADF (device has been closed while reading)
* - -EIO (hardware error or broken bit stream)
* .
* @n
* @b Write @n
* Environments: RT (non-RT optional)@n
* Specific return values:
* - -ETIMEDOUT
* - -EINTR (interrupted explicitly or by signal)
* - -EAGAIN (no data written in non-blocking mode)
* - -EBADF (device has been closed while writing)
*
* @{
*/
#ifndef _RTSERIAL_H
#define _RTSERIAL_H
#include <rtdm/rtdm.h>
#define RTSER_PROFILE_VER 3
/*!
* @anchor RTSER_DEF_BAUD @name RTSER_DEF_BAUD
* Default baud rate
* @{ */
#define RTSER_DEF_BAUD 9600
/** @} */
/*!
* @anchor RTSER_xxx_PARITY @name RTSER_xxx_PARITY
* Number of parity bits
* @{ */
#define RTSER_NO_PARITY 0x00
#define RTSER_ODD_PARITY 0x01
#define RTSER_EVEN_PARITY 0x03
#define RTSER_DEF_PARITY RTSER_NO_PARITY
/** @} */
/*!
* @anchor RTSER_xxx_BITS @name RTSER_xxx_BITS
* Number of data bits
* @{ */
#define RTSER_5_BITS 0x00
#define RTSER_6_BITS 0x01
#define RTSER_7_BITS 0x02
#define RTSER_8_BITS 0x03
#define RTSER_DEF_BITS RTSER_8_BITS
/** @} */
/*!
* @anchor RTSER_xxx_STOPB @name RTSER_xxx_STOPB
* Number of stop bits
* @{ */
#define RTSER_1_STOPB 0x00
/** valid only in combination with 5 data bits */
#define RTSER_1_5_STOPB 0x01
#define RTSER_2_STOPB 0x01
#define RTSER_DEF_STOPB RTSER_1_STOPB
/** @} */
/*!
* @anchor RTSER_xxx_HAND @name RTSER_xxx_HAND
* Handshake mechanisms
* @{ */
#define RTSER_NO_HAND 0x00
#define RTSER_RTSCTS_HAND 0x01
#define RTSER_DEF_HAND RTSER_NO_HAND
/** @} */
/*!
* @anchor RTSER_RS485_xxx @name RTSER_RS485_xxx
* RS485 mode with automatic RTS handling
* @{ */
#define RTSER_RS485_DISABLE 0x00
#define RTSER_RS485_ENABLE 0x01
#define RTSER_DEF_RS485 RTSER_RS485_DISABLE
/** @} */
/*!
* @anchor RTSER_FIFO_xxx @name RTSER_FIFO_xxx
* Reception FIFO interrupt threshold
* @{ */
#define RTSER_FIFO_DEPTH_1 0x00
#define RTSER_FIFO_DEPTH_4 0x40
#define RTSER_FIFO_DEPTH_8 0x80
#define RTSER_FIFO_DEPTH_14 0xC0
#define RTSER_DEF_FIFO_DEPTH RTSER_FIFO_DEPTH_1
/** @} */
/*!
* @anchor RTSER_TIMEOUT_xxx @name RTSER_TIMEOUT_xxx
* Special timeout values, see also @ref RTDM_TIMEOUT_xxx
* @{ */
#define RTSER_TIMEOUT_INFINITE RTDM_TIMEOUT_INFINITE
#define RTSER_TIMEOUT_NONE RTDM_TIMEOUT_NONE
#define RTSER_DEF_TIMEOUT RTDM_TIMEOUT_INFINITE
/** @} */
/*!
* @anchor RTSER_xxx_TIMESTAMP_HISTORY @name RTSER_xxx_TIMESTAMP_HISTORY
* Timestamp history control
* @{ */
#define RTSER_RX_TIMESTAMP_HISTORY 0x01
#define RTSER_DEF_TIMESTAMP_HISTORY 0x00
/** @} */
/*!
* @anchor RTSER_EVENT_xxx @name RTSER_EVENT_xxx
* Events bits
* @{ */
#define RTSER_EVENT_RXPEND 0x01
#define RTSER_EVENT_ERRPEND 0x02
#define RTSER_EVENT_MODEMHI 0x04
#define RTSER_EVENT_MODEMLO 0x08
#define RTSER_EVENT_TXEMPTY 0x10
#define RTSER_DEF_EVENT_MASK 0x00
/** @} */
/*!
* @anchor RTSER_SET_xxx @name RTSER_SET_xxx
* Configuration mask bits
* @{ */
#define RTSER_SET_BAUD 0x0001
#define RTSER_SET_PARITY 0x0002
#define RTSER_SET_DATA_BITS 0x0004
#define RTSER_SET_STOP_BITS 0x0008
#define RTSER_SET_HANDSHAKE 0x0010
#define RTSER_SET_FIFO_DEPTH 0x0020
#define RTSER_SET_TIMEOUT_RX 0x0100
#define RTSER_SET_TIMEOUT_TX 0x0200
#define RTSER_SET_TIMEOUT_EVENT 0x0400
#define RTSER_SET_TIMESTAMP_HISTORY 0x0800
#define RTSER_SET_EVENT_MASK 0x1000
#define RTSER_SET_RS485 0x2000
/** @} */
/*!
* @anchor RTSER_LSR_xxx @name RTSER_LSR_xxx
* Line status bits
* @{ */
#define RTSER_LSR_DATA 0x01
#define RTSER_LSR_OVERRUN_ERR 0x02
#define RTSER_LSR_PARITY_ERR 0x04
#define RTSER_LSR_FRAMING_ERR 0x08
#define RTSER_LSR_BREAK_IND 0x10
#define RTSER_LSR_THR_EMTPY 0x20
#define RTSER_LSR_TRANSM_EMPTY 0x40
#define RTSER_LSR_FIFO_ERR 0x80
#define RTSER_SOFT_OVERRUN_ERR 0x0100
/** @} */
/*!
* @anchor RTSER_MSR_xxx @name RTSER_MSR_xxx
* Modem status bits
* @{ */
#define RTSER_MSR_DCTS 0x01
#define RTSER_MSR_DDSR 0x02
#define RTSER_MSR_TERI 0x04
#define RTSER_MSR_DDCD 0x08
#define RTSER_MSR_CTS 0x10
#define RTSER_MSR_DSR 0x20
#define RTSER_MSR_RI 0x40
#define RTSER_MSR_DCD 0x80
/** @} */
/*!
* @anchor RTSER_MCR_xxx @name RTSER_MCR_xxx
* Modem control bits
* @{ */
#define RTSER_MCR_DTR 0x01
#define RTSER_MCR_RTS 0x02
#define RTSER_MCR_OUT1 0x04
#define RTSER_MCR_OUT2 0x08
#define RTSER_MCR_LOOP 0x10
/** @} */
/*!
* @anchor RTSER_BREAK_xxx @name RTSER_BREAK_xxx
* Break control
* @{ */
#define RTSER_BREAK_CLR 0x00
#define RTSER_BREAK_SET 0x01
/**
* Serial device configuration
*/
typedef struct rtser_config {
/** mask specifying valid fields, see @ref RTSER_SET_xxx */
int config_mask;
/** baud rate, default @ref RTSER_DEF_BAUD */
int baud_rate;
/** number of parity bits, see @ref RTSER_xxx_PARITY */
int parity;
/** number of data bits, see @ref RTSER_xxx_BITS */
int data_bits;
/** number of stop bits, see @ref RTSER_xxx_STOPB */
int stop_bits;
/** handshake mechanisms, see @ref RTSER_xxx_HAND */
int handshake;
/** reception FIFO interrupt threshold, see @ref RTSER_FIFO_xxx */
int fifo_depth;
int reserved;
/** reception timeout, see @ref RTSER_TIMEOUT_xxx for special
* values */
nanosecs_rel_t rx_timeout;
/** transmission timeout, see @ref RTSER_TIMEOUT_xxx for special
* values */
nanosecs_rel_t tx_timeout;
/** event timeout, see @ref RTSER_TIMEOUT_xxx for special values */
nanosecs_rel_t event_timeout;
/** enable timestamp history, see @ref RTSER_xxx_TIMESTAMP_HISTORY */
int timestamp_history;
/** event mask to be used with @ref RTSER_RTIOC_WAIT_EVENT, see
* @ref RTSER_EVENT_xxx */
int event_mask;
/** enable RS485 mode, see @ref RTSER_RS485_xxx */
int rs485;
} rtser_config_t;
/**
* Serial device status
*/
typedef struct rtser_status {
/** line status register, see @ref RTSER_LSR_xxx */
int line_status;
/** modem status register, see @ref RTSER_MSR_xxx */
int modem_status;
} rtser_status_t;
/**
* Additional information about serial device events
*/
typedef struct rtser_event {
/** signalled events, see @ref RTSER_EVENT_xxx */
int events;
/** number of pending input characters */
int rx_pending;
/** last interrupt timestamp */
nanosecs_abs_t last_timestamp;
/** reception timestamp of oldest character in input queue */
nanosecs_abs_t rxpend_timestamp;
} rtser_event_t;
#define RTIOC_TYPE_SERIAL RTDM_CLASS_SERIAL
/*!
* @name Sub-Classes of RTDM_CLASS_SERIAL
* @{ */
#define RTDM_SUBCLASS_16550A 0
/** @} */
/*!
* @anchor SERIOCTLs @name IOCTLs
* Serial device IOCTLs
* @{ */
/**
* Get serial device configuration
*
* @param[out] arg Pointer to configuration buffer (struct rtser_config)
*
* @return 0 on success, otherwise negative error code
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
* - Kernel-based task
* - User-space task (RT, non-RT)
*
* Rescheduling: never.
*/
#define RTSER_RTIOC_GET_CONFIG \
_IOR(RTIOC_TYPE_SERIAL, 0x00, struct rtser_config)
/**
* Set serial device configuration
*
* @param[in] arg Pointer to configuration buffer (struct rtser_config)
*
* @return 0 on success, otherwise:
*
* - -EPERM is returned if the caller's context is invalid, see note below.
*
* - -ENOMEM is returned if a new history buffer for timestamps cannot be
* allocated.
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
* - Kernel-based task
* - User-space task (RT, non-RT)
*
* @note If rtser_config contains a valid timestamp_history and the
* addressed device has been opened in non-real-time context, this IOCTL must
* be issued in non-real-time context as well. Otherwise, this command will
* fail.
*
* Rescheduling: never.
*/
#define RTSER_RTIOC_SET_CONFIG \
_IOW(RTIOC_TYPE_SERIAL, 0x01, struct rtser_config)
/**
* Get serial device status
*
* @param[out] arg Pointer to status buffer (struct rtser_status)
*
* @return 0 on success, otherwise negative error code
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
* - Kernel-based task
* - User-space task (RT, non-RT)
*
* @note The error states @c RTSER_LSR_OVERRUN_ERR, @c RTSER_LSR_PARITY_ERR,
* @c RTSER_LSR_FRAMING_ERR, and @c RTSER_SOFT_OVERRUN_ERR that may have
* occured during previous read accesses to the device will be saved for being
* reported via this IOCTL. Upon return from @c RTSER_RTIOC_GET_STATUS, the
* saved state will be cleared.
*
* Rescheduling: never.
*/
#define RTSER_RTIOC_GET_STATUS \
_IOR(RTIOC_TYPE_SERIAL, 0x02, struct rtser_status)
/**
* Get serial device's modem contol register
*
* @param[out] arg Pointer to variable receiving the content (int, see
* @ref RTSER_MCR_xxx)
*
* @return 0 on success, otherwise negative error code
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
* - Kernel-based task
* - User-space task (RT, non-RT)
*
* Rescheduling: never.
*/
#define RTSER_RTIOC_GET_CONTROL \
_IOR(RTIOC_TYPE_SERIAL, 0x03, int)
/**
* Set serial device's modem contol register
*
* @param[in] arg New control register content (int, see @ref RTSER_MCR_xxx)
*
* @return 0 on success, otherwise negative error code
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
* - Kernel-based task
* - User-space task (RT, non-RT)
*
* Rescheduling: never.
*/
#define RTSER_RTIOC_SET_CONTROL \
_IOW(RTIOC_TYPE_SERIAL, 0x04, int)
/**
* Wait on serial device events according to previously set mask
*
* @param[out] arg Pointer to event information buffer (struct rtser_event)
*
* @return 0 on success, otherwise:
*
* - -EBUSY is returned if another task is already waiting on events of this
* device.
*
* - -EBADF is returned if the file descriptor is invalid or the device has
* just been closed.
*
* Environments:
*
* This service can be called from:
*
* - Kernel-based task
* - User-space task (RT)
*
* Rescheduling: possible.
*/
#define RTSER_RTIOC_WAIT_EVENT \
_IOR(RTIOC_TYPE_SERIAL, 0x05, struct rtser_event)
/** @} */
/**
* Set or clear break on UART output line
*
* @param[in] arg @c RTSER_BREAK_SET or @c RTSER_BREAK_CLR (int)
*
* @return 0 on success, otherwise negative error code
*
* Environments:
*
* This service can be called from:
*
* - Kernel module initialization/cleanup code
* - Kernel-based task
* - User-space task (RT, non-RT)
*
* @note A set break condition may also be cleared on UART line
* reconfiguration.
*
* Rescheduling: never.
*/
#define RTSER_RTIOC_BREAK_CTL \
_IOR(RTIOC_TYPE_SERIAL, 0x06, int)
/** @} */
/*!
* @anchor SERutils @name RT Serial example and utility programs
* @{ */
/** @example cross-link.c */
/** @} */
/** @} */
#endif /* _RTSERIAL_H */

View file

@ -1,466 +0,0 @@
/*!\file select.c
* \brief file descriptors events multiplexing.
* \author Gilles Chanteperdrix
*
* Copyright (C) 2008 Efixo <gilles.chanteperdrix@laposte.net>
*
* with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* RTAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* RTAI is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RTAI; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* \ingroup select
*/
/*!
* \ingroup nucleus
* \defgroup select File descriptors events multiplexing services.
*
* File descriptors events multiplexing services.
*
* This module implements the services needed for implementing the posix
* "select" service, or any other events multiplexing services.
*
* Following the implementation of the posix select service, this module defines
* three types of events:
* - \a XNSELECT_READ meaning that a file descriptor is ready for reading;
* - \a XNSELECT_WRITE meaning that a file descriptor is ready for writing;
* - \a XNSELECT_EXCEPT meaning that a file descriptor received an exceptional
* event.
*
* It works by defining two structures:
* - a @a struct @a xnselect structure, which should be added to every file
* descriptor for every event type (read, write, or except);
* - a @a struct @a xnselector structure, the selection structure, passed by
* the thread calling the xnselect service, where this service does all its
* housekeeping.
*@{*/
#include "select.h"
#ifdef CONFIG_RTAI_RTDM_SELECT
#include <linux/types.h>
#include <linux/bitops.h> /* For hweight_long */
static xnqueue_t xnselectors;
static int xnselect_apc;
#define link2binding(baddr, memb) \
container_of(baddr, struct xnselect_binding, memb)
/**
* Initialize a @a struct @a xnselect structure.
*
* This service must be called to initialize a @a struct @a xnselect structure
* before it is bound to a selector by the means of xnselect_bind().
*
* @param select_block pointer to the xnselect structure to be initialized
*/
void xnselect_init(struct xnselect *select_block)
{
initq(&select_block->bindings);
}
EXPORT_SYMBOL_GPL(xnselect_init);
static inline int xnselect_wakeup(struct xnselector *selector)
{
return xnsynch_flush(&selector->synchbase, 0) == XNSYNCH_RESCHED;
}
/**
* Bind a file descriptor (represented by its @a xnselect structure) to a
* selector block.
*
* @param select_block pointer to the @a struct @a xnselect to be bound;
*
* @param binding pointer to a newly allocated (using xnmalloc) @a struct
* @a xnselect_binding;
*
* @param selector pointer to the selector structure;
*
* @param type type of events (@a XNSELECT_READ, @a XNSELECT_WRITE, or @a
* XNSELECT_EXCEPT);
*
* @param index index of the file descriptor (represented by @a select_block) in the bit fields used by the @a selector structure;
*
* @param state current state of the file descriptor>.
*
* @a select_block must have been initialized with xnselect_init(),
* the @a xnselector structure must have been initialized with
* xnselector_init(), @a binding may be uninitialized.
*
* This service must be called with nklock locked, irqs off. For this reason,
* the @a binding parameter must have been allocated by the caller outside the
* locking section.
*
* @retval -EINVAL if @a type or @a index is invalid;
* @retval 0 otherwise.
*/
int xnselect_bind(struct xnselect *select_block,
struct xnselect_binding *binding,
struct xnselector *selector,
unsigned type,
unsigned index,
unsigned state)
{
if (type >= XNSELECT_MAX_TYPES || index > __FD_SETSIZE)
return -EINVAL;
binding->selector = selector;
binding->fd = select_block;
binding->type = type;
binding->bit_index = index;
inith(&binding->link);
inith(&binding->slink);
appendq(&selector->bindings, &binding->slink);
appendq(&select_block->bindings, &binding->link);
__FD_SET__(index, &selector->fds[type].expected);
if (state) {
__FD_SET__(index, &selector->fds[type].pending);
if (xnselect_wakeup(selector))
xnpod_schedule();
} else
__FD_CLR__(index, &selector->fds[type].pending);
return 0;
}
EXPORT_SYMBOL_GPL(xnselect_bind);
/* Must be called with nklock locked irqs off */
int __xnselect_signal(struct xnselect *select_block, unsigned state)
{
xnholder_t *holder;
int resched;
for(resched = 0, holder = getheadq(&select_block->bindings);
holder; holder = nextq(&select_block->bindings, holder)) {
struct xnselect_binding *binding;
struct xnselector *selector;
binding = link2binding(holder, link);
selector = binding->selector;
if (state) {
if (!__FD_ISSET__(binding->bit_index,
&selector->fds[binding->type].pending)) {
__FD_SET__(binding->bit_index,
&selector->fds[binding->type].pending);
if (xnselect_wakeup(selector))
resched = 1;
}
} else
__FD_CLR__(binding->bit_index,
&selector->fds[binding->type].pending);
}
return resched;
}
EXPORT_SYMBOL_GPL(__xnselect_signal);
/**
* Destroy the @a xnselect structure associated with a file descriptor.
*
* Any binding with a @a xnselector block is destroyed.
*
* @param select_block pointer to the @a xnselect structure associated with a file descriptor
*/
void xnselect_destroy(struct xnselect *select_block)
{
xnholder_t *holder;
int resched = 0;
spl_t s;
xnlock_get_irqsave(&nklock, s);
while ((holder = getq(&select_block->bindings))) {
struct xnselect_binding *binding;
struct xnselector *selector;
binding = link2binding(holder, link);
selector = binding->selector;
__FD_CLR__(binding->bit_index,
&selector->fds[binding->type].expected);
if (!__FD_ISSET__(binding->bit_index,
&selector->fds[binding->type].pending)) {
__FD_SET__(binding->bit_index,
&selector->fds[binding->type].pending);
if (xnselect_wakeup(selector))
resched = 1;
}
removeq(&selector->bindings, &binding->slink);
xnlock_put_irqrestore(&nklock, s);
xnfree(binding);
xnlock_get_irqsave(&nklock, s);
}
if (resched)
xnpod_schedule();
xnlock_put_irqrestore(&nklock, s);
}
EXPORT_SYMBOL_GPL(xnselect_destroy);
static unsigned
fd_set_andnot(fd_set *result, fd_set *first, fd_set *second, unsigned n)
{
unsigned i, not_empty = 0;
for (i = 0; i < __FDELT__(n); i++)
if((result->fds_bits[i] =
first->fds_bits[i] & ~(second->fds_bits[i])))
not_empty = 1;
if (i < __FDSET_LONGS__
&& (result->fds_bits[i] =
first->fds_bits[i] & ~(second->fds_bits[i]) & (__FDMASK__(n) - 1)))
not_empty = 1;
return not_empty;
}
static unsigned
fd_set_and(fd_set *result, fd_set *first, fd_set *second, unsigned n)
{
unsigned i, not_empty = 0;
for (i = 0; i < __FDELT__(n); i++)
if((result->fds_bits[i] =
first->fds_bits[i] & second->fds_bits[i]))
not_empty = 1;
if (i < __FDSET_LONGS__
&& (result->fds_bits[i] =
first->fds_bits[i] & second->fds_bits[i] & (__FDMASK__(n) - 1)))
not_empty = 1;
return not_empty;
}
static void fd_set_zeropad(fd_set *set, unsigned n)
{
unsigned i;
i = __FDELT__(n);
if (i < __FDSET_LONGS__)
set->fds_bits[i] &= (__FDMASK__(n) - 1);
for(i++; i < __FDSET_LONGS__; i++)
set->fds_bits[i] = 0;
}
static unsigned fd_set_popcount(fd_set *set, unsigned n)
{
unsigned count = 0, i;
for (i = 0; i < __FDELT__(n); i++)
if (set->fds_bits[i])
count += hweight_long(set->fds_bits[i]);
if (i < __FDSET_LONGS__ && (set->fds_bits[i] & (__FDMASK__(n) - 1)))
count += hweight_long(set->fds_bits[i] & (__FDMASK__(n) - 1));
return count;
}
/**
* Initialize a selector structure.
*
* @param selector The selector structure to be initialized.
*
* @retval 0
*/
int xnselector_init(struct xnselector *selector)
{
unsigned i;
xnsynch_init(&selector->synchbase, XNSYNCH_FIFO, NULL);
for (i = 0; i < XNSELECT_MAX_TYPES; i++) {
__FD_ZERO__(&selector->fds[i].expected);
__FD_ZERO__(&selector->fds[i].pending);
}
initq(&selector->bindings);
return 0;
}
EXPORT_SYMBOL_GPL(xnselector_init);
/**
* Check the state of a number of file descriptors, wait for a state change if
* no descriptor is ready.
*
* @param selector structure to check for pending events
* @param out_fds The set of descriptors with pending events if a strictly positive number is returned, or the set of descriptors not yet bound if -ECHRNG is returned;
* @param in_fds the set of descriptors which events should be checked
* @param nfds the highest-numbered descriptor in any of the @a in_fds sets, plus 1;
* @param timeout the timeout, whose meaning depends on @a timeout_mode, note
* that xnselect() pass @a timeout and @a timeout_mode unchanged to
* xnsynch_sleep_on, so passing a relative value different from XN_INFINITE as a
* timeout with @a timeout_mode set to XN_RELATIVE, will cause a longer sleep
* than expected if the sleep is interrupted.
* @param timeout_mode the mode of @a timeout.
*
* @retval -EINVAL if @a nfds is negative;
* @retval -ECHRNG if some of the descriptors passed in @a in_fds have not yet
* been registered with xnselect_bind(), @a out_fds contains the set of such
* descriptors;
* @retval -EINTR if @a xnselect was interrupted while waiting;
* @retval 0 in case of timeout.
* @retval the number of file descriptors having received an event.
*/
int xnselect(struct xnselector *selector,
fd_set *out_fds[XNSELECT_MAX_TYPES],
fd_set *in_fds[XNSELECT_MAX_TYPES],
int nfds,
xnticks_t timeout, xntmode_t timeout_mode)
{
unsigned i, not_empty = 0;
xnthread_t *thread;
spl_t s;
if ((unsigned) nfds > __FD_SETSIZE)
return -EINVAL;
thread = xnpod_current_thread();
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
if (out_fds[i])
fd_set_zeropad(out_fds[i], nfds);
xnlock_get_irqsave(&nklock, s);
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
if (out_fds[i]
&& fd_set_andnot(out_fds[i], in_fds[i],
&selector->fds[i].expected, nfds))
not_empty = 1;
xnlock_put_irqrestore(&nklock, s);
if (not_empty)
return -ECHRNG;
xnlock_get_irqsave(&nklock, s);
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
if (out_fds[i]
&& fd_set_and(out_fds[i], in_fds[i],
&selector->fds[i].pending, nfds))
not_empty = 1;
while (!not_empty) {
xnsynch_sleep_on(&selector->synchbase, timeout, timeout_mode);
for (i = 0; i < XNSELECT_MAX_TYPES; i++)
if (out_fds[i]
&& fd_set_and(out_fds[i], in_fds[i],
&selector->fds[i].pending, nfds))
not_empty = 1;
if (xnthread_test_info(thread, XNBREAK | XNTIMEO))
break;
}
xnlock_put_irqrestore(&nklock, s);
if (not_empty) {
unsigned count;
for (count = 0, i = 0; i < XNSELECT_MAX_TYPES; i++)
if (out_fds[i])
count += fd_set_popcount(out_fds[i], nfds);
return count;
}
if (xnthread_test_info(thread, XNBREAK))
return -EINTR;
return 0; /* Timeout */
}
EXPORT_SYMBOL_GPL(xnselect);
/**
* Destroy a selector block.
*
* All bindings with file descriptor are destroyed.
*
* @param selector the selector block to be destroyed
*/
void xnselector_destroy(struct xnselector *selector)
{
spl_t s;
inith(&selector->destroy_link);
xnlock_get_irqsave(&nklock, s);
appendq(&xnselectors, &selector->destroy_link);
xnlock_put_irqrestore(&nklock, s);
rthal_apc_schedule(xnselect_apc);
}
EXPORT_SYMBOL_GPL(xnselector_destroy);
static void xnselector_destroy_loop(void *cookie)
{
struct xnselector *selector;
xnholder_t *holder;
int resched;
spl_t s;
xnlock_get_irqsave(&nklock, s);
while ((holder = getq(&xnselectors))) {
selector = container_of(holder, struct xnselector, destroy_link);
while ((holder = getq(&selector->bindings))) {
struct xnselect_binding *binding;
struct xnselect *fd;
binding = link2binding(holder, slink);
fd = binding->fd;
removeq(&fd->bindings, &binding->link);
xnlock_put_irqrestore(&nklock, s);
xnfree(binding);
xnlock_get_irqsave(&nklock, s);
}
resched =
xnsynch_destroy(&selector->synchbase) == XNSYNCH_RESCHED;
xnlock_put_irqrestore(&nklock, s);
xnfree(selector);
if (resched)
xnpod_schedule();
xnlock_get_irqsave(&nklock, s);
}
xnlock_put_irqrestore(&nklock, s);
}
int xnselect_mount(void)
{
initq(&xnselectors);
xnselect_apc = rthal_apc_alloc("xnselectors_destroy",
xnselector_destroy_loop, NULL);
if (xnselect_apc < 0)
return xnselect_apc;
return 0;
}
int xnselect_umount(void)
{
rthal_apc_free(xnselect_apc);
return 0;
}
#endif
/*@}*/

View file

@ -1,970 +0,0 @@
/**
* @file
* This file is part of the Xenomai project.
*
* @note Copyright (C) 2010 Philippe Gerum <rpm@xenomai.org>
*
* adapted to RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*!
* @ingroup nucleus
* @defgroup vfile Virtual file services
*
* Virtual files provide a mean to export RTAI object states to
* user-space, based on common kernel interfaces. This encapsulation
* is aimed at:
*
* - supporting consistent collection of very large record-based
* output, without encurring latency peaks for undergoing real-time
* activities.
*
* - in the future, hiding discrepancies between linux kernel
* releases, regarding the proper way to export kernel object states
* to userland, either via the /proc interface or by any other mean.
*
* This virtual file implementation offers record-based read support
* based on seq_files, single-buffer write support, directory and link
* handling, all visible from the /proc namespace.
*
* The vfile support exposes four filesystem object types:
*
* - snapshot-driven file (struct xnvfile_snapshot). This is commonly
* used to export real-time object states via the /proc filesystem. To
* minimize the latency involved in protecting the vfile routines from
* changes applied by real-time code on such objects, a snapshot of
* the data to output is first taken under proper locking, before the
* collected data is formatted and sent out in a lockless manner.
*
* Because a large number of records may have to be output, the data
* collection phase is not strictly atomic as a whole, but only
* protected at record level. The vfile implementation can be notified
* of updates to the underlying data set, and restart the collection
* from scratch until the snapshot is fully consistent.
*
* - regular sequential file (struct xnvfile_regular). This is
* basically an encapsulated sequential file object as available from
* the host kernel (i.e. seq_file), with a few additional features to
* make it more handy in an RTAI environment, like implicit locking
* support and shortened declaration for simplest, single-record
* output.
*
* - virtual link (struct xnvfile_link). This is a symbolic link
* feature integrated with the vfile semantics. The link target is
* computed dynamically at creation time from a user-given helper
* routine.
*
* - virtual directory (struct xnvfile_directory). A directory object,
* which can be used to create a hierarchy for ordering a set of vfile
* objects.
*
*@{*/
#include <stdarg.h>
#include <linux/ctype.h>
#include <rtdm/vfile.h>
/**
* @var struct xnvfile_directory nkvfroot
* @brief RTAI vfile root directory
*
* This vdir maps the /proc/rtai directory. It can be used to
* create a hierarchy of RTAI-related vfiles under this root.
*/
struct xnvfile_directory nkvfroot;
EXPORT_SYMBOL_GPL(nkvfroot);
static struct xnvfile_directory sysroot;
static void *vfile_snapshot_start(struct seq_file *seq, loff_t *offp)
{
struct xnvfile_snapshot_iterator *it = seq->private;
loff_t pos = *offp;
if (pos > it->nrdata)
return NULL;
if (pos == 0)
return SEQ_START_TOKEN;
return it->databuf + (pos - 1) * it->vfile->datasz;
}
static void *vfile_snapshot_next(struct seq_file *seq, void *v, loff_t *offp)
{
struct xnvfile_snapshot_iterator *it = seq->private;
loff_t pos = *offp;
if (pos >= it->nrdata)
return NULL;
++*offp;
return it->databuf + pos * it->vfile->datasz;
}
static void vfile_snapshot_stop(struct seq_file *seq, void *v)
{
}
static int vfile_snapshot_show(struct seq_file *seq, void *v)
{
struct xnvfile_snapshot_iterator *it = seq->private;
void *data = v == SEQ_START_TOKEN ? NULL : v;
int ret;
ret = it->vfile->ops->show(it, data);
return ret == VFILE_SEQ_SKIP ? SEQ_SKIP : ret;
}
static struct seq_operations vfile_snapshot_ops = {
.start = vfile_snapshot_start,
.next = vfile_snapshot_next,
.stop = vfile_snapshot_stop,
.show = vfile_snapshot_show
};
static void vfile_snapshot_free(struct xnvfile_snapshot_iterator *it, void *buf)
{
kfree(buf);
}
static int vfile_snapshot_open(struct inode *inode, struct file *file)
{
struct xnvfile_snapshot *vfile = PDE_DATA(inode);
struct xnvfile_snapshot_ops *ops = vfile->ops;
struct xnvfile_snapshot_iterator *it;
int revtag, ret, nrdata;
struct seq_file *seq;
caddr_t data;
if ((file->f_mode & FMODE_WRITE) != 0 && ops->store == NULL)
return -EACCES;
/*
* Make sure to create the seq_file backend only when reading
* from the v-file is possible.
*/
if ((file->f_mode & FMODE_READ) == 0) {
file->private_data = NULL;
return 0;
}
if ((file->f_flags & O_EXCL) != 0 && xnvfile_nref(vfile) > 0)
return -EBUSY;
it = kzalloc(sizeof(*it) + vfile->privsz, GFP_KERNEL);
if (it == NULL)
return -ENOMEM;
it->vfile = vfile;
xnvfile_file(vfile) = file;
ret = vfile->entry.lockops->get(&vfile->entry);
if (ret)
goto fail;
redo:
/*
* The ->rewind() method is optional; there may be cases where
* we don't have to take an atomic snapshot of the v-file
* contents before proceeding. In case ->rewind() detects a
* stale backend object, it can force us to bail out.
*
* If present, ->rewind() may return a strictly positive
* value, indicating how many records at most may be returned
* by ->next(). We use this hint to allocate the snapshot
* buffer, in case ->begin() is not provided. The size of this
* buffer would then be vfile->datasz * hint value.
*
* If ->begin() is given, we always expect the latter do the
* allocation for us regardless of the hint value. Otherwise,
* a NULL return from ->rewind() tells us that the vfile won't
* output any snapshot data via ->show().
*/
nrdata = 0;
if (ops->rewind) {
nrdata = ops->rewind(it);
if (nrdata < 0) {
ret = nrdata;
vfile->entry.lockops->put(&vfile->entry);
goto fail;
}
}
revtag = vfile->tag->rev;
vfile->entry.lockops->put(&vfile->entry);
/* Release the data buffer, in case we had to restart. */
if (it->databuf) {
it->endfn(it, it->databuf);
it->databuf = NULL;
}
/*
* Having no record to output is fine, in which case ->begin()
* shall return VFILE_SEQ_EMPTY if present. ->begin() may be
* absent, meaning that no allocation is even required to
* collect the records to output. NULL is kept for allocation
* errors in all other cases.
*/
if (ops->begin) {
RTAI_BUGON(NUCLEUS, ops->end == NULL);
data = ops->begin(it);
if (data == NULL) {
kfree(it);
return -ENOMEM;
}
if (data != VFILE_SEQ_EMPTY) {
it->databuf = data;
it->endfn = ops->end;
}
} else if (nrdata > 0 && vfile->datasz > 0) {
/* We have a hint for auto-allocation. */
data = kmalloc(vfile->datasz * nrdata, GFP_KERNEL);
if (data == NULL) {
kfree(it);
return -ENOMEM;
}
it->databuf = data;
it->endfn = vfile_snapshot_free;
}
ret = seq_open(file, &vfile_snapshot_ops);
if (ret)
goto fail;
it->nrdata = 0;
data = it->databuf;
if (data == NULL)
goto finish;
/*
* Take a snapshot of the vfile contents, redo if the revision
* tag of the scanned data set changed concurrently.
*/
for (;;) {
ret = vfile->entry.lockops->get(&vfile->entry);
if (ret)
break;
if (vfile->tag->rev != revtag)
goto redo;
ret = ops->next(it, data);
vfile->entry.lockops->put(&vfile->entry);
if (ret <= 0)
break;
if (ret != VFILE_SEQ_SKIP) {
data += vfile->datasz;
it->nrdata++;
}
}
if (ret < 0) {
seq_release(inode, file);
fail:
if (it->databuf)
it->endfn(it, it->databuf);
kfree(it);
return ret;
}
finish:
seq = file->private_data;
it->seq = seq;
seq->private = it;
xnvfile_nref(vfile)++;
return 0;
}
static int vfile_snapshot_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;
struct xnvfile_snapshot_iterator *it;
if (seq) {
it = seq->private;
if (it) {
--xnvfile_nref(it->vfile);
RTAI_BUGON(NUCLEUS, it->vfile->entry.refcnt < 0);
if (it->databuf)
it->endfn(it, it->databuf);
kfree(it);
}
return seq_release(inode, file);
}
return 0;
}
ssize_t vfile_snapshot_write(struct file *file, const char __user *buf,
size_t size, loff_t *ppos)
{
struct xnvfile_snapshot *vfile = PDE_DATA(wrap_f_inode(file));
struct xnvfile_input input;
ssize_t ret;
if (vfile->entry.lockops) {
ret = vfile->entry.lockops->get(&vfile->entry);
if (ret)
return ret;
}
input.u_buf = buf;
input.size = size;
input.vfile = &vfile->entry;
ret = vfile->ops->store(&input);
if (vfile->entry.lockops)
vfile->entry.lockops->put(&vfile->entry);
return ret;
}
static struct file_operations vfile_snapshot_fops = {
.owner = THIS_MODULE,
.open = vfile_snapshot_open,
.read = seq_read,
.write = vfile_snapshot_write,
.llseek = seq_lseek,
.release = vfile_snapshot_release,
};
/**
* @fn int xnvfile_init_snapshot(const char *name, struct xnvfile_snapshot *vfile, struct xnvfile_directory *parent)
* @brief Initialize a snapshot-driven vfile.
*
* @param name The name which should appear in the pseudo-filesystem,
* identifying the vfile entry.
*
* @param vfile A pointer to a vfile descriptor to initialize
* from. The following fields in this structure should be filled in
* prior to call this routine:
*
* - .privsz is the size (in bytes) of the private data area to be
* reserved in the @ref snapshot_iterator "vfile iterator". A NULL
* value indicates that no private area should be reserved.
*
* - .datasz is the size (in bytes) of a single record to be collected
* by the @ref snapshot_next "next() handler" from the @ref
* snapshot_ops "operation descriptor".
*
* - .tag is a pointer to a mandatory vfile revision tag structure
* (struct xnvfile_rev_tag). This tag will be monitored for changes by
* the vfile core while collecting data to output, so that any update
* detected will cause the current snapshot data to be dropped, and
* the collection to restart from the beginning. To this end, any
* change to the data which may be part of the collected records,
* should also invoke xnvfile_touch() on the associated tag.
*
* - entry.lockops is a pointer to a @ref vfile_lockops "locking
* descriptor", defining the lock and unlock operations for the
* vfile. This pointer may be left to NULL, in which case the
* operations on the nucleus lock (i.e. nklock) will be used
* internally around calls to data collection handlers (see @ref
* snapshot_ops "operation descriptor").
*
* - .ops is a pointer to an @ref snapshot_ops "operation descriptor".
*
* @param parent A pointer to a virtual directory descriptor; the
* vfile entry will be created into this directory. If NULL, the /proc
* root directory will be used. /proc/rtai is mapped on the
* globally available @a nkvfroot vdir.
*
* @return 0 is returned on success. Otherwise:
*
* - -ENOMEM is returned if the virtual file entry cannot be created
* in the /proc hierarchy.
*/
int xnvfile_init_snapshot(const char *name,
struct xnvfile_snapshot *vfile,
struct xnvfile_directory *parent)
{
struct proc_dir_entry *ppde, *pde;
int mode;
RTAI_BUGON(NUCLEUS, vfile->tag == NULL);
if (vfile->entry.lockops == NULL)
/* Defaults to nucleus lock */
vfile->entry.lockops = &xnvfile_nucleus_lock.ops;
if (parent == NULL)
parent = &sysroot;
mode = vfile->ops->store ? 0644 : 0444;
ppde = parent->entry.pde;
pde = proc_create_data(name, mode, ppde, &vfile_snapshot_fops, vfile);
if (pde == NULL)
return -ENOMEM;
wrap_proc_dir_entry_owner(pde);
vfile->entry.pde = pde;
return 0;
}
EXPORT_SYMBOL_GPL(xnvfile_init_snapshot);
static void *vfile_regular_start(struct seq_file *seq, loff_t *offp)
{
struct xnvfile_regular_iterator *it = seq->private;
struct xnvfile_regular *vfile = it->vfile;
int ret;
it->pos = *offp;
if (vfile->entry.lockops) {
ret = vfile->entry.lockops->get(&vfile->entry);
if (ret)
return ERR_PTR(ret);
}
/*
* If we have no begin() op, then we allow a single call only
* to ->show(), by returning the start token once. Otherwise,
* we are done.
*/
if (vfile->ops->begin == NULL)
return it->pos > 0 ? NULL : SEQ_START_TOKEN;
return vfile->ops->begin(it);
}
static void *vfile_regular_next(struct seq_file *seq, void *v, loff_t *offp)
{
struct xnvfile_regular_iterator *it = seq->private;
struct xnvfile_regular *vfile = it->vfile;
void *data;
if (vfile->ops->next == NULL)
return NULL;
it->pos = *offp + 1;
data = vfile->ops->next(it);
if (data == NULL)
return NULL;
*offp = it->pos;
return data;
}
static void vfile_regular_stop(struct seq_file *seq, void *v)
{
struct xnvfile_regular_iterator *it = seq->private;
struct xnvfile_regular *vfile = it->vfile;
if (vfile->entry.lockops)
vfile->entry.lockops->put(&vfile->entry);
if (vfile->ops->end)
vfile->ops->end(it);
}
static int vfile_regular_show(struct seq_file *seq, void *v)
{
struct xnvfile_regular_iterator *it = seq->private;
struct xnvfile_regular *vfile = it->vfile;
void *data = v == SEQ_START_TOKEN ? NULL : v;
int ret;
ret = vfile->ops->show(it, data);
return ret == VFILE_SEQ_SKIP ? SEQ_SKIP : ret;
}
static struct seq_operations vfile_regular_ops = {
.start = vfile_regular_start,
.next = vfile_regular_next,
.stop = vfile_regular_stop,
.show = vfile_regular_show
};
static int vfile_regular_open(struct inode *inode, struct file *file)
{
struct xnvfile_regular *vfile = PDE_DATA(inode);
struct xnvfile_regular_ops *ops = vfile->ops;
struct xnvfile_regular_iterator *it;
struct seq_file *seq;
int ret;
if ((file->f_flags & O_EXCL) != 0 && xnvfile_nref(vfile) > 0)
return -EBUSY;
if ((file->f_mode & FMODE_WRITE) != 0 && ops->store == NULL)
return -EACCES;
if ((file->f_mode & FMODE_READ) == 0) {
file->private_data = NULL;
return 0;
}
it = kzalloc(sizeof(*it) + vfile->privsz, GFP_KERNEL);
if (it == NULL)
return -ENOMEM;
it->vfile = vfile;
it->pos = -1;
xnvfile_file(vfile) = file;
if (ops->rewind) {
ret = ops->rewind(it);
if (ret) {
fail:
kfree(it);
return ret;
}
}
ret = seq_open(file, &vfile_regular_ops);
if (ret)
goto fail;
seq = file->private_data;
it->seq = seq;
seq->private = it;
xnvfile_nref(vfile)++;
return 0;
}
static int vfile_regular_release(struct inode *inode, struct file *file)
{
struct seq_file *seq = file->private_data;
struct xnvfile_regular_iterator *it;
if (seq) {
it = seq->private;
if (it) {
--xnvfile_nref(it->vfile);
RTAI_BUGON(NUCLEUS, xnvfile_nref(it->vfile) < 0);
kfree(it);
}
return seq_release(inode, file);
}
return 0;
}
ssize_t vfile_regular_write(struct file *file, const char __user *buf,
size_t size, loff_t *ppos)
{
struct xnvfile_regular *vfile = PDE_DATA(wrap_f_inode(file));
struct xnvfile_input input;
ssize_t ret;
if (vfile->entry.lockops) {
ret = vfile->entry.lockops->get(&vfile->entry);
if (ret)
return ret;
}
input.u_buf = buf;
input.size = size;
input.vfile = &vfile->entry;
ret = vfile->ops->store(&input);
if (vfile->entry.lockops)
vfile->entry.lockops->put(&vfile->entry);
return ret;
}
static struct file_operations vfile_regular_fops = {
.owner = THIS_MODULE,
.open = vfile_regular_open,
.read = seq_read,
.write = vfile_regular_write,
.llseek = seq_lseek,
.release = vfile_regular_release,
};
/**
* @fn int xnvfile_init_regular(const char *name, struct xnvfile_regular *vfile, struct xnvfile_directory *parent)
* @brief Initialize a regular vfile.
*
* @param name The name which should appear in the pseudo-filesystem,
* identifying the vfile entry.
*
* @param vfile A pointer to a vfile descriptor to initialize
* from. The following fields in this structure should be filled in
* prior to call this routine:
*
* - .privsz is the size (in bytes) of the private data area to be
* reserved in the @ref regular_iterator "vfile iterator". A NULL
* value indicates that no private area should be reserved.
*
* - entry.lockops is a pointer to a @ref vfile_lockops "locking
* descriptor", defining the lock and unlock operations for the
* vfile. This pointer may be left to NULL, in which case no
* locking will be applied.
*
* - .ops is a pointer to an @ref regular_ops "operation descriptor".
*
* @param parent A pointer to a virtual directory descriptor; the
* vfile entry will be created into this directory. If NULL, the /proc
* root directory will be used. /proc/rtai is mapped on the
* globally available @a nkvfroot vdir.
*
* @return 0 is returned on success. Otherwise:
*
* - -ENOMEM is returned if the virtual file entry cannot be created
* in the /proc hierarchy.
*/
int xnvfile_init_regular(const char *name,
struct xnvfile_regular *vfile,
struct xnvfile_directory *parent)
{
struct proc_dir_entry *ppde, *pde;
int mode;
if (parent == NULL)
parent = &sysroot;
mode = vfile->ops->store ? 0644 : 0444;
ppde = parent->entry.pde;
pde = proc_create_data(name, mode, ppde, &vfile_regular_fops, vfile);
if (pde == NULL)
return -ENOMEM;
wrap_proc_dir_entry_owner(pde);
vfile->entry.pde = pde;
return 0;
}
EXPORT_SYMBOL_GPL(xnvfile_init_regular);
/**
* @fn int xnvfile_init_dir(const char *name, struct xnvfile_directory *vdir, struct xnvfile_directory *parent)
* @brief Initialize a virtual directory entry.
*
* @param name The name which should appear in the pseudo-filesystem,
* identifying the vdir entry.
*
* @param vdir A pointer to the virtual directory descriptor to
* initialize.
*
* @param parent A pointer to a virtual directory descriptor standing
* for the parent directory of the new vdir. If NULL, the /proc root
* directory will be used. /proc/rtai is mapped on the globally
* available @a nkvfroot vdir.
*
* @return 0 is returned on success. Otherwise:
*
* - -ENOMEM is returned if the virtual directory entry cannot be
* created in the /proc hierarchy.
*/
int xnvfile_init_dir(const char *name,
struct xnvfile_directory *vdir,
struct xnvfile_directory *parent)
{
struct proc_dir_entry *ppde, *pde;
if (parent == NULL)
parent = &sysroot;
ppde = parent->entry.pde;
pde = proc_mkdir(name, ppde);
if (pde == NULL)
return -ENOMEM;
vdir->entry.pde = pde;
vdir->entry.lockops = NULL;
vdir->entry.private = NULL;
wrap_proc_dir_entry_owner(pde);
return 0;
}
EXPORT_SYMBOL_GPL(xnvfile_init_dir);
/**
* @fn int xnvfile_init_link(const char *from, const char *to, struct xnvfile_link *vlink, struct xnvfile_directory *parent)
* @brief Initialize a virtual link entry.
*
* @param from The name which should appear in the pseudo-filesystem,
* identifying the vlink entry.
*
* @param to The target file name which should be referred to
* symbolically by @a name.
*
* @param vlink A pointer to the virtual link descriptor to
* initialize.
*
* @param parent A pointer to a virtual directory descriptor standing
* for the parent directory of the new vlink. If NULL, the /proc root
* directory will be used. /proc/rtai is mapped on the globally
* available @a nkvfroot vdir.
*
* @return 0 is returned on success. Otherwise:
*
* - -ENOMEM is returned if the virtual link entry cannot be created
* in the /proc hierarchy.
*/
int xnvfile_init_link(const char *from,
const char *to,
struct xnvfile_link *vlink,
struct xnvfile_directory *parent)
{
struct proc_dir_entry *ppde, *pde;
if (parent == NULL)
parent = &sysroot;
ppde = parent->entry.pde;
pde = proc_symlink(from, ppde, to);
if (pde == NULL)
return -ENOMEM;
vlink->entry.pde = pde;
vlink->entry.lockops = NULL;
vlink->entry.private = NULL;
wrap_proc_dir_entry_owner(pde);
return 0;
}
EXPORT_SYMBOL_GPL(xnvfile_init_link);
/**
* @fn void xnvfile_destroy(struct xnvfile *vfile)
* @brief Removes a virtual file entry.
*
* @param vfile A pointer to the virtual file descriptor to
* remove.
*/
void xnvfile_destroy(struct xnvfile *vfile)
{
proc_remove(vfile->pde);
}
EXPORT_SYMBOL_GPL(xnvfile_destroy);
/**
* @fn ssize_t xnvfile_get_blob(struct xnvfile_input *input, void *data, size_t size)
* @brief Read in a data bulk written to the vfile.
*
* When writing to a vfile, the associated store() handler from the
* @ref snapshot_store "snapshot-driven vfile" or @ref regular_store
* "regular vfile" is called, with a single argument describing the
* input data. xnvfile_get_blob() retrieves this data as an untyped
* binary blob, and copies it back to the caller's buffer.
*
* @param input A pointer to the input descriptor passed to the
* store() handler.
*
* @param data The address of the destination buffer to copy the input
* data to.
*
* @param size The maximum number of bytes to copy to the destination
* buffer. If @a size is larger than the actual data size, the input
* is truncated to @a size.
*
* @return The number of bytes read and copied to the destination
* buffer upon success. Otherwise, a negative error code is returned:
*
* - -EFAULT indicates an invalid source buffer address.
*/
ssize_t xnvfile_get_blob(struct xnvfile_input *input,
void *data, size_t size)
{
ssize_t nbytes = input->size;
if (nbytes > size)
nbytes = size;
if (nbytes > 0 && copy_from_user(data, input->u_buf, nbytes))
return -EFAULT;
return nbytes;
}
EXPORT_SYMBOL_GPL(xnvfile_get_blob);
/**
* @fn ssize_t xnvfile_get_string(struct xnvfile_input *input, char *s, size_t maxlen)
* @brief Read in a C-string written to the vfile.
*
* When writing to a vfile, the associated store() handler from the
* @ref snapshot_store "snapshot-driven vfile" or @ref regular_store
* "regular vfile" is called, with a single argument describing the
* input data. xnvfile_get_string() retrieves this data as a
* null-terminated character string, and copies it back to the
* caller's buffer.
*
* @param input A pointer to the input descriptor passed to the
* store() handler.
*
* @param s The address of the destination string buffer to copy the
* input data to.
*
* @param maxlen The maximum number of bytes to copy to the
* destination buffer, including the ending null character. If @a
* maxlen is larger than the actual string length, the input is
* truncated to @a maxlen.
*
* @return The number of characters read and copied to the destination
* buffer upon success. Otherwise, a negative error code is returned:
*
* - -EFAULT indicates an invalid source buffer address.
*/
ssize_t xnvfile_get_string(struct xnvfile_input *input,
char *s, size_t maxlen)
{
ssize_t nbytes;
if (maxlen < 1)
return -EINVAL;
nbytes = xnvfile_get_blob(input, s, maxlen - 1);
if (nbytes < 0)
return nbytes;
if (nbytes > 0 && s[nbytes - 1] == '\n')
nbytes--;
s[nbytes] = '\0';
return nbytes;
}
EXPORT_SYMBOL_GPL(xnvfile_get_string);
/**
* @fn ssize_t xnvfile_get_integer(struct xnvfile_input *input, long *valp)
* @brief Evaluate the string written to the vfile as a long integer.
*
* When writing to a vfile, the associated store() handler from the
* @ref snapshot_store "snapshot-driven vfile" or @ref regular_store
* "regular vfile" is called, with a single argument describing the
* input data. xnvfile_get_integer() retrieves and interprets this
* data as a long integer, and copies the resulting value back to @a
* valp.
*
* The long integer can be expressed in decimal, octal or hexadecimal
* bases depending on the prefix found.
*
* @param input A pointer to the input descriptor passed to the
* store() handler.
*
* @param valp The address of a long integer variable to receive the
* value.
*
* @return The number of characters read while evaluating the input as
* a long integer upon success. Otherwise, a negative error code is
* returned:
*
* - -EINVAL indicates a parse error on the input stream; the written
* text cannot be evaluated as a long integer.
*
* - -EFAULT indicates an invalid source buffer address.
*/
ssize_t xnvfile_get_integer(struct xnvfile_input *input, long *valp)
{
char *end, buf[32];
ssize_t nbytes;
long val;
nbytes = xnvfile_get_blob(input, buf, sizeof(buf) - 1);
if (nbytes < 0)
return nbytes;
if (nbytes == 0)
return -EINVAL;
buf[nbytes] = '\0';
val = simple_strtol(buf, &end, 0);
if (*end != '\0' && !isspace(*end))
return -EINVAL;
*valp = val;
return nbytes;
}
EXPORT_SYMBOL_GPL(xnvfile_get_integer);
int __vfile_hostlock_get(struct xnvfile *vfile)
{
struct xnvfile_hostlock_class *lc;
lc = container_of(vfile->lockops, struct xnvfile_hostlock_class, ops);
return down_interruptible(&lc->sem) ? -ERESTARTSYS : 0;
}
EXPORT_SYMBOL_GPL(__vfile_hostlock_get);
void __vfile_hostlock_put(struct xnvfile *vfile)
{
struct xnvfile_hostlock_class *lc;
lc = container_of(vfile->lockops, struct xnvfile_hostlock_class, ops);
up(&lc->sem);
}
EXPORT_SYMBOL_GPL(__vfile_hostlock_put);
static int __vfile_nklock_get(struct xnvfile *vfile)
{
struct xnvfile_nklock_class *lc;
lc = container_of(vfile->lockops, struct xnvfile_nklock_class, ops);
xnlock_get_irqsave(&nklock, lc->s);
return 0;
}
static void __vfile_nklock_put(struct xnvfile *vfile)
{
struct xnvfile_nklock_class *lc;
lc = container_of(vfile->lockops, struct xnvfile_nklock_class, ops);
xnlock_put_irqrestore(&nklock, lc->s);
}
struct xnvfile_nklock_class xnvfile_nucleus_lock = {
.ops = {
.get = __vfile_nklock_get,
.put = __vfile_nklock_put,
},
};
int __init xnvfile_init_root(void)
{
struct xnvfile_directory *vdir = &nkvfroot;
struct proc_dir_entry *pde;
pde = proc_mkdir("rtai", NULL);
if (pde == NULL)
return -ENOMEM;
vdir->entry.pde = pde;
vdir->entry.lockops = NULL;
vdir->entry.private = NULL;
wrap_proc_dir_entry_owner(pde);
return 0;
}
void xnvfile_destroy_root(void)
{
nkvfroot.entry.pde = NULL;
remove_proc_entry("rtai", NULL);
}
/*@}*/

View file

@ -1,700 +0,0 @@
/**
* @file
* This file is part of the Xenomai project.
*
* @note Copyright (C) 2010 Philippe Gerum <rpm@xenomai.org>
*
* adapted to RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @ingroup vfile
*/
#ifndef RTAI_RTDM_VFILE_H
#define RTAI_RTDM_VFILE_H
#ifdef CONFIG_PROC_FS
/** @addtogroup vfile
*@{*/
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <rtdm/xn.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
#define PDE_DATA(inode) PDE(inode)->data
static inline void proc_remove(struct proc_dir_entry *pde)
{
remove_proc_entry(pde->name, pde->parent);
}
#endif
#define wrap_f_inode(file) ((file)->f_path.dentry->d_inode)
#define wrap_proc_dir_entry_owner(entry) do { (void)entry; } while(0)
struct xnvfile_directory;
struct xnvfile_regular_iterator;
struct xnvfile_snapshot_iterator;
struct xnvfile_lock_ops;
struct xnvfile {
struct proc_dir_entry *pde;
struct file *file;
struct xnvfile_lock_ops *lockops;
int refcnt;
void *private;
};
/**
* @brief Vfile locking operations
* @anchor vfile_lockops
*
* This structure describes the operations to be provided for
* implementing locking support on vfiles. They apply to both
* snapshot-driven and regular vfiles.
*/
struct xnvfile_lock_ops {
/**
* @anchor lockops_get
* This handler should grab the desired lock.
*
* @param vfile A pointer to the virtual file which needs
* locking.
*
* @return zero should be returned if the call
* succeeds. Otherwise, a negative error code can be returned;
* upon error, the current vfile operation is aborted, and the
* user-space caller is passed back the error value.
*/
int (*get)(struct xnvfile *vfile);
/**
* @anchor lockops_put This handler should release the lock
* previously grabbed by the @ref lockops_get "get() handler".
*
* @param vfile A pointer to the virtual file which currently
* holds the lock to release.
*/
void (*put)(struct xnvfile *vfile);
};
/*
* XXX: struct semaphore is legacy for mutual exclusion, but supported
* on both 2.4 and 2.6 kernels. Will be changed to mutex when 2.4
* support is dropped from RTAI.
*/
struct xnvfile_hostlock_class {
struct xnvfile_lock_ops ops;
struct semaphore sem;
};
struct xnvfile_nklock_class {
struct xnvfile_lock_ops ops;
spl_t s;
};
struct xnvfile_input {
const char __user *u_buf;
size_t size;
struct xnvfile *vfile;
};
/**
* @brief Regular vfile operation descriptor
* @anchor regular_ops
*
* This structure describes the operations available with a regular
* vfile. It defines handlers for sending back formatted kernel data
* upon a user-space read request, and for obtaining user data upon a
* user-space write request.
*/
struct xnvfile_regular_ops {
/**
* @anchor regular_rewind This handler is called only once,
* when the virtual file is opened, before the @ref
* regular_begin "begin() handler" is invoked.
*
* @param it A pointer to the vfile iterator which will be
* used to read the file contents.
*
* @return Zero should be returned upon success. Otherwise, a
* negative error code aborts the operation, and is passed
* back to the reader.
*
* @note This handler is optional. It should not be used to
* allocate resources but rather to perform consistency
* checks, since no closure call is issued in case the open
* sequence eventually fails.
*/
int (*rewind)(struct xnvfile_regular_iterator *it);
/**
* @anchor regular_begin
* This handler should prepare for iterating over the records
* upon a read request, starting from the specified position.
*
* @param it A pointer to the current vfile iterator. On
* entry, it->pos is set to the (0-based) position of the
* first record to output. This handler may be called multiple
* times with different position requests.
*
* @return A pointer to the first record to format and output,
* to be passed to the @ref regular_show "show() handler" as
* its @a data parameter, if the call succeeds. Otherwise:
*
* - NULL in case no record is available, in which case the
* read operation will terminate immediately with no output.
*
* - VFILE_SEQ_START, a special value indicating that @ref
* regular_show "the show() handler" should receive a NULL
* data pointer first, in order to output a header.
*
* - ERR_PTR(errno), where errno is a negative error code;
* upon error, the current operation will be aborted
* immediately.
*
* @note This handler is optional; if none is given in the
* operation descriptor (i.e. NULL value), the @ref
* regular_show "show() handler()" will be called only once
* for a read operation, with a NULL @a data parameter. This
* particular setting is convenient for simple regular vfiles
* having a single, fixed record to output.
*/
void *(*begin)(struct xnvfile_regular_iterator *it);
/**
* @anchor regular_next
* This handler should return the address of the next record
* to format and output by the @ref regular_show "show()
* handler".
*
* @param it A pointer to the current vfile iterator. On
* entry, it->pos is set to the (0-based) position of the
* next record to output.
*
* @return A pointer to the next record to format and output,
* to be passed to the @ref regular_show "show() handler" as
* its @a data parameter, if the call succeeds. Otherwise:
*
* - NULL in case no record is available, in which case the
* read operation will terminate immediately with no output.
*
* - ERR_PTR(errno), where errno is a negative error code;
* upon error, the current operation will be aborted
* immediately.
*
* @note This handler is optional; if none is given in the
* operation descriptor (i.e. NULL value), the read operation
* will stop after the first invocation of the @ref regular_show
* "show() handler".
*/
void *(*next)(struct xnvfile_regular_iterator *it);
/**
* @anchor regular_end
* This handler is called after all records have been output.
*
* @param it A pointer to the current vfile iterator.
*
* @note This handler is optional and the pointer may be NULL.
*/
void (*end)(struct xnvfile_regular_iterator *it);
/**
* @anchor regular_show
* This handler should format and output a record.
*
* xnvfile_printf(), xnvfile_write(), xnvfile_puts() and
* xnvfile_putc() are available to format and/or emit the
* output. All routines take the iterator argument @a it as
* their first parameter.
*
* @param it A pointer to the current vfile iterator.
*
* @param data A pointer to the record to format then
* output. The first call to the handler may receive a NULL @a
* data pointer, depending on the presence and/or return of a
* @ref regular_begin "hander"; the show handler should test
* this special value to output any header that fits, prior to
* receiving more calls with actual records.
*
* @return zero if the call succeeds, also indicating that the
* handler should be called for the next record if
* any. Otherwise:
*
* - A negative error code. This will abort the output phase,
* and return this status to the reader.
*
* - VFILE_SEQ_SKIP, a special value indicating that the
* current record should be skipped and will not be output.
*/
int (*show)(struct xnvfile_regular_iterator *it, void *data);
/**
* @anchor regular_store
* This handler receives data written to the vfile, likely for
* updating some kernel setting, or triggering any other
* action which fits. This is the only handler which deals
* with the write-side of a vfile. It is called when writing
* to the /proc entry of the vfile from a user-space process.
*
* The input data is described by a descriptor passed to the
* handler, which may be subsequently passed to parsing helper
* routines. For instance, xnvfile_get_string() will accept
* the input descriptor for returning the written data as a
* null-terminated character string. On the other hand,
* xnvfile_get_integer() will attempt to return a long integer
* from the input data.
*
* @param input A pointer to an input descriptor. It refers to
* an opaque data from the handler's standpoint.
*
* @return the number of bytes read from the input descriptor
* if the call succeeds. Otherwise, a negative error code.
* Return values from parsing helper routines are commonly
* passed back to the caller by the @ref store
* "store() handler".
*
* @note This handler is optional, and may be omitted for
* read-only vfiles.
*/
ssize_t (*store)(struct xnvfile_input *input);
};
struct xnvfile_regular {
struct xnvfile entry;
size_t privsz;
struct xnvfile_regular_ops *ops;
};
struct xnvfile_regular_template {
size_t privsz;
struct xnvfile_regular_ops *ops;
struct xnvfile_lock_ops *lockops;
};
/**
* @brief Regular vfile iterator
* @anchor regular_iterator
*
* This structure defines an iterator over a regular vfile.
*/
struct xnvfile_regular_iterator {
/** Current record position while iterating. */
loff_t pos;
/** Backlink to the host sequential file supporting the vfile. */
struct seq_file *seq;
/** Backlink to the vfile being read. */
struct xnvfile_regular *vfile;
/**
* Start of private area. Use xnvfile_iterator_priv() to
* address it.
*/
char private[0];
};
/**
* @brief Snapshot vfile operation descriptor
* @anchor snapshot_ops
*
* This structure describes the operations available with a
* snapshot-driven vfile. It defines handlers for returning a
* printable snapshot of some RTAI object contents upon a
* user-space read request, and for updating this object upon a
* user-space write request.
*/
struct xnvfile_snapshot_ops {
/**
* @anchor snapshot_rewind
* This handler (re-)initializes the data collection, moving
* the seek pointer at the first record. When the file
* revision tag is touched while collecting data, the current
* reading is aborted, all collected data dropped, and the
* vfile is eventually rewound.
*
* @param it A pointer to the current snapshot iterator. Two
* useful information can be retrieved from this iterator in
* this context:
*
* - it->vfile is a pointer to the descriptor of the virtual
* file being rewound.
*
* - xnvfile_iterator_priv(it) returns a pointer to the
* private data area, available from the descriptor, which
* size is vfile->privsz. If the latter size is zero, the
* returned pointer is meaningless and should not be used.
*
* @return A negative error code aborts the data collection,
* and is passed back to the reader. Otherwise:
*
* - a strictly positive value is interpreted as the total
* number of records which will be returned by the @ref
* snapshot_next "next() handler" during the data collection
* phase. If no @ref snapshot_begin "begin() handler" is
* provided in the @ref snapshot_ops "operation descriptor",
* this value is used to allocate the snapshot buffer
* internally. The size of this buffer would then be
* vfile->datasz * value.
*
* - zero leaves the allocation to the @ref snapshot_begin
* "begin() handler" if present, or indicates that no record
* is to be output in case such handler is not given.
*
* @note This handler is optional; a NULL value indicates that
* nothing needs to be done for rewinding the vfile. It is
* called with the vfile lock held.
*/
int (*rewind)(struct xnvfile_snapshot_iterator *it);
/**
* @anchor snapshot_begin
* This handler should allocate the snapshot buffer to hold
* records during the data collection phase. When specified,
* all records collected via the @ref snapshot_next "next()
* handler" will be written to a cell from the memory area
* returned by begin().
*
* @param it A pointer to the current snapshot iterator.
*
* @return A pointer to the record buffer, if the call
* succeeds. Otherwise:
*
* - NULL in case of allocation error. This will abort the data
* collection, and return -ENOMEM to the reader.
*
* - VFILE_SEQ_EMPTY, a special value indicating that no
* record will be output. In such a case, the @ref
* snapshot_next "next() handler" will not be called, and the
* data collection will stop immediately. However, the @ref
* snapshot_show "show() handler" will still be called once,
* with a NULL data pointer (i.e. header display request).
*
* @note This handler is optional; if none is given, an
* internal allocation depending on the value returned by the
* @ref snapshot_rewind "rewind() handler" can be obtained.
*/
void *(*begin)(struct xnvfile_snapshot_iterator *it);
/**
* @anchor snapshot_end
* This handler releases the memory buffer previously obtained
* from begin(). It is usually called after the snapshot data
* has been output by show(), but it may also be called before
* rewinding the vfile after a revision change, to release the
* dropped buffer.
*
* @param it A pointer to the current snapshot iterator.
*
* @param buf A pointer to the buffer to release.
*
* @note This routine is optional and the pointer may be
* NULL. It is not needed upon internal buffer allocation;
* see the description of the @ref snapshot_rewind "rewind()
* handler".
*/
void (*end)(struct xnvfile_snapshot_iterator *it, void *buf);
/**
* @anchor snapshot_next
* This handler fetches the next record, as part of the
* snapshot data to be sent back to the reader via the
* show().
*
* @param it A pointer to the current snapshot iterator.
*
* @param data A pointer to the record to fill in.
*
* @return a strictly positive value, if the call succeeds and
* leaves a valid record into @a data, which should be passed
* to the @ref snapshot_show "show() handler()" during the
* formatting and output phase. Otherwise:
*
* - A negative error code. This will abort the data
* collection, and return this status to the reader.
*
* - VFILE_SEQ_SKIP, a special value indicating that the
* current record should be skipped. In such a case, the @a
* data pointer is not advanced to the next position before
* the @ref snapshot_next "next() handler" is called anew.
*
* @note This handler is called with the vfile lock
* held. Before each invocation of this handler, the vfile
* core checks whether the revision tag has been touched, in
* which case the data collection is restarted from scratch. A
* data collection phase succeeds whenever all records can be
* fetched via the @ref snapshot_next "next() handler", while
* the revision tag remains unchanged, which indicates that a
* consistent snapshot of the object state was taken.
*/
int (*next)(struct xnvfile_snapshot_iterator *it, void *data);
/**
* @anchor snapshot_show
* This handler should format and output a record from the
* collected data.
*
* xnvfile_printf(), xnvfile_write(), xnvfile_puts() and
* xnvfile_putc() are available to format and/or emit the
* output. All routines take the iterator argument @a it as
* their first parameter.
*
* @param it A pointer to the current snapshot iterator.
*
* @param data A pointer to the record to format then
* output. The first call to the handler is always passed a
* NULL @a data pointer; the show handler should test this
* special value to output any header that fits, prior to
* receiving more calls with actual records.
*
* @return zero if the call succeeds, also indicating that the
* handler should be called for the next record if
* any. Otherwise:
*
* - A negative error code. This will abort the output phase,
* and return this status to the reader.
*
* - VFILE_SEQ_SKIP, a special value indicating that the
* current record should be skipped and will not be output.
*/
int (*show)(struct xnvfile_snapshot_iterator *it, void *data);
/**
* @anchor snapshot_store
* This handler receives data written to the vfile, likely for
* updating the associated RTAI object's state, or
* triggering any other action which fits. This is the only
* handler which deals with the write-side of a vfile. It is
* called when writing to the /proc entry of the vfile
* from a user-space process.
*
* The input data is described by a descriptor passed to the
* handler, which may be subsequently passed to parsing helper
* routines. For instance, xnvfile_get_string() will accept
* the input descriptor for returning the written data as a
* null-terminated character string. On the other hand,
* xnvfile_get_integer() will attempt to return a long integer
* from the input data.
*
* @param input A pointer to an input descriptor. It refers to
* an opaque data from the handler's standpoint.
*
* @return the number of bytes read from the input descriptor
* if the call succeeds. Otherwise, a negative error code.
* Return values from parsing helper routines are commonly
* passed back to the caller by the @ref snapshot_store
* "store() handler".
*
* @note This handler is optional, and may be omitted for
* read-only vfiles.
*/
ssize_t (*store)(struct xnvfile_input *input);
};
/**
* @brief Snapshot revision tag
* @anchor revision_tag
*
* This structure defines a revision tag to be used with @ref
* snapshot_vfile "snapshot-driven vfiles".
*/
struct xnvfile_rev_tag {
/** Current revision number. */
int rev;
};
struct xnvfile_snapshot_template {
size_t privsz;
size_t datasz;
struct xnvfile_rev_tag *tag;
struct xnvfile_snapshot_ops *ops;
struct xnvfile_lock_ops *lockops;
};
/**
* @brief Snapshot vfile descriptor
* @anchor snapshot_vfile
*
* This structure describes a snapshot-driven vfile. Reading from
* such a vfile involves a preliminary data collection phase under
* lock protection, and a subsequent formatting and output phase of
* the collected data records. Locking is done in a way that does not
* increase worst-case latency, regardless of the number of records to
* be collected for output.
*/
struct xnvfile_snapshot {
struct xnvfile entry;
size_t privsz;
size_t datasz;
struct xnvfile_rev_tag *tag;
struct xnvfile_snapshot_ops *ops;
};
/**
* @brief Snapshot-driven vfile iterator
* @anchor snapshot_iterator
*
* This structure defines an iterator over a snapshot-driven vfile.
*/
struct xnvfile_snapshot_iterator {
/** Number of collected records. */
int nrdata;
/** Address of record buffer. */
caddr_t databuf;
/** Backlink to the host sequential file supporting the vfile. */
struct seq_file *seq;
/** Backlink to the vfile being read. */
struct xnvfile_snapshot *vfile;
/** Buffer release handler. */
void (*endfn)(struct xnvfile_snapshot_iterator *it, void *buf);
/**
* Start of private area. Use xnvfile_iterator_priv() to
* address it.
*/
char private[0];
};
struct xnvfile_directory {
struct xnvfile entry;
};
struct xnvfile_link {
struct xnvfile entry;
};
/* vfile.begin()=> */
#define VFILE_SEQ_EMPTY ((void *)-1)
/* =>vfile.show() */
#define VFILE_SEQ_START SEQ_START_TOKEN
/* vfile.next/show()=> */
#define VFILE_SEQ_SKIP 2
#define xnvfile_printf(it, args...) seq_printf((it)->seq, ##args)
#define xnvfile_write(it, data, len) seq_write((it)->seq, (data),(len))
#define xnvfile_puts(it, s) seq_puts((it)->seq, (s))
#define xnvfile_putc(it, c) seq_putc((it)->seq, (c))
static inline void xnvfile_touch_tag(struct xnvfile_rev_tag *tag)
{
tag->rev++;
}
static inline void xnvfile_touch(struct xnvfile_snapshot *vfile)
{
xnvfile_touch_tag(vfile->tag);
}
#define xnvfile_noentry \
{ \
.pde = NULL, \
.private = NULL, \
.file = NULL, \
.refcnt = 0, \
}
#define xnvfile_nodir { .entry = xnvfile_noentry }
#define xnvfile_nolink { .entry = xnvfile_noentry }
#define xnvfile_nofile { .entry = xnvfile_noentry }
#define xnvfile_priv(e) ((e)->entry.private)
#define xnvfile_nref(e) ((e)->entry.refcnt)
#define xnvfile_file(e) ((e)->entry.file)
#define xnvfile_iterator_priv(it) ((void *)(&(it)->private))
extern struct xnvfile_nklock_class xnvfile_nucleus_lock;
extern struct xnvfile_directory nkvfroot;
int xnvfile_init_root(void);
void xnvfile_destroy_root(void);
#ifdef __cplusplus
extern "C" {
#endif
int xnvfile_init_snapshot(const char *name,
struct xnvfile_snapshot *vfile,
struct xnvfile_directory *parent);
int xnvfile_init_regular(const char *name,
struct xnvfile_regular *vfile,
struct xnvfile_directory *parent);
int xnvfile_init_dir(const char *name,
struct xnvfile_directory *vdir,
struct xnvfile_directory *parent);
int xnvfile_init_link(const char *from,
const char *to,
struct xnvfile_link *vlink,
struct xnvfile_directory *parent);
void xnvfile_destroy(struct xnvfile *vfile);
ssize_t xnvfile_get_blob(struct xnvfile_input *input,
void *data, size_t size);
ssize_t xnvfile_get_string(struct xnvfile_input *input,
char *s, size_t maxlen);
ssize_t xnvfile_get_integer(struct xnvfile_input *input, long *valp);
int __vfile_hostlock_get(struct xnvfile *vfile);
void __vfile_hostlock_put(struct xnvfile *vfile);
#ifdef __cplusplus
}
#endif
static inline
void xnvfile_destroy_snapshot(struct xnvfile_snapshot *vfile)
{
xnvfile_destroy(&vfile->entry);
}
static inline
void xnvfile_destroy_regular(struct xnvfile_regular *vfile)
{
xnvfile_destroy(&vfile->entry);
}
static inline
void xnvfile_destroy_dir(struct xnvfile_directory *vdir)
{
xnvfile_destroy(&vdir->entry);
}
static inline
void xnvfile_destroy_link(struct xnvfile_link *vlink)
{
xnvfile_destroy(&vlink->entry);
}
#define DEFINE_VFILE_HOSTLOCK(name) \
struct xnvfile_hostlock_class name = { \
.ops = { \
.get = __vfile_hostlock_get, \
.put = __vfile_hostlock_put, \
}, \
.sem = __SEMAPHORE_INITIALIZER(name.sem, 1), \
}
#else /* !CONFIG_PROC_FS */
#define xnvfile_touch_tag(tag) do { } while (0)
#define xnvfile_touch(vfile) do { } while (0)
#endif /* !CONFIG_PROC_FS */
/*@}*/
#endif /* !RTAI_RTDM_VFILE_H */

View file

@ -34,29 +34,15 @@ endmenu
menu "Machine (x86 / x86_64)" menu "Machine (x86 / x86_64)"
config RTAI_FPU_SUPPORT
bool "Enable FPU support"
default y
help
The FPU executes instructions from the processor's normal
instruction stream. It can handle the types of high-precision
floating-point processing operations commonly found in
scientific, engineering, and business applications. Enabling
FPU support on a platform providing this hardware component
may greatly improve performances. You can obtain more
information about Float-Point Unit on x86 platform on
internet at the following URL:
http://www.intel.com/design/intarch/techinfo/Pentium/fpu.htm
config RTAI_CPUS config RTAI_CPUS
string "Number of CPUs (SMP-only)" string "Number of CPUs (SMP-only)"
default 2 default 4
help help
RTAI has native support for Symmetrical Multi-Processing RTAI has native support for Symmetrical Multi-Processing
machines. If it is your case, you may want to enter here the machines. If it is your case, you may want to enter here the
number of CPUs of your motherboard. number of CPUs of your motherboard.
PAY ATTENTION: the default value is 2. PAY ATTENTION: the default value is 4.
config RTAI_DIAG_TSC_SYNC config RTAI_DIAG_TSC_SYNC
bool "Diagnose out of sync MP-TSCs" bool "Diagnose out of sync MP-TSCs"
@ -207,7 +193,7 @@ config RTAI_USER_BUSY_ALIGN_RET_DELAY
config RTAI_SCHED_LXRT_NUMSLOTS config RTAI_SCHED_LXRT_NUMSLOTS
string "Number of registrable RTAI objects" string "Number of registrable RTAI objects"
default 256 default 1024
help help
The maximum number of registrable objects in RTAI. The maximum number of registrable objects in RTAI.
@ -264,7 +250,7 @@ config RTAI_FULL_PRINHER
config RTAI_ALIGN_LINUX_PRIORITY config RTAI_ALIGN_LINUX_PRIORITY
bool "Keep Linux task priority aligned to RTAI" bool "Keep Linux task priority aligned to RTAI"
default n default y
help help
By enabling this option the RTAI scheduler will keep Linux tasks By enabling this option the RTAI scheduler will keep Linux tasks
@ -275,7 +261,7 @@ config RTAI_ALIGN_LINUX_PRIORITY
config RTAI_ONE_SHOT config RTAI_ONE_SHOT
bool "One-shot timer mode" bool "One-shot timer mode"
default n default y
help help
Set to enable one-shot timer mode as the default. If not set, the Set to enable one-shot timer mode as the default. If not set, the
hard timer will run in periodic mode according to the period used hard timer will run in periodic mode according to the period used
@ -313,22 +299,6 @@ endmenu
menu "Supported services" menu "Supported services"
config RTAI_BITS
tristate "Event flags"
default m
help
Event flags are used to synchronize a task to the occurrence of
multiple events. RTAI uses the term "bits" to stress the fact that
events are just logical objects, i.e. a kind of digital I/O,
nothing else being associated to them, e.g a count.
So any synchronization based on them may be disjunctive, when any
of the events have occurred, or conjunctive, when all events have
occurred. The former corresponds to a logical OR whereas the latter
is associated to a logical AND. Their use is similar to semaphores
except that signal/waits are not related to just a simple counter
but depends on the combination of set of bits.
The module will be called rtai_bits.o.
config RTAI_FIFOS config RTAI_FIFOS
tristate "Fifo" tristate "Fifo"
default m default m
@ -463,28 +433,6 @@ config RTAI_MBX
Mailboxes depend on semaphores. Mailboxes depend on semaphores.
The module will be called rtai_mbx.o. The module will be called rtai_mbx.o.
config RTAI_TBX
tristate "RTAI message queues and typed mailboxes"
depends on RTAI_SEM
default y if RTAI_SEM=y
default m if RTAI_SEM=m
help
RTAI message queues (msgq) are intertask processor messages that allow
exchanging prioritised messages of any size. Broadcasting of messages
to all the waiting tasks is also possible.
Legacy typed mailbox (TBX) services are recovered by using RTAI msgqs
and afford a pre canned example of their use offering:
1 - message broadcasting allowing to send a message to all the tasks
that are pending on the same TBX;
2 - urgent sending of messages: these messages are not enqueued, but
inserted in the head of the queue, bypassing all the other
messages already present in TBX;
3 - a priority or fifo wakeup policy that may be set at runtime when
creating the typed mailbox.
Typed mailboxes depend on semaphores.
The module will be called rtai_tbx.o.
config RTAI_TASKLETS config RTAI_TASKLETS
tristate "Tasklets" tristate "Tasklets"
default m default m
@ -577,20 +525,6 @@ config RTAI_USE_NEWERR
to choose what to do, without forcing any adaption for already to choose what to do, without forcing any adaption for already
existing working applications. existing working applications.
config RTAI_MATH
tristate "Mathfuns support in kernel"
depends on RTAI_FPU_SUPPORT
default y
help
This parameter allows building a module containing math support
functions for kernel space. It might be useful to avoid fighting
for the use of libc within the kernel.
config RTAI_MATH_C99
bool "C99 standard support"
depends on RTAI_MATH
default y
config RTAI_MALLOC config RTAI_MALLOC
tristate "Real-time malloc support" tristate "Real-time malloc support"
default y default y
@ -687,47 +621,3 @@ config RTAI_HARD_SOFT_TOGGLER
endmenu endmenu
endmenu endmenu
menu "Add-ons"
config RTAI_RTDM
bool "Real-Time Driver Model over RTAI"
default n
help
Real Time Drive Model specific implementation for RTAI.
config RTAI_RTDM_FD_MAX
depends on RTAI_RTDM
string "Number of RTDM file descriptors"
default 512
help
The maximum number of file descriptors in RTDM.
config RTAI_RTDM_SELECT
depends on RTAI_RTDM
bool "Enable select multiplexing for RTDM services"
default n
help
By enabling this option, select(2) support can be used to monitor
access to multiple RTDM services all in one, as for the standard UNIX
support, with the exception of the timeout argument format. Being it
RTDM specific nanoseconds are used directly in place of
timeval/timespec.
config RTAI_RTDM_SHIRQ
depends on RTAI_RTDM
bool "Shared interrupts"
default n
help
Make it possible for RTDM own interrupt handlers to manage shared
interrupts.
config RTAI_DEBUG_RTDM
depends on RTAI_RTDM
bool "Enable some elementary RTDM debugging messages"
default n
help
Enable some elementary debugging of wrong requests to RTDM, in the
form of messages asserting what's improper and where it's happening.
endmenu

View file

@ -3,8 +3,6 @@ moduledir = @RTAI_MODULE_DIR@
modext = @RTAI_MODULE_EXT@ modext = @RTAI_MODULE_EXT@
libcalibrate_rt_a_SOURCES = calibrate-module.c calibrate.h libcalibrate_rt_a_SOURCES = calibrate-module.c calibrate.h
libsmi_rt_a_SOURCES = smi-module.c libsmi_rt_a_SOURCES = smi-module.c
@ -57,7 +55,7 @@ calibration_PROGRAMS += calibration_helper
calibrate_SOURCES = calibrate.c calibrate.h calibrate_SOURCES = calibrate.c calibrate.h
calibrate_CPPFLAGS = \ calibrate_CPPFLAGS = \
@RTAI_REAL_USER_CFLAGS@ \ @RTAI_USER_CFLAGS@ \
-DKERNEL_HELPER_PATH="\"$(calibrationdir)/rtai_calibrate$(modext)\"" \ -DKERNEL_HELPER_PATH="\"$(calibrationdir)/rtai_calibrate$(modext)\"" \
-DUSER_HELPER_PATH="\"$(calibrationdir)/calibration_helper\"" \ -DUSER_HELPER_PATH="\"$(calibrationdir)/calibration_helper\"" \
-I$(top_srcdir)/base/include \ -I$(top_srcdir)/base/include \
@ -66,7 +64,7 @@ calibrate_CPPFLAGS = \
calibration_helper_SOURCES = calibration_helper.c calibration_helper_SOURCES = calibration_helper.c
calibration_helper_CPPFLAGS = \ calibration_helper_CPPFLAGS = \
@RTAI_REAL_USER_CFLAGS@ \ @RTAI_USER_CFLAGS@ \
-DHAL_SCHED_PATH="\"$(DESTDIR)$(moduledir)\"" \ -DHAL_SCHED_PATH="\"$(DESTDIR)$(moduledir)\"" \
-DHAL_SCHED_MODEXT="\"$(modext)\"" \ -DHAL_SCHED_MODEXT="\"$(modext)\"" \
-I$(top_srcdir)/base/include \ -I$(top_srcdir)/base/include \

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
# #
# Automatically generated make config: don't edit # Automatically generated file; DO NOT EDIT.
# RTAI/x86 configuration
# #
CONFIG_MODULES=y CONFIG_MODULES=y
CONFIG_RTAI_VERSION="4.0 (vulcano)" CONFIG_RTAI_VERSION="4.0 (vulcano)"
@ -11,22 +12,9 @@ CONFIG_RTAI_INSTALLDIR="/usr/realtime"
CONFIG_RTAI_LINUXDIR="/usr/src/linux" CONFIG_RTAI_LINUXDIR="/usr/src/linux"
# #
# RTAI Documentation # Machine (x86 / x86_64)
# #
# CONFIG_RTAI_DOX_DOC is not set CONFIG_RTAI_CPUS="4"
# CONFIG_RTAI_DOC_LATEX_NONSTOP is not set
# CONFIG_RTAI_DBX_DOC is not set
CONFIG_RTAI_TESTSUITE=y
CONFIG_RTAI_COMPAT=y
# CONFIG_RTAI_EXTENDED is not set
CONFIG_RTAI_LXRT_NO_INLINE=y
# CONFIG_RTAI_LXRT_STATIC_INLINE is not set
#
# Machine (x86)
#
CONFIG_RTAI_FPU_SUPPORT=y
CONFIG_RTAI_CPUS="2"
# CONFIG_RTAI_DIAG_TSC_SYNC is not set # CONFIG_RTAI_DIAG_TSC_SYNC is not set
# #
@ -41,27 +29,26 @@ CONFIG_RTAI_CPUS="2"
CONFIG_RTAI_SCHED_8254_LATENCY="4700" CONFIG_RTAI_SCHED_8254_LATENCY="4700"
CONFIG_RTAI_SCHED_APIC_LATENCY="3944" CONFIG_RTAI_SCHED_APIC_LATENCY="3944"
# CONFIG_RTAI_BUSY_TIME_ALIGN is not set # CONFIG_RTAI_BUSY_TIME_ALIGN is not set
CONFIG_RTAI_SCHED_LXRT_NUMSLOTS="150" CONFIG_RTAI_SCHED_LXRT_NUMSLOTS="1024"
CONFIG_RTAI_MONITOR_EXECTIME=y CONFIG_RTAI_MONITOR_EXECTIME=y
CONFIG_RTAI_ALLOW_RR=y CONFIG_RTAI_ALLOW_RR=y
# CONFIG_RTAI_FULL_PRINHER is not set # CONFIG_RTAI_FULL_PRINHER is not set
# CONFIG_RTAI_ALIGN_LINUX_PRIORITY is not set CONFIG_RTAI_ALIGN_LINUX_PRIORITY=y
# CONFIG_RTAI_ONE_SHOT is not set CONFIG_RTAI_ONE_SHOT=y
CONFIG_RTAI_CAL_FREQS_FACT="0" CONFIG_RTAI_CAL_FREQS_FACT="0"
# #
# Supported services # Supported services
# #
CONFIG_RTAI_BITS=m
CONFIG_RTAI_FIFOS=m CONFIG_RTAI_FIFOS=m
CONFIG_RTAI_NETRPC=m CONFIG_RTAI_NETRPC=m
# CONFIG_RTAI_NETRPC_RTNET is not set # CONFIG_RTAI_NETRPC_RTNET is not set
CONFIG_RTAI_SHM=m CONFIG_RTAI_SHM=m
CONFIG_RTAI_SEM=m CONFIG_RTAI_SEM=m
# CONFIG_RTAI_RT_POLL is not set CONFIG_RTAI_RT_POLL=y
# CONFIG_RTAI_RT_POLL_ON_STACK is not set
CONFIG_RTAI_MSG=m CONFIG_RTAI_MSG=m
CONFIG_RTAI_MBX=m CONFIG_RTAI_MBX=m
CONFIG_RTAI_TBX=m
CONFIG_RTAI_TASKLETS=m CONFIG_RTAI_TASKLETS=m
CONFIG_RTAI_MQ=m CONFIG_RTAI_MQ=m
CONFIG_RTAI_CLOCK_REALTIME=y CONFIG_RTAI_CLOCK_REALTIME=y
@ -69,33 +56,11 @@ CONFIG_RTAI_CLOCK_REALTIME=y
# #
# Other features # Other features
# #
# CONFIG_RTAI_USE_NEWERR is not set CONFIG_RTAI_USE_NEWERR=y
# CONFIG_RTAI_MATH is not set
CONFIG_RTAI_MALLOC=y CONFIG_RTAI_MALLOC=y
# CONFIG_RTAI_USE_TLSF is not set # CONFIG_RTAI_USE_TLSF is not set
CONFIG_RTAI_MALLOC_VMALLOC=y CONFIG_RTAI_MALLOC_VMALLOC=y
CONFIG_RTAI_MALLOC_HEAPSZ="2048" CONFIG_RTAI_MALLOC_HEAPSZ="2048"
CONFIG_RTAI_KSTACK_HEAPSZ="512" CONFIG_RTAI_KSTACK_HEAPSZ="512"
# CONFIG_RTAI_TASK_SWITCH_SIGNAL is not set # CONFIG_RTAI_TASK_SWITCH_SIGNAL is not set
# CONFIG_RTAI_USI is not set
CONFIG_RTAI_WD=y
# CONFIG_RTAI_HARD_SOFT_TOGGLER is not set # CONFIG_RTAI_HARD_SOFT_TOGGLER is not set
#
# Add-ons
#
CONFIG_RTAI_COMEDI_LXRT=y
CONFIG_RTAI_COMEDI_DIR="/usr/comedi"
# CONFIG_RTAI_USE_COMEDI_LOCK is not set
# CONFIG_RTAI_CPLUSPLUS is not set
# CONFIG_RTAI_RTDM is not set
#
# Drivers
#
CONFIG_RTAI_DRIVERS_SERIAL=y
#
# RTAI Lab
#
# CONFIG_RTAI_LAB is not set

View file

@ -938,8 +938,8 @@ void rt_request_apic_timers (void (*handler)(void), struct apic_timer_setup_data
} }
} }
rtai_critical_exit(flags);
rtai_request_tickdev(handler); rtai_request_tickdev(handler);
rtai_critical_exit(flags);
} }
/** /**
@ -956,8 +956,8 @@ void rt_free_apic_timers(void)
rtai_release_tickdev(); rtai_release_tickdev();
rtai_sync_level = 3; rtai_sync_level = 3;
rtai_setup_periodic_apic(RTAI_APIC_ICOUNT,LOCAL_TIMER_VECTOR); rtai_setup_periodic_apic(RTAI_APIC_ICOUNT,LOCAL_TIMER_VECTOR);
rtai_critical_exit(flags);
rt_release_irq(RTAI_APIC_TIMER_IPI); rt_release_irq(RTAI_APIC_TIMER_IPI);
rtai_critical_exit(flags);
} }
/** /**
@ -1460,7 +1460,7 @@ static unsigned long hal_request_apic_freq(void);
static void rtai_install_archdep (void) static void rtai_install_archdep (void)
{ {
ipipe_select_timers(cpu_active_mask); ipipe_select_timers(cpu_present_mask);
hal_catch_event(hal_root_domain, HAL_SYSCALL_PROLOGUE, (void *)intercept_syscall_prologue); hal_catch_event(hal_root_domain, HAL_SYSCALL_PROLOGUE, (void *)intercept_syscall_prologue);
if (rtai_cpufreq_arg == 0) { if (rtai_cpufreq_arg == 0) {

View file

@ -96,7 +96,7 @@ static void rtai_release_tickdev(void);
static inline void rtai_setup_periodic_apic (unsigned count, unsigned vector) static inline void rtai_setup_periodic_apic (unsigned count, unsigned vector)
{ {
apic_read(APIC_LVTT); apic_read(APIC_LVTT);
apic_write(APIC_LVTT, APIC_LVT_TIMER_PERIODIC | vector); apic_write(APIC_LVTT, APIC_INTEGRATED(GET_APIC_VERSION(apic_read(APIC_LVR))) ? SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | APIC_LVT_TIMER_PERIODIC | vector : APIC_LVT_TIMER_PERIODIC | vector);
apic_read(APIC_TMICT); apic_read(APIC_TMICT);
apic_write(APIC_TMICT, count); apic_write(APIC_TMICT, count);
} }
@ -104,7 +104,7 @@ static inline void rtai_setup_periodic_apic (unsigned count, unsigned vector)
static inline void rtai_setup_oneshot_apic (unsigned count, unsigned vector) static inline void rtai_setup_oneshot_apic (unsigned count, unsigned vector)
{ {
apic_read(APIC_LVTT); apic_read(APIC_LVTT);
apic_write(APIC_LVTT, vector); apic_write(APIC_LVTT, APIC_INTEGRATED(GET_APIC_VERSION(apic_read(APIC_LVR))) ? SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | vector : vector);
apic_read(APIC_TMICT); apic_read(APIC_TMICT);
apic_write(APIC_TMICT, count); apic_write(APIC_TMICT, count);
} }
@ -924,8 +924,8 @@ void rt_request_apic_timers (void (*handler)(void), struct apic_timer_setup_data
} }
} }
rtai_critical_exit(flags);
rtai_request_tickdev(handler); rtai_request_tickdev(handler);
rtai_critical_exit(flags);
} }
/** /**
@ -942,8 +942,8 @@ void rt_free_apic_timers(void)
rtai_release_tickdev(); rtai_release_tickdev();
rtai_sync_level = 3; rtai_sync_level = 3;
rtai_setup_periodic_apic(RTAI_APIC_ICOUNT,LOCAL_TIMER_VECTOR); rtai_setup_periodic_apic(RTAI_APIC_ICOUNT,LOCAL_TIMER_VECTOR);
rtai_critical_exit(flags);
rt_release_irq(RTAI_APIC_TIMER_IPI); rt_release_irq(RTAI_APIC_TIMER_IPI);
rtai_critical_exit(flags);
} }
/** /**
@ -1394,7 +1394,7 @@ static unsigned long hal_request_apic_freq(void);
static void rtai_install_archdep (void) static void rtai_install_archdep (void)
{ {
ipipe_select_timers(cpu_active_mask); ipipe_select_timers(cpu_present_mask);
hal_catch_event(hal_root_domain, HAL_SYSCALL_PROLOGUE, (void *)intercept_syscall_prologue); hal_catch_event(hal_root_domain, HAL_SYSCALL_PROLOGUE, (void *)intercept_syscall_prologue);
if (rtai_cpufreq_arg == 0) { if (rtai_cpufreq_arg == 0) {

View file

@ -5250,6 +5250,67 @@ index f04e25f..5fa6be6 100644
select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE)
select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE) select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE)
help help
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 79bbc21..f1805d4 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -5,6 +5,7 @@ config IOMMU_API
menuconfig IOMMU_SUPPORT
bool "IOMMU Hardware Support"
default y
+ depends on !IPIPE
---help---
Say Y here if you want to compile device drivers for IO Memory
Management Units into the kernel. These devices usually allow to
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 893503f..d0d856d 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -28,7 +28,7 @@ config PCI_DEBUG
config PCI_REALLOC_ENABLE_AUTO
bool "Enable PCI resource re-allocation detection"
- depends on PCI
+ depends on PCI && PCI_IOV
help
Say Y here if you want the PCI core to detect if PCI resource
re-allocation needs to be enabled. You can always use pci=realloc=on
@@ -72,7 +72,7 @@ config PCI_ATS
config PCI_IOV
bool "PCI IOV support"
- depends on PCI
+ depends on PCI && !IPIPE
select PCI_ATS
help
I/O Virtualization is a PCI feature supported by some devices
@@ -83,7 +83,7 @@ config PCI_IOV
config PCI_PRI
bool "PCI PRI support"
- depends on PCI
+ depends on PCI && IOMMU_SUPPORT
select PCI_ATS
help
PRI is the PCI Page Request Interface. It allows PCI devices that are
@@ -93,7 +93,7 @@ config PCI_PRI
config PCI_PASID
bool "PCI PASID support"
- depends on PCI
+ depends on PCI && IOMMU_SUPPORT
select PCI_ATS
help
Process Address Space Identifiers (PASIDs) can be used by PCI devices
@@ -106,7 +106,7 @@ config PCI_PASID
config PCI_IOAPIC
bool "PCI IO-APIC hotplug support" if X86
- depends on PCI
+ depends on PCI && !IPIPE
depends on ACPI
depends on X86_IO_APIC
default !X86
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c
index 6e373ea..f32da7b 100644 index 6e373ea..f32da7b 100644
--- a/drivers/pci/htirq.c --- a/drivers/pci/htirq.c

View file

@ -3,7 +3,6 @@ ARCHDIR = asm-x86
nobase_include_HEADERS = \ nobase_include_HEADERS = \
rtai.h \ rtai.h \
rtai_hal_names.h \ rtai_hal_names.h \
rtai_bits.h \
rtai_fifos.h \ rtai_fifos.h \
rtai_lxrt.h \ rtai_lxrt.h \
rtai_malloc.h \ rtai_malloc.h \
@ -30,7 +29,6 @@ nobase_include_HEADERS = \
rtai_signal.h \ rtai_signal.h \
rtai_spl.h \ rtai_spl.h \
rtai_tasklets.h \ rtai_tasklets.h \
rtai_tbx.h \
rtai_trace.h \ rtai_trace.h \
rtai_types.h \ rtai_types.h \
rtai_version.h \ rtai_version.h \
@ -41,7 +39,7 @@ install-data-local:
if CONFIG_RTAI_OLD_FASHIONED_BUILD if CONFIG_RTAI_OLD_FASHIONED_BUILD
distclean-local: distclean-local:
rm -f $(DESTDIR)$(includedir)/asm $(DESTDIR)$(includedir)/rtai_config.h rm -f $(srcdir)$(includedir)/asm $(srcdir)$(includedir)/rtai_config.h
endif endif
SUBDIRS = $(ARCHDIR) SUBDIRS = $(ARCHDIR)

View file

@ -32,20 +32,10 @@
#include <asm/processor.h> #include <asm/processor.h>
#endif /* !__cplusplus */ #endif /* !__cplusplus */
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
typedef union i387_union FPU_ENV;
#define TASK_FPENV(tsk) (&(tsk)->thread.i387)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)
typedef union thread_xstate FPU_ENV;
#define TASK_FPENV(tsk) ((tsk)->thread.xstate)
#else
typedef union thread_xstate FPU_ENV; typedef union thread_xstate FPU_ENV;
#define TASK_FPENV(tsk) ((tsk)->thread.fpu.state) #define TASK_FPENV(tsk) ((tsk)->thread.fpu.state)
#endif
#ifdef CONFIG_RTAI_FPU_SUPPORT /* RAW FPU MANAGEMENT FOR USAGE FROM WHAT/WHEREVER RTAI DOES IN KERNEL */
// RAW FPU MANAGEMENT FOR USAGE FROM WHAT/WHEREVER RTAI DOES IN KERNEL
#define enable_fpu() do { \ #define enable_fpu() do { \
__asm__ __volatile__ ("clts"); \ __asm__ __volatile__ ("clts"); \
@ -62,7 +52,7 @@ typedef union thread_xstate FPU_ENV;
} \ } \
} while (0) } while (0)
// initialise the hard fpu unit directly /* initialise the hard fpu unit directly */
#define init_hard_fpenv() do { \ #define init_hard_fpenv() do { \
__asm__ __volatile__ ("clts; fninit"); \ __asm__ __volatile__ ("clts; fninit"); \
if (cpu_has_xmm) { \ if (cpu_has_xmm) { \
@ -71,7 +61,7 @@ typedef union thread_xstate FPU_ENV;
} \ } \
} while (0) } while (0)
// initialise the given fpenv union, without touching the related hard fpu unit /* initialise the given fpenv union, without touching the related hard fpu unit */
#define __init_fpenv(fpenv) do { \ #define __init_fpenv(fpenv) do { \
if (cpu_has_fxsr) { \ if (cpu_has_fxsr) { \
memset(&(fpenv)->fxsave, 0, sizeof(struct i387_fxsave_struct));\ memset(&(fpenv)->fxsave, 0, sizeof(struct i387_fxsave_struct));\
@ -104,14 +94,14 @@ typedef union thread_xstate FPU_ENV;
} \ } \
} while (0) } while (0)
// FPU MANAGEMENT DRESSED FOR IN KTHREAD/THREAD/PROCESS FPU USAGE FROM RTAI /* FPU MANAGEMENT DRESSED FOR IN KTHREAD/THREAD/PROCESS FPU USAGE FROM RTAI */
// Macros used for RTAI own kernel space tasks, where it uses the FPU env union /* Macros used for RTAI own kernel space tasks, where it uses the FPU env union */
#define init_fpenv(fpenv) do { __init_fpenv(&(fpenv)); } while (0) #define init_fpenv(fpenv) do { __init_fpenv(&(fpenv)); } while (0)
#define save_fpenv(fpenv) do { __save_fpenv(&(fpenv)); } while (0) #define save_fpenv(fpenv) do { __save_fpenv(&(fpenv)); } while (0)
#define restore_fpenv(fpenv) do { __restore_fpenv(&(fpenv)); } while (0) #define restore_fpenv(fpenv) do { __restore_fpenv(&(fpenv)); } while (0)
// Macros used for user space, where Linux might use eother a pointer or the FPU env union /* Macros used for user space, where Linux might use eother a pointer or the FPU env union */
#define init_hard_fpu(lnxtsk) do { \ #define init_hard_fpu(lnxtsk) do { \
init_hard_fpenv(); \ init_hard_fpenv(); \
set_lnxtsk_uses_fpu(lnxtsk); \ set_lnxtsk_uses_fpu(lnxtsk); \
@ -129,73 +119,18 @@ typedef union thread_xstate FPU_ENV;
set_lnxtsk_using_fpu(lnxtsk); \ set_lnxtsk_using_fpu(lnxtsk); \
} while (0) } while (0)
#else /* !CONFIG_RTAI_FPU_SUPPORT */
#define enable_fpu()
#define save_fpcr_and_enable_fpu(fpcr)
#define restore_fpcr(fpcr)
#define init_hard_fpenv()
#define init_fpenv(fpenv)
#define save_fpenv(fpenv)
#define restore_fpenv(fpenv)
#define init_hard_fpu(lnxtsk)
#define init_fpu(lnxtsk)
#define restore_fpu(lnxtsk)
#endif /* CONFIG_RTAI_FPU_SUPPORT */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#define set_lnxtsk_uses_fpu(lnxtsk) \
do { (lnxtsk)->used_math = 1; } while(0)
#define clear_lnxtsk_uses_fpu(lnxtsk) \
do { (lnxtsk)->used_math = 0; } while(0)
#define lnxtsk_uses_fpu(lnxtsk) ((lnxtsk)->used_math)
#define set_lnxtsk_using_fpu(lnxtsk) \
do { (lnxtsk)->flags |= PF_USEDFPU; } while(0)
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
#define set_lnxtsk_uses_fpu(lnxtsk) \
do { (lnxtsk)->used_math = 1; } while(0)
#define clear_lnxtsk_uses_fpu(lnxtsk) \
do { (lnxtsk)->used_math = 0; } while(0)
#define lnxtsk_uses_fpu(lnxtsk) ((lnxtsk)->used_math)
#define set_lnxtsk_using_fpu(lnxtsk) \
do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
// do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
#define set_lnxtsk_uses_fpu(lnxtsk) \ #define set_lnxtsk_uses_fpu(lnxtsk) \
do { set_stopped_child_used_math(lnxtsk); } while(0) do { set_stopped_child_used_math(lnxtsk); } while(0)
#define clear_lnxtsk_uses_fpu(lnxtsk) \ #define clear_lnxtsk_uses_fpu(lnxtsk) \
do { clear_stopped_child_used_math(lnxtsk); } while(0) do { clear_stopped_child_used_math(lnxtsk); } while(0)
#define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk)) #define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
#undef init_fpu #undef init_fpu
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/fpu-internal.h> #include <asm/fpu-internal.h>
#define rtai_set_fpu_used(lnxtsk) __thread_set_has_fpu(lnxtsk) #define rtai_set_fpu_used(lnxtsk) __thread_set_has_fpu(lnxtsk)
#else
#define rtai_set_fpu_used(lnxtsk) do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
#endif
#define set_lnxtsk_using_fpu(lnxtsk) \ #define set_lnxtsk_using_fpu(lnxtsk) \
do { rtai_set_fpu_used(lnxtsk); } while(0) do { rtai_set_fpu_used(lnxtsk); } while(0)
// do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) */
#endif /* !_RTAI_ASM_I386_FPU_H */ #endif /* !_RTAI_ASM_I386_FPU_H */

View file

@ -34,20 +34,10 @@
#include <asm/processor.h> #include <asm/processor.h>
#endif /* !__cplusplus */ #endif /* !__cplusplus */
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
typedef union i387_union FPU_ENV;
#define TASK_FPENV(tsk) (&(tsk)->thread.i387.fxsave)
#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34)
typedef union thread_xstate FPU_ENV;
#define TASK_FPENV(tsk) (&(tsk)->thread.xstate->fxsave)
#else
typedef union thread_xstate FPU_ENV; typedef union thread_xstate FPU_ENV;
#define TASK_FPENV(tsk) (&(tsk)->thread.fpu.state->fxsave) #define TASK_FPENV(tsk) (&(tsk)->thread.fpu.state->fxsave)
#endif
#ifdef CONFIG_RTAI_FPU_SUPPORT /* RAW FPU MANAGEMENT FOR USAGE FROM WHAT/WHEREVER RTAI DOES IN KERNEL */
// RAW FPU MANAGEMENT FOR USAGE FROM WHAT/WHEREVER RTAI DOES IN KERNEL
#define enable_fpu() do { \ #define enable_fpu() do { \
__asm__ __volatile__ ("clts"); \ __asm__ __volatile__ ("clts"); \
@ -68,7 +58,7 @@ typedef union thread_xstate FPU_ENV;
} \ } \
} while (0) } while (0)
// initialise the hard fpu unit directly /* initialise the hard fpu unit directly */
#define init_hard_fpenv() do { \ #define init_hard_fpenv() do { \
unsigned long __mxcsr; \ unsigned long __mxcsr; \
__asm__ __volatile__ ("clts; fninit"); \ __asm__ __volatile__ ("clts; fninit"); \
@ -76,7 +66,7 @@ typedef union thread_xstate FPU_ENV;
__asm__ __volatile__ ("ldmxcsr %0": : "m" (__mxcsr)); \ __asm__ __volatile__ ("ldmxcsr %0": : "m" (__mxcsr)); \
} while (0) } while (0)
// initialise the given fpenv union, without touching the related hard fpu unit /* initialise the given fpenv union, without touching the related hard fpu unit */
#define __init_fpenv(fpenv) do { \ #define __init_fpenv(fpenv) do { \
memset(fpenv, 0, sizeof(struct i387_fxsave_struct)); \ memset(fpenv, 0, sizeof(struct i387_fxsave_struct)); \
(fpenv)->cwd = 0x37f; \ (fpenv)->cwd = 0x37f; \
@ -84,7 +74,6 @@ typedef union thread_xstate FPU_ENV;
} while (0) } while (0)
/* taken from Linux i387.h */ /* taken from Linux i387.h */
static inline int __save_fpenv(struct i387_fxsave_struct __user *fx) static inline int __save_fpenv(struct i387_fxsave_struct __user *fx)
{ {
int err; int err;
@ -129,7 +118,7 @@ static inline int __restore_fpenv(struct i387_fxsave_struct *fx)
#define save_fpenv(fpenv) do { __save_fpenv(&(fpenv).fxsave); } while (0) #define save_fpenv(fpenv) do { __save_fpenv(&(fpenv).fxsave); } while (0)
#define restore_fpenv(fpenv) do { __restore_fpenv(&(fpenv).fxsave); } while (0) #define restore_fpenv(fpenv) do { __restore_fpenv(&(fpenv).fxsave); } while (0)
// FPU MANAGEMENT DRESSED FOR IN KTHREAD/THREAD/PROCESS FPU USAGE FROM RTAI /* FPU MANAGEMENT DRESSED FOR IN KTHREAD/THREAD/PROCESS FPU USAGE FROM RTAI */
#define init_hard_fpu(lnxtsk) do { \ #define init_hard_fpu(lnxtsk) do { \
init_hard_fpenv(); \ init_hard_fpenv(); \
@ -148,58 +137,18 @@ static inline int __restore_fpenv(struct i387_fxsave_struct *fx)
set_lnxtsk_using_fpu(lnxtsk); \ set_lnxtsk_using_fpu(lnxtsk); \
} while (0) } while (0)
#else /* !CONFIG_RTAI_FPU_SUPPORT */
#define enable_fpu()
#define save_fpcr_and_enable_fpu(fpcr)
#define restore_fpcr(fpcr)
#define init_hard_fpenv()
#define init_fpenv(fpenv)
#define save_fpenv(fpenv)
#define restore_fpenv(fpenv)
#define init_hard_fpu(lnxtsk)
#define init_fpu(lnxtsk)
#define restore_fpu(lnxtsk)
#endif /* CONFIG_RTAI_FPU_SUPPORT */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
#define set_lnxtsk_uses_fpu(lnxtsk) \
do { (lnxtsk)->used_math = 1; } while(0)
#define clear_lnxtsk_uses_fpu(lnxtsk) \
do { (lnxtsk)->used_math = 0; } while(0)
#define lnxtsk_uses_fpu(lnxtsk) ((lnxtsk)->used_math)
#define set_lnxtsk_using_fpu(lnxtsk) \
do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
// do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
#define set_lnxtsk_uses_fpu(lnxtsk) \ #define set_lnxtsk_uses_fpu(lnxtsk) \
do { set_stopped_child_used_math(lnxtsk); } while(0) do { set_stopped_child_used_math(lnxtsk); } while(0)
#define clear_lnxtsk_uses_fpu(lnxtsk) \ #define clear_lnxtsk_uses_fpu(lnxtsk) \
do { clear_stopped_child_used_math(lnxtsk); } while(0) do { clear_stopped_child_used_math(lnxtsk); } while(0)
#define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk)) #define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
#undef init_fpu #undef init_fpu
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/fpu-internal.h> #include <asm/fpu-internal.h>
#define rtai_set_fpu_used(lnxtsk) __thread_set_has_fpu(lnxtsk) #define rtai_set_fpu_used(lnxtsk) __thread_set_has_fpu(lnxtsk)
#else
#define rtai_set_fpu_used(lnxtsk) do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0)
#endif
#define set_lnxtsk_using_fpu(lnxtsk) \ #define set_lnxtsk_using_fpu(lnxtsk) \
do { rtai_set_fpu_used(lnxtsk); } while(0) //do { task_thread_info(lnxtsk)->status |= TS_USEDFPU; } while(0) do { rtai_set_fpu_used(lnxtsk); } while(0)
// do { (lnxtsk)->thread_info->status |= TS_USEDFPU; } while(0)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) */
#endif /* !_RTAI_ASM_X86_64_FPU_H */ #endif /* !_RTAI_ASM_X86_64_FPU_H */

View file

@ -120,7 +120,9 @@ extern "C" {
static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid) static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid)
{ {
extern void context_switch(void *, void *, void *); extern void context_switch(void *, void *, void *);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19) #if LINUX_VERSION_CODE > KERNEL_VERSION(3,14,0)
prev->thread.fpu_counter = 0;
#else
prev->fpu_counter = 0; prev->fpu_counter = 0;
#endif #endif
context_switch(0, prev, next); context_switch(0, prev, next);

View file

@ -1,192 +0,0 @@
/*
* Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _RTAI_BITS_H
#define _RTAI_BITS_H
#include <rtai_types.h>
#define RT_BITS_MAGIC 0x9ac24448 // nam2num("rtbits")
#define ALL_SET 0
#define ANY_SET 1
#define ALL_CLR 2
#define ANY_CLR 3
#define ALL_SET_AND_ANY_SET 4
#define ALL_SET_AND_ALL_CLR 5
#define ALL_SET_AND_ANY_CLR 6
#define ANY_SET_AND_ALL_CLR 7
#define ANY_SET_AND_ANY_CLR 8
#define ALL_CLR_AND_ANY_CLR 9
#define ALL_SET_OR_ANY_SET 10
#define ALL_SET_OR_ALL_CLR 11
#define ALL_SET_OR_ANY_CLR 12
#define ANY_SET_OR_ALL_CLR 13
#define ANY_SET_OR_ANY_CLR 14
#define ALL_CLR_OR_ANY_CLR 15
#define SET_BITS 0
#define CLR_BITS 1
#define SET_CLR_BITS 2
#define NOP_BITS 3
#define BITS_ERR (RTE_OBJINV) // same as semaphores
#define BITS_TIMOUT (RTE_TIMOUT) // same as semaphores
struct rt_bits_struct;
#ifdef __KERNEL__
#ifndef __cplusplus
typedef struct rt_bits_struct {
struct rt_queue queue; /* <= Must be first in struct. */
int magic;
int type; // to align mask to semaphore count, for easier uspace init
unsigned long mask;
} BITS;
#else /* __cplusplus */
extern "C" {
#endif /* !__cplusplus */
int __rtai_bits_init(void);
void __rtai_bits_exit(void);
void rt_bits_init(struct rt_bits_struct *bits, unsigned long mask);
int rt_bits_delete(struct rt_bits_struct *bits);
RTAI_SYSCALL_MODE unsigned long rt_get_bits(struct rt_bits_struct *bits);
RTAI_SYSCALL_MODE unsigned long rt_bits_reset(struct rt_bits_struct *bits, unsigned long mask);
RTAI_SYSCALL_MODE unsigned long rt_bits_signal(struct rt_bits_struct *bits, int setfun, unsigned long masks);
RTAI_SYSCALL_MODE int _rt_bits_wait(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask, int space);
static inline int rt_bits_wait(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask)
{
return _rt_bits_wait(bits, testfun, testmasks, exitfun, exitmasks, resulting_mask, 1);
}
RTAI_SYSCALL_MODE int _rt_bits_wait_if(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask, int space);
static inline int rt_bits_wait_if(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask)
{
return _rt_bits_wait_if(bits, testfun, testmasks, exitfun, exitmasks, resulting_mask, 1);
}
RTAI_SYSCALL_MODE int _rt_bits_wait_until(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME time, unsigned long *resulting_mask, int space);
static inline int rt_bits_wait_until(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME time, unsigned long *resulting_mask)
{
return _rt_bits_wait_until(bits, testfun, testmasks, exitfun, exitmasks, time, resulting_mask, 1);
}
RTAI_SYSCALL_MODE int _rt_bits_wait_timed(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME delay, unsigned long *resulting_mask, int space);
static inline int rt_bits_wait_timed(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME delay, unsigned long *resulting_mask)
{
return _rt_bits_wait_timed(bits, testfun, testmasks, exitfun, exitmasks, delay, resulting_mask, 1);
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#include <rtai_lxrt.h>
#define BITSIDX 0
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
RTAI_PROTO(struct rt_bits_struct *,rt_bits_init,(unsigned long name, unsigned long mask))
{
struct { unsigned long name, mask; } arg = { name, mask };
return (struct rt_bits_struct *)rtai_lxrt(BITSIDX, SIZARG, BITS_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_bits_delete,(struct rt_bits_struct *bits))
{
struct { struct rt_bits_struct *bits; } arg = { bits };
return rtai_lxrt(BITSIDX, SIZARG, BITS_DELETE, &arg).i[LOW];
}
RTAI_PROTO(unsigned long, rt_get_bits,(struct rt_bits_struct *bits))
{
struct { struct rt_bits_struct *bits; } arg = { bits };
return rtai_lxrt(BITSIDX, SIZARG, BITS_GET, &arg).i[LOW];
}
RTAI_PROTO(unsigned long, rt_bits_reset,(struct rt_bits_struct *bits, unsigned long mask))
{
struct { struct rt_bits_struct *bits; unsigned long mask; } arg = { bits, mask };
return (unsigned long)rtai_lxrt(BITSIDX, SIZARG, BITS_RESET, &arg).i[LOW];
}
RTAI_PROTO(unsigned long, rt_bits_signal,(struct rt_bits_struct *bits, int setfun, unsigned long masks))
{
struct { struct rt_bits_struct *bits; long setfun; unsigned long masks; } arg = { bits, setfun, masks };
return rtai_lxrt(BITSIDX, SIZARG, BITS_SIGNAL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_bits_wait,(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask))
{
struct { struct rt_bits_struct *bits; long testfun; unsigned long testmasks; long exitfun; unsigned long exitmasks; unsigned long *resulting_mask; long space; } arg = { bits, testfun, testmasks, exitfun, exitmasks, resulting_mask, 0 };
return rtai_lxrt(BITSIDX, SIZARG, BITS_WAIT, &arg).i[LOW];
}
RTAI_PROTO(int, rt_bits_wait_if,(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask))
{
struct { struct rt_bits_struct *bits; long testfun; unsigned long testmasks; long exitfun; unsigned long exitmasks; unsigned long *resulting_mask; long space; } arg = { bits, testfun, testmasks, exitfun, exitmasks, resulting_mask, 0 };
return rtai_lxrt(BITSIDX, SIZARG, BITS_WAIT_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_bits_wait_until,(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME time, unsigned long *resulting_mask))
{
struct { struct rt_bits_struct *bits; long testfun; unsigned long testmasks; long exitfun; unsigned long exitmasks; RTIME time; unsigned long *resulting_mask; long space; } arg = { bits, testfun, testmasks, exitfun, exitmasks, time, resulting_mask, 0 };
return rtai_lxrt(BITSIDX, SIZARG, BITS_WAIT_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_bits_wait_timed,(struct rt_bits_struct *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME delay, unsigned long *resulting_mask))
{
struct { struct rt_bits_struct *bits; long testfun; unsigned long testmasks; long exitfun; unsigned long exitmasks; RTIME delay; unsigned long *resulting_mask; long space; } arg = { bits, testfun, testmasks, exitfun, exitmasks, delay, resulting_mask, 0 };
return rtai_lxrt(BITSIDX, SIZARG, BITS_WAIT_TIMED, &arg).i[LOW];
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#if !defined(__KERNEL__) || defined(__cplusplus)
typedef struct rt_bits_struct {
int opaque;
} BITS;
#endif /* !__KERNEL__ || __cplusplus */
#endif /* !_RTAI_BITS_H */

View file

@ -231,28 +231,6 @@
#define BITS_WAIT_UNTIL 142 #define BITS_WAIT_UNTIL 142
#define BITS_WAIT_TIMED 143 #define BITS_WAIT_TIMED 143
// typed mail boxes
#define TBX_INIT 144
#define TBX_DELETE 145
#define NAMED_TBX_INIT 146
#define NAMED_TBX_DELETE 147
#define TBX_SEND 148
#define TBX_SEND_IF 149
#define TBX_SEND_UNTIL 150
#define TBX_SEND_TIMED 151
#define TBX_RECEIVE 152
#define TBX_RECEIVE_IF 153
#define TBX_RECEIVE_UNTIL 154
#define TBX_RECEIVE_TIMED 155
#define TBX_BROADCAST 156
#define TBX_BROADCAST_IF 157
#define TBX_BROADCAST_UNTIL 158
#define TBX_BROADCAST_TIMED 159
#define TBX_URGENT 160
#define TBX_URGENT_IF 161
#define TBX_URGENT_UNTIL 162
#define TBX_URGENT_TIMED 163
// pqueue // pqueue
#define MQ_OPEN 164 #define MQ_OPEN 164
#define MQ_RECEIVE 165 #define MQ_RECEIVE 165

View file

@ -34,121 +34,69 @@
#ifdef __attribute_used__ #ifdef __attribute_used__
#undef __attribute_used__ #undef __attribute_used__
#endif #endif
#include <features.h>
__BEGIN_DECLS #ifdef __cplusplus
extern "C" {
/* Get machine-dependent HUGE_VAL value (returned on overflow).
On all IEEE754 machines, this is +Infinity. */
#include <bits/huge_val.h>
/* Get machine-dependent NAN value (returned for some domain errors). */
#ifdef __USE_ISOC99
# include <bits/nan.h>
#endif #endif
/* Get general and ISO C99 specific information. */
#include <bits/mathdef.h>
extern double acos(double);
extern double asin(double);
extern double atan(double);
extern double atan2(double, double);
extern double ceil(double);
extern double copysign(double, double);
extern double cos(double);
extern double cosh(double);
extern double exp(double);
extern double expm1(double);
extern double fabs(double);
extern int finite(double);
extern double floor(double);
extern double fmod(double, double);
extern double frexp(double, int *);
extern double log(double);
extern double log10(double);
extern double modf(double, double *);
extern double pow(double, double);
extern double scalbn(double, long);
extern double sin(double);
extern double sinh(double);
extern double sqrt(double);
extern double tan(double);
extern double tanh(double);
extern double acosh(double);
extern double asinh(double);
extern double atanh(double);
extern double cabs(double __complex__ x);
extern double cbrt(double);
extern double drem(double, double);
extern double erf(double);
extern double erfc(double);
extern double gamma(double);
extern double gamma_r(double, int *);
extern double hypot(double, double);
extern int ilogb(double);
extern double j0(double);
extern double j1(double);
extern double jn(int, double);
extern double ldexp(double, int);
extern double lgamma(double);
extern double lgamma_r(double, int *);
extern double log1p(double);
extern double nextafter(double, double);
extern double remainder(double, double);
extern double rint(double);
extern double scalb(double, double);
extern double significand(double);
extern double y0(double);
extern double y1(double);
extern double yn(int, double);
extern int libm_errno;
/* The file <bits/mathcalls.h> contains the prototypes for all the
actual math functions. These macros are used for those prototypes,
so we can easily declare each function as both `name' and `__name',
and can declare the float versions `namef' and `__namef'. */
#define __MATHCALL(function,suffix, args) \
__MATHDECL (_Mdouble_,function,suffix, args)
#define __MATHDECL(type, function,suffix, args) \
__MATHDECL_1(type, function,suffix, args); \
__MATHDECL_1(type, __CONCAT(__,function),suffix, args)
#define __MATHCALLX(function,suffix, args, attrib) \
__MATHDECLX (_Mdouble_,function,suffix, args, attrib)
#define __MATHDECLX(type, function,suffix, args, attrib) \
__MATHDECL_1(type, function,suffix, args) __attribute__ (attrib); \
__MATHDECL_1(type, __CONCAT(__,function),suffix, args) __attribute__ (attrib)
#define __MATHDECL_1(type, function,suffix, args) \
extern type __MATH_PRECNAME(function,suffix) args __THROW
#define _Mdouble_ double
#define __MATH_PRECNAME(name,r) __CONCAT(name,r)
// added for gcc-3.2
#define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_STD
#define _Mdouble_END_NAMESPACE __END_NAMESPACE_STD
// end added for gcc-3.2
#include <bits/mathcalls.h>
#undef _Mdouble_
// added for gcc-3.2
#undef _Mdouble_BEGIN_NAMESPACE
#undef _Mdouble_END_NAMESPACE
// end added for gcc-3.2
#undef __MATH_PRECNAME
#if defined __USE_MISC || defined __USE_ISOC99
/* Include the file of declarations again, this time using `float'
instead of `double' and appending f to each function name. */
# ifndef _Mfloat_
# define _Mfloat_ float
# endif
# define _Mdouble_ _Mfloat_
# ifdef __STDC__
# define __MATH_PRECNAME(name,r) name##f##r
# else
# define __MATH_PRECNAME(name,r) name/**/f/**/r
# endif
// added for gcc-3.2
#define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99
#define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99
// end added for gcc-3.2
# include <bits/mathcalls.h>
# undef _Mdouble_
// added for gcc-3.2
# undef _Mdouble_BEGIN_NAMESPACE
# undef _Mdouble_END_NAMESPACE
// end added for gcc-3.2
# undef __MATH_PRECNAME
# if (__STDC__ - 0 || __GNUC__ - 0) && !defined __NO_LONG_DOUBLE_MATH
/* Include the file of declarations again, this time using `long double'
instead of `double' and appending l to each function name. */
# ifndef _Mlong_double_
# define _Mlong_double_ long double
# endif
# define _Mdouble_ _Mlong_double_
# ifdef __STDC__
# define __MATH_PRECNAME(name,r) name##l##r
# else
# define __MATH_PRECNAME(name,r) name/**/l/**/r
# endif
// added for gcc-3.2
#define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99
#define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99
// end added for gcc-3.2
# include <bits/mathcalls.h>
# undef _Mdouble_
// added for gcc-3.2
# undef _Mdouble_BEGIN_NAMESPACE
# undef _Mdouble_END_NAMESPACE
// end added for gcc-3.2
# undef __MATH_PRECNAME
# endif /* __STDC__ || __GNUC__ */
#endif /* Use misc or ISO C99. */
#undef __MATHDECL_1
#undef __MATHDECL
#undef __MATHCALL
#if defined __USE_MISC || defined __USE_XOPEN
/* This variable is used by `gamma' and `lgamma'. */ /* This variable is used by `gamma' and `lgamma'. */
extern int signgam; extern int signgam;
#endif
/* ISO C99 defines some generic macros which work on any data type. */
#if defined(__USE_ISOC99) && __USE_ISOC99 #if defined(__USE_ISOC99) && __USE_ISOC99
/* Get the architecture specific values describing the floating-point /* Get the architecture specific values describing the floating-point
@ -239,16 +187,16 @@ enum
# define isnormal(x) (fpclassify (x) == FP_NORMAL) # define isnormal(x) (fpclassify (x) == FP_NORMAL)
/* Return nonzero value if X is a NaN. We could use `fpclassify' but /* Return nonzero value if X is a NaN. We could use `fpclassify' but
we already have this functions `__isnan' and it is faster. */ we already have this functions `__builtin_isnan' and it is faster. */
# ifdef __NO_LONG_DOUBLE_MATH # ifdef __NO_LONG_DOUBLE_MATH
# define isnan(x) \ # define isnan(x) \
(sizeof (x) == sizeof (float) ? __isnanf (x) : __isnan (x)) (sizeof (x) == sizeof (float) ? __builtin_isnanf (x) : __builtin_isnan (x))
# else # else
# define isnan(x) \ # define isnan(x) \
(sizeof (x) == sizeof (float) \ (sizeof (x) == sizeof (float) \
? __isnanf (x) \ ? __builtin_isnanf (x) \
: sizeof (x) == sizeof (double) \ : sizeof (x) == sizeof (double) \
? __isnan (x) : __isnanl (x)) ? __builtin_isnan (x) : __builtin_isnanl (x))
# endif # endif
/* Return nonzero value is X is positive or negative infinity. */ /* Return nonzero value is X is positive or negative infinity. */
@ -442,21 +390,16 @@ extern int matherr (struct exception *__exc);
#endif #endif
__END_DECLS
/* Missing declarations */ /* Missing declarations */
struct complex {
double x;
double y;
};
double cabs __P((struct complex));
double gamma_r(double x, int *signgamp); /* wrapper lgamma_r */ double gamma_r(double x, int *signgamp); /* wrapper lgamma_r */
long int rinttol(double x); long int rinttol(double x);
long int roundtol(double x); long int roundtol(double x);
#ifdef __cplusplus
}
#endif
#endif /* !_RTAI_MATH_H */ #endif /* !_RTAI_MATH_H */

View file

@ -49,9 +49,7 @@ struct rt_registry_entry {
#define IS_SPL 3 #define IS_SPL 3
#define IS_MBX 4 #define IS_MBX 4
#define IS_PRX 5 #define IS_PRX 5
#define IS_BIT 6 #define IS_HPCK 6
#define IS_TBX 7
#define IS_HPCK 8
#ifdef __KERNEL__ #ifdef __KERNEL__

View file

@ -47,9 +47,7 @@
#include <rtai_scb.h> #include <rtai_scb.h>
#include <rtai_mbx.h> #include <rtai_mbx.h>
#include <rtai_msg.h> #include <rtai_msg.h>
#include <rtai_tbx.h>
#include <rtai_mq.h> #include <rtai_mq.h>
#include <rtai_bits.h>
#include <rtai_tasklets.h> #include <rtai_tasklets.h>
#include <rtai_fifos.h> #include <rtai_fifos.h>
#include <rtai_netrpc.h> #include <rtai_netrpc.h>
@ -543,9 +541,6 @@ static inline XHDL *__set_exit_handler(RT_TASK *task, void (*fun) (void *, int),
static inline int rtai_init_features (void) static inline int rtai_init_features (void)
{ {
#ifdef CONFIG_RTAI_LEDS_BUILTIN
__rtai_leds_init();
#endif /* CONFIG_RTAI_LEDS_BUILTIN */
#ifdef CONFIG_RTAI_SEM_BUILTIN #ifdef CONFIG_RTAI_SEM_BUILTIN
__rtai_sem_init(); __rtai_sem_init();
#endif /* CONFIG_RTAI_SEM_BUILTIN */ #endif /* CONFIG_RTAI_SEM_BUILTIN */
@ -555,15 +550,9 @@ static inline int rtai_init_features (void)
#ifdef CONFIG_RTAI_MBX_BUILTIN #ifdef CONFIG_RTAI_MBX_BUILTIN
__rtai_mbx_init(); __rtai_mbx_init();
#endif /* CONFIG_RTAI_MBX_BUILTIN */ #endif /* CONFIG_RTAI_MBX_BUILTIN */
#ifdef CONFIG_RTAI_TBX_BUILTIN
__rtai_msg_queue_init();
#endif /* CONFIG_RTAI_TBX_BUILTIN */
#ifdef CONFIG_RTAI_MQ_BUILTIN #ifdef CONFIG_RTAI_MQ_BUILTIN
__rtai_mq_init(); __rtai_mq_init();
#endif /* CONFIG_RTAI_MQ_BUILTIN */ #endif /* CONFIG_RTAI_MQ_BUILTIN */
#ifdef CONFIG_RTAI_BITS_BUILTIN
__rtai_bits_init();
#endif /* CONFIG_RTAI_BITS_BUILTIN */
#ifdef CONFIG_RTAI_TASKLETS_BUILTIN #ifdef CONFIG_RTAI_TASKLETS_BUILTIN
__rtai_tasklets_init(); __rtai_tasklets_init();
#endif /* CONFIG_RTAI_TASKLETS_BUILTIN */ #endif /* CONFIG_RTAI_TASKLETS_BUILTIN */
@ -579,9 +568,6 @@ static inline int rtai_init_features (void)
#ifdef CONFIG_RTAI_MATH_BUILTIN #ifdef CONFIG_RTAI_MATH_BUILTIN
__rtai_math_init(); __rtai_math_init();
#endif /* CONFIG_RTAI_MATH_BUILTIN */ #endif /* CONFIG_RTAI_MATH_BUILTIN */
#ifdef CONFIG_RTAI_USI
printk(KERN_INFO "RTAI[usi]: enabled.\n");
#endif /* CONFIG_RTAI_USI */
return 0; return 0;
} }
@ -603,15 +589,9 @@ static inline void rtai_cleanup_features (void) {
#ifdef CONFIG_RTAI_TASKLETS_BUILTIN #ifdef CONFIG_RTAI_TASKLETS_BUILTIN
__rtai_tasklets_exit(); __rtai_tasklets_exit();
#endif /* CONFIG_RTAI_TASKLETS_BUILTIN */ #endif /* CONFIG_RTAI_TASKLETS_BUILTIN */
#ifdef CONFIG_RTAI_BITS_BUILTIN
__rtai_bits_exit();
#endif /* CONFIG_RTAI_BITS_BUILTIN */
#ifdef CONFIG_RTAI_MQ_BUILTIN #ifdef CONFIG_RTAI_MQ_BUILTIN
__rtai_mq_exit(); __rtai_mq_exit();
#endif /* CONFIG_RTAI_MQ_BUILTIN */ #endif /* CONFIG_RTAI_MQ_BUILTIN */
#ifdef CONFIG_RTAI_TBX_BUILTIN
__rtai_msg_queue_exit();
#endif /* CONFIG_RTAI_TBX_BUILTIN */
#ifdef CONFIG_RTAI_MBX_BUILTIN #ifdef CONFIG_RTAI_MBX_BUILTIN
__rtai_mbx_exit(); __rtai_mbx_exit();
#endif /* CONFIG_RTAI_MBX_BUILTIN */ #endif /* CONFIG_RTAI_MBX_BUILTIN */
@ -621,9 +601,6 @@ static inline void rtai_cleanup_features (void) {
#ifdef CONFIG_RTAI_SEM_BUILTIN #ifdef CONFIG_RTAI_SEM_BUILTIN
__rtai_sem_exit(); __rtai_sem_exit();
#endif /* CONFIG_RTAI_SEM_BUILTIN */ #endif /* CONFIG_RTAI_SEM_BUILTIN */
#ifdef CONFIG_RTAI_LEDS_BUILTIN
__rtai_leds_exit();
#endif /* CONFIG_RTAI_LEDS_BUILTIN */
} }
int rt_check_current_stack(void); int rt_check_current_stack(void);
@ -647,30 +624,6 @@ int rt_kthread_init_cpuid(RT_TASK *task,
#else /* !__KERNEL__ */ #else /* !__KERNEL__ */
#if 0
#include <rtai_version.h>
#include <rtai_lxrt.h>
#include <rtai_sched.h>
#include <rtai_malloc.h>
#include <rtai_trace.h>
#include <rtai_leds.h>
#include <rtai_sem.h>
#include <rtai_rwl.h>
#include <rtai_spl.h>
#include <rtai_scb.h>
#include <rtai_mbx.h>
#include <rtai_msg.h>
#include <rtai_tbx.h>
#include <rtai_mq.h>
#include <rtai_bits.h>
#include <rtai_wd.h>
#include <rtai_tasklets.h>
#include <rtai_fifos.h>
#include <rtai_netrpc.h>
#include <rtai_shm.h>
#include <rtai_usi.h>
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* !_RTAI_SCHEDCORE_H */ #endif /* !_RTAI_SCHEDCORE_H */

View file

@ -1,326 +0,0 @@
/*
* Copyright (C) 2005 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef _RTAI_RT_MSGQ_H
#define _RTAI_RT_MSGQ_H
#include <linux/version.h>
#include <rtai_sem.h>
#define MSGQ_INIT TBX_INIT
#define MSGQ_DELETE TBX_DELETE
#define NAMED_MSGQ_INIT NAMED_TBX_INIT
#define NAMED_MSGQ_DELETE NAMED_TBX_DELETE
#define MSG_SEND TBX_SEND
#define MSG_SEND_IF TBX_SEND_IF
#define MSG_SEND_UNTIL TBX_SEND_UNTIL
#define MSG_SEND_TIMED TBX_SEND_TIMED
#define MSG_RECEIVE TBX_RECEIVE
#define MSG_RECEIVE_IF TBX_RECEIVE_IF
#define MSG_RECEIVE_UNTIL TBX_RECEIVE_UNTIL
#define MSG_RECEIVE_TIMED TBX_RECEIVE_TIMED
#define MSG_BROADCAST TBX_BROADCAST
#define MSG_BROADCAST_IF TBX_BROADCAST_IF
#define MSG_BROADCAST_UNTIL TBX_BROADCAST_UNTIL
#define MSG_BROADCAST_TIMED TBX_BROADCAST_TIMED
#define MSG_EVDRP TBX_URGENT
#define TBX RT_MSGQ
#ifdef __KERNEL__
typedef struct rt_msgh {
void *malloc;
int broadcast;
int size;
int priority;
void *next;
} RT_MSGH;
#define RT_MSGH_SIZE (sizeof(RT_MSGH))
typedef struct rt_msg {
RT_MSGH hdr;
char msg[1];
} RT_MSG;
typedef struct rt_msgq {
int nmsg;
int fastsize;
int slot;
void **slots;
void *firstmsg;
SEM receivers, senders;
SEM received, freslots;
SEM broadcast;
spinlock_t lock;
} RT_MSGQ;
#include <linux/types.h>
#ifdef __cplusplus
extern "C" {
#endif /* !__cplusplus */
int __rtai_msg_queue_init(void);
void __rtai_msg_queue_exit(void);
RTAI_SYSCALL_MODE int rt_msgq_init(RT_MSGQ *msgq, int nmsg, int msg_size);
RTAI_SYSCALL_MODE int rt_msgq_delete(RT_MSGQ *msgq);
RTAI_SYSCALL_MODE RT_MSGQ *_rt_named_msgq_init(unsigned long msgq_name, int nmsg, int size);
static inline RT_MSGQ *rt_named_msgq_init(const char *msgq_name, int nmsg, int size)
{
return _rt_named_msgq_init(nam2num(msgq_name), nmsg, size);
}
RTAI_SYSCALL_MODE int rt_named_msgq_delete(RT_MSGQ *msgq);
RTAI_SYSCALL_MODE int _rt_msg_send(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, int space);
static inline int rt_msg_send(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri)
{
return _rt_msg_send(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_send_if(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, int space);
static inline int rt_msg_send_if(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri)
{
return _rt_msg_send_if(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_send_until(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME until, int space);
static inline int rt_msg_send_until(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME until)
{
return _rt_msg_send_until(msgq, msg, msg_size, msgpri, until, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_send_timed(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME delay, int space);
static inline int rt_msg_send_timed(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME delay)
{
return _rt_msg_send_timed(msgq, msg, msg_size, msgpri, delay, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_receive(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, int space);
static inline int rt_msg_receive(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri)
{
return _rt_msg_receive(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_receive_if(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, int space);
static inline int rt_msg_receive_if(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri)
{
return _rt_msg_receive_if(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_receive_until(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, RTIME until, int space);
static inline int rt_msg_receive_until(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, RTIME until)
{
return _rt_msg_receive_until(msgq, msg, msg_size, msgpri, until, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_receive_timed(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, RTIME delay, int space);
static inline int rt_msg_receive_timed(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, RTIME delay)
{
return _rt_msg_receive_timed(msgq, msg, msg_size, msgpri, delay, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_evdrp(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri, int space);
static inline int rt_msg_evdrp(RT_MSGQ *msgq, void *msg, int msg_size, int *msgpri)
{
return _rt_msg_evdrp(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, int space);
static inline int rt_msg_broadcast(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri)
{
return _rt_msg_broadcast(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast_if(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, int space);
static inline int rt_msg_broadcast_if(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri)
{
return _rt_msg_broadcast_if(msgq, msg, msg_size, msgpri, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast_until(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME until, int space);
static inline int rt_msg_broadcast_until(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME until)
{
return _rt_msg_broadcast_until(msgq, msg, msg_size, msgpri, until, 1);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast_timed(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME delay, int space);
static inline int rt_msg_broadcast_delay(RT_MSGQ *msgq, void *msg, int msg_size, int msgpri, RTIME delay)
{
return _rt_msg_broadcast_until(msgq, msg, msg_size, msgpri, delay, 1);
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !__KERNEL__ */
#include <signal.h>
#include <rtai_lxrt.h>
struct rt_msgh;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct rt_msgq {
int dummy;
} RT_MSGQ;
RTAI_PROTO(RT_MSGQ *, rt_msgq_init, (unsigned long msgq, int nmsg, int msg_size))
{
struct { unsigned long msgq; long nmsg; long msg_size; } arg = { msgq, nmsg, msg_size };
return rtai_lxrt(BIDX, SIZARG, NAMED_MSGQ_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_msgq_delete, (RT_MSGQ *msgq))
{
struct { RT_MSGQ *msgq; } arg = { msgq };
return rtai_lxrt(BIDX, SIZARG, NAMED_MSGQ_DELETE, &arg).i[LOW];
}
RTAI_PROTO(RT_MSGQ *, rt_named_msgq_init,(const char *name, int nmsg, int size))
{
struct { unsigned long name; long nmsg; long size; } arg = { nam2num(name), nmsg, size };
return rtai_lxrt(BIDX, SIZARG, NAMED_MSGQ_INIT, &arg).v[LOW];
}
RTAI_PROTO(int, rt_named_msgq_delete, (RT_MSGQ *msgq))
{
struct { RT_MSGQ *msgq; } arg = { msgq };
return rtai_lxrt(BIDX, SIZARG, NAMED_MSGQ_DELETE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_send, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_SEND, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_send_if, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_SEND_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_send_until, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio, RTIME until))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; RTIME until; long space; } arg = { msgq, msg, msg_size, msgprio, until, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_SEND_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_send_timed, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio, RTIME delay))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; RTIME delay; long space; } arg = { msgq, msg, msg_size, msgprio, delay, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_SEND_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_receive, (RT_MSGQ *msgq, void *msg, int msg_size, int *msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; int *msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_RECEIVE, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_receive_if, (RT_MSGQ *msgq, void *msg, int msg_size, int *msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; int *msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_RECEIVE_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_receive_until, (RT_MSGQ *msgq, void *msg, int msg_size, int *msgprio, RTIME until))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; int *msgprio; RTIME until; long space; } arg = { msgq, msg, msg_size, msgprio, until, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_RECEIVE_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_receive_timed, (RT_MSGQ *msgq, void *msg, int msg_size, int *msgprio, RTIME delay))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; int *msgprio; RTIME delay; long space; } arg = { msgq, msg, msg_size, msgprio, delay, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_RECEIVE_TIMED, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_evdrp, (RT_MSGQ *msgq, void *msg, int msg_size, int *msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; int *msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_EVDRP, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_broadcast, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_BROADCAST, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_broadcast_if, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; long space; } arg = { msgq, msg, msg_size, msgprio, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_BROADCAST_IF, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_broadcast_until, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio, RTIME until))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; RTIME until; long space; } arg = { msgq, msg, msg_size, msgprio, until, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_BROADCAST_UNTIL, &arg).i[LOW];
}
RTAI_PROTO(int, rt_msg_broadcast_timed, (RT_MSGQ *msgq, void *msg, int msg_size, int msgprio, RTIME delay))
{
struct { RT_MSGQ *msgq; void *msg; long msg_size; long msgprio; RTIME delay; long space; } arg = { msgq, msg, msg_size, msgprio, delay, 0 };
return rtai_lxrt(BIDX, SIZARG, MSG_BROADCAST_TIMED, &arg).i[LOW];
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __KERNEL__ */
#define rt_tbx_init(tbx, size, flags) rt_msgq_init(tbx, size, 0)
#define rt_tbx_delete(tbx) rt_msgq_delete(tbx)
#define rt_tbx_send(tbx, msg, msg_size) rt_msg_send(tbx, msg, msg_size, 1)
#define rt_tbx_send_if(tbx, msg, msg_size) rt_msg_send_if(tbx, msg, msg_size, 1)
#define rt_tbx_send_until(tbx, msg, msg_size, until) rt_msg_send_until(tbx, msg, msg_size, 1, until)
#define rt_tbx_send_timed(tbx, msg, msg_size, delay) rt_msg_send_timed(tbx, msg, msg_size, 1, delay)
#define rt_tbx_receive(tbx, msg, msg_size) rt_msg_receive(tbx, msg, msg_size, 0)
#define rt_tbx_receive_if(tbx, msg, msg_size) rt_msg_receive_if(tbx, msg, msg_size, 0)
#define rt_tbx_receive_until(tbx, msg, msg_size, until) rt_msg_receive_until(tbx, msg, msg_size, 0, until)
#define rt_tbx_receive_timed(tbx, msg, msg_size, delay) rt_msg_receive_timed(tbx, msg, msg_size, 0, delay)
#define rt_tbx_broadcast(tbx, msg, msg_size) rt_msg_broadcast(tbx, msg, msg_size, 0)
#define rt_tbx_broadcast_if(tbx, msg, msg_size) rt_msg_broadcast_if(tbx, msg, msg_size, 0)
#define rt_tbx_broadcast_until(tbx, msg, msg_size, until) rt_msg_broadcast_until(tbx, msg, msg_size, 0, until)
#define rt_tbx_broadcast_timed(tbx, msg, msg_size, delay) rt_msg_broadcast_timed(tbx, msg, msg_size, 0, delay)
#define rt_tbx_urgent(tbx, msg, msg_size) rt_msg_send(tbx, msg, msg_size, 0)
#define rt_tbx_urgent_if(tbx, msg, msg_size) rt_msg_send_if(tbx, msg, msg_size, 0)
#define rt_tbx_urgent_until(tbx, msg, msg_size, until) rt_msg_send_until(tbx, msg, msg_size, 0, until)
#define rt_tbx_urgent_timed(tbx, msg, msg_size, delay) rt_msg_send_timed(tbx, msg, msg_size, 0, delay)
#endif /* !_RTAI_RT_MSGQ_H */

View file

@ -323,17 +323,7 @@ static inline ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout) static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
{ {
#ifdef CONFIG_RTAI_RTDM_SELECT
struct xnselector *selector;
int ret;
selector = rt_malloc(sizeof(struct xnselector));
xnselector_init(selector);
ret = __rt_dev_select(nfds, rfds, wfds, efds, timeout, selector, 1);
xnselector_destroy(selector);
return ret;
#else
return -ENOSYS; return -ENOSYS;
#endif
} }
#else /* !__KERNEL__ */ #else /* !__KERNEL__ */
@ -445,12 +435,7 @@ static inline ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout) static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
{ {
#ifdef CONFIG_RTAI_RTDM_SELECT
struct { long nfds; fd_set *rfds; fd_set *wfds; fd_set *efds; nanosecs_rel_t timeout; } arg = { nfds, rfds, wfds, efds, timeout };
return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_select, &arg);
#else
return -ENOSYS; return -ENOSYS;
#endif
} }
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -84,77 +84,6 @@ static inline void __FD_ZERO__(__kernel_fd_set *__p)
} }
} }
#ifdef CONFIG_RTAI_RTDM_SELECT
struct xnselect {
xnqueue_t bindings;
};
#define DECLARE_XNSELECT(name) struct xnselect name
struct xnselect_binding {
struct xnselector *selector;
struct xnselect *fd;
unsigned type;
unsigned bit_index;
xnholder_t link; /* link in selected fds list. */
xnholder_t slink; /* link in selector list */
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void xnselect_init(struct xnselect *select_block);
int xnselect_bind(struct xnselect *select_block,
struct xnselect_binding *binding,
struct xnselector *selector,
unsigned type,
unsigned bit_index,
unsigned state);
int __xnselect_signal(struct xnselect *select_block, unsigned state);
/**
* Signal a file descriptor state change.
*
* @param select_block pointer to an @a xnselect structure representing the file
* descriptor whose state changed;
* @param state new value of the state.
*
* @retval 1 if rescheduling is needed;
* @retval 0 otherwise.
*/
static inline int
xnselect_signal(struct xnselect *select_block, unsigned state)
{
if (!emptyq_p(&select_block->bindings))
return __xnselect_signal(select_block, state);
return 0;
}
void xnselect_destroy(struct xnselect *select_block);
int xnselector_init(struct xnselector *selector);
int xnselect(struct xnselector *selector,
fd_set *out_fds[XNSELECT_MAX_TYPES],
fd_set *in_fds[XNSELECT_MAX_TYPES],
int nfds,
xnticks_t timeout, xntmode_t timeout_mode);
void xnselector_destroy(struct xnselector *selector);
int xnselect_mount(void);
int xnselect_umount(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* !CONFIG_RTAI_RTDM_SELECT */
struct xnselector; struct xnselector;
#define DECLARE_XNSELECT(name) #define DECLARE_XNSELECT(name)
#define xnselect_init(block) #define xnselect_init(block)
@ -162,7 +91,6 @@ struct xnselector;
({ -EBADF; }) ({ -EBADF; })
#define xnselect_signal(block, state) ({ int __ret = 0; __ret; }) #define xnselect_signal(block, state) ({ int __ret = 0; __ret; })
#define xnselect_destroy(block) #define xnselect_destroy(block)
#endif /* !CONFIG_RTAI_RTDM_SELECT */
/*@}*/ /*@}*/

View file

@ -30,12 +30,6 @@
#include <rtai_schedcore.h> #include <rtai_schedcore.h>
#define CONFIG_RTAI_OPT_PERVASIVE
#ifndef CONFIG_RTAI_DEBUG_RTDM
#define CONFIG_RTAI_DEBUG_RTDM 0
#endif
#define RTAI_DEBUG(subsystem) (CONFIG_RTAI_DEBUG_##subsystem > 0) #define RTAI_DEBUG(subsystem) (CONFIG_RTAI_DEBUG_##subsystem > 0)
#define RTAI_ASSERT(subsystem, cond, action) do { \ #define RTAI_ASSERT(subsystem, cond, action) do { \
@ -370,9 +364,6 @@ typedef struct xnstat_counter {
#define xnstat_counter_inc(c) ((c)->counter++) #define xnstat_counter_inc(c) ((c)->counter++)
typedef struct xnintr { typedef struct xnintr {
#ifdef CONFIG_RTAI_RTDM_SHIRQ
struct xnintr *next;
#endif /* CONFIG_RTAI_RTDM_SHIRQ */
unsigned unhandled; unsigned unhandled;
xnisr_t isr; xnisr_t isr;
void *cookie; void *cookie;
@ -594,24 +585,8 @@ static inline void xnsynch_sleep_on(void *synch, xnticks_t timeout, xntmode_t ti
#define rthal_apc_schedule(apc) \ #define rthal_apc_schedule(apc) \
rt_pend_linux_srq((apc)) rt_pend_linux_srq((apc))
#ifdef CONFIG_RTAI_RTDM_SELECT
#define SELECT_SIGNAL(select_block, state) \
do { \
spl_t flags; \
xnlock_get_irqsave(&nklock, flags); \
if (xnselect_signal(select_block, state) && state) { \
xnpod_schedule(); \
} \
xnlock_put_irqrestore(&nklock, flags); \
} while (0)
#else
#define SELECT_SIGNAL(select_block, state) do { } while (0) #define SELECT_SIGNAL(select_block, state) do { } while (0)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
#define __WORK_INITIALIZER(n,f,d) { \ #define __WORK_INITIALIZER(n,f,d) { \

View file

@ -1,9 +1,5 @@
OPTDIRS = OPTDIRS =
if CONFIG_RTAI_BITS
OPTDIRS += bits
endif
if CONFIG_RTAI_FIFOS if CONFIG_RTAI_FIFOS
OPTDIRS += fifos OPTDIRS += fifos
endif endif
@ -24,10 +20,6 @@ if CONFIG_RTAI_MBX
OPTDIRS += mbx OPTDIRS += mbx
endif endif
if CONFIG_RTAI_TBX
OPTDIRS += tbx
endif
if CONFIG_RTAI_MQ if CONFIG_RTAI_MQ
OPTDIRS += mq OPTDIRS += mq
endif endif

View file

@ -1,48 +0,0 @@
moduledir = @RTAI_MODULE_DIR@
modext = @RTAI_MODULE_EXT@
libbits_a_SOURCES = bits.c
if CONFIG_KBUILD
if CONFIG_RTAI_BITS_BUILTIN
rtai_bits.ko:
else
rtai_bits.ko: @RTAI_KBUILD_ENV@
rtai_bits.ko: $(libbits_a_SOURCES)
@RTAI_KBUILD_TOP@ \
@RTAI_KBUILD_CMD@ \
@RTAI_KBUILD_BOTTOM@
clean-local:
@RTAI_KBUILD_CLEAN@
endif
else
noinst_LIBRARIES = libbits.a
libbits_a_AR = ar cru
AM_CPPFLAGS = \
@RTAI_KMOD_CFLAGS@ \
-I$(top_srcdir)/base/include \
-I../../include
rtai_bits.o: libbits.a
$(LD) --whole-archive $< -r -o $@
endif
all-local: rtai_bits$(modext)
if !CONFIG_RTAI_BITS_BUILTIN
if CONFIG_RTAI_OLD_FASHIONED_BUILD
$(mkinstalldirs) $(top_srcdir)/modules
$(INSTALL_DATA) $^ $(top_srcdir)/modules
endif
install-exec-local: rtai_bits$(modext)
$(mkinstalldirs) $(DESTDIR)$(moduledir)
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
endif
EXTRA_DIST = Makefile.kbuild

View file

@ -1,8 +0,0 @@
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
-I$(src)/../../include \
-I$(src)/../../.. \
-D__IN_RTAI__
obj-m += rtai_bits.o
rtai_bits-objs := $(rtai_objs)

View file

@ -1,104 +0,0 @@
Bits
====
This module provides helper functions allowing compound synchronizations based
on AND/ORs on a 32bits unsigned long. In other OSes similar objects are often
referred as flags/events. Their use is similar to that of semaphores except
that signal/waits are not related just to a simple counter but depends on a
combinations of bits set.
Test operations provided:
Single tests:
#define ALL_SET: test if an entire mask is set
#define ANY_SET: test if any entry of a mask is set
#define ALL_CLR: test if an entire mask is cleared
#define ANY_CLR: test if any entry of a mask is cleared
Combined tests (meaning easily inferred from macros names):
#define ALL_SET_AND_ANY_SET
#define ALL_SET_AND_ALL_CLR
#define ALL_SET_AND_ANY_CLR
#define ANY_SET_AND_ALL_CLR
#define ANY_SET_AND_ANY_CLR
#define ALL_CLR_AND_ANY_CLR
#define ALL_SET_OR_ANY_SET
#define ALL_SET_OR_ALL_CLR
#define ALL_SET_OR_ANY_CLR
#define ANY_SET_OR_ALL_CLR
#define ANY_SET_OR_ANY_CLR
#define ALL_CLR_OR_ANY_CLR
Bit operations provided:
#define SET_BITS: set bits according to the given mask
#define CLR_BITS: clear bits according to the given mask
#define SET_CLR_BITS: combined operation
#define NOP_BITS: do nothing
Services provided:
struct rt_bits_struct {
struct rt_queue queue; // must be first in struct
int magic;
int type; // to align mask to semaphore count, for easier uspace init
unsigned long mask;
};
typedef struct rt_bits_struct BITS;
To be noticed. The int variable type above is inserted to keep
rt_bits_struct aligned with the initial part of SEM, to ease use in user
space. For the same reason BITS_MAGIC and error returns are also the same
as those of SEM. Not so strange, bits code and APIs are very similar to
those of semaphores.
#include <rtai_bits.h>
- void rt_bits_init(BITS *bits, unsigned long mask)
create and initialize the bits structure pointed by bits support
structure, setting bits mask to mask.
- int rt_bits_delete(BITS *bits)
delete bits; returns: BITS_ERR if bits has already been deleted, 0 if OK.
- unsigned long rt_get_bits(BITS *bits)
get the actual value of bits mask.
- unsigned long rt_bits_signal(BITS *bits, int setfun, unsigned long masks)
execute setfun, any bits operation above, or/anding masks onto the actual bits
mask, schedule any task blocked on bits if the new bits mask meets its request;
returns the value of bits after executing setfun; in case of combined operations
masks is to be cast to a pointer of a two elements array of unsigned longs
containing the masks to be used for the combined setfun used.
- int rt_bits_reset(BITS *bits, unsigned long mask)
unconditionally schedule any task blocked on bits and reset its mask to mask;
returns the value of bits mask before being reset to mask.
- int rt_bits_wait(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask)
test bits mask against testmasks according to testfun, any of the test funs
above, if the test is not satisfied block the task; whenever the condition is
met execute exitfun, any bits operation above, using exitmasks, save the
the mask resulting after the whole processing in the variable pointed by
resulting_mask; returns: BITS_ERR if the task was blocked and resumed because
bits was deleted, 0 if OK; in case of combined operations testmasks and/or
exitmasks are to be cast to pointers of two elements arrays of unsigned
longs containing the masks to be used for the combined tests/executions.
- int rt_bits_wait_if(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask)
as rt_bits_wait but does not block if testfun is not satisfied; returns 1 if
it succeeded, 0 if it failed.
- int rt_bits_wait_until(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME time, unsigned long *resulting_mask)
as rt_bits_wait but waits at most till time expires; returns the same values
also, BITS_TIMOUT if the task blocked and has been resumed because a timeout
occured.
- unsigned long rt_bits_wait_timed(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME delay, unsigned long *resulting_mask)
as rt_bits_wait_until but waits at most for delay to meet the required
condition.
As usual, comments and bug fixes are welcomed.
Paolo Mantegazza (mantegazza@aero.polimi.it)

View file

@ -1,493 +0,0 @@
/*
* Copyright (C) 1999-2003 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/version.h>
#include <asm/uaccess.h>
#include <rtai_schedcore.h>
#include <rtai_sched.h>
#include <rtai_lxrt.h>
#include <rtai_bits.h>
MODULE_LICENSE("GPL");
#define MASK0(x) ((unsigned long *)&(x))[0]
#define MASK1(x) ((unsigned long *)&(x))[1]
static int all_set(BITS *bits, unsigned long mask)
{
return (bits->mask & mask) == mask;
}
static int any_set(BITS *bits, unsigned long mask)
{
return (bits->mask & mask);
}
static int all_clr(BITS *bits, unsigned long mask)
{
return (~bits->mask & mask) == mask;
}
static int any_clr(BITS *bits, unsigned long mask)
{
return (~bits->mask & mask);
}
static int all_set_and_any_set(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK1(masks)) && (bits->mask & MASK0(masks)) == MASK0(masks);
}
static int all_set_and_all_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) == MASK0(masks) && (~bits->mask & MASK1(masks)) == MASK1(masks);
}
static int all_set_and_any_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) == MASK0(masks) && (~bits->mask & MASK1(masks));
}
static int any_set_and_all_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) && (~bits->mask & MASK1(masks)) == MASK1(masks);
}
static int any_set_and_any_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) && (~bits->mask & MASK1(masks));
}
static int all_clr_and_any_clr(BITS *bits, unsigned long masks)
{
return (~bits->mask & MASK1(masks)) && (~bits->mask & MASK0(masks)) == MASK0(masks);
}
static int all_set_or_any_set(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK1(masks)) || (bits->mask & MASK0(masks)) == MASK0(masks);
}
static int all_set_or_all_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) == MASK0(masks) || (~bits->mask & MASK1(masks)) == MASK1(masks);
}
static int all_set_or_any_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) == MASK0(masks) || (~bits->mask & MASK1(masks));
}
static int any_set_or_all_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) || (~bits->mask & MASK1(masks)) == MASK1(masks);
}
static int any_set_or_any_clr(BITS *bits, unsigned long masks)
{
return (bits->mask & MASK0(masks)) || (~bits->mask & MASK1(masks));
}
static int all_clr_or_any_clr(BITS *bits, unsigned long masks)
{
return (~bits->mask & MASK1(masks)) || (~bits->mask & MASK0(masks)) == MASK0(masks);
}
static void set_bits_mask(BITS *bits, unsigned long mask)
{
bits->mask |= mask;
}
static void clr_bits_mask(BITS *bits, unsigned long mask)
{
bits->mask &= ~mask;
}
static void set_clr_bits_mask(BITS *bits, unsigned long masks)
{
bits->mask = (bits->mask | MASK0(masks)) & ~MASK1(masks);
}
static void nop_fun(BITS *bits, unsigned long mask)
{
}
static int (*test_fun[])(BITS *, unsigned long) = {
all_set, any_set, all_clr, any_clr,
all_set_and_any_set, all_set_and_all_clr, all_set_and_any_clr,
any_set_and_all_clr, any_set_and_any_clr,
all_clr_and_any_clr,
all_set_or_any_set, all_set_or_all_clr, all_set_or_any_clr,
any_set_or_all_clr, any_set_or_any_clr,
all_clr_or_any_clr
};
static void (*exec_fun[])(BITS *, unsigned long) = {
set_bits_mask, clr_bits_mask,
set_clr_bits_mask,
nop_fun
};
#define CHECK_BITS_MAGIC(bits) \
do { if (bits->magic != RT_BITS_MAGIC) return RTE_OBJINV; } while (0)
void rt_bits_init(BITS *bits, unsigned long mask)
{
bits->magic = RT_BITS_MAGIC;
bits->queue.prev = &(bits->queue);
bits->queue.next = &(bits->queue);
bits->queue.task = 0;
bits->mask = mask;
}
int rt_bits_delete(BITS *bits)
{
unsigned long flags, schedmap;
RT_TASK *task;
QUEUE *q;
CHECK_BITS_MAGIC(bits);
schedmap = 0;
q = &bits->queue;
flags = rt_global_save_flags_and_cli();
bits->magic = 0;
while ((q = q->next) != &bits->queue && (task = q->task)) {
rem_timed_task(task);
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
task->blocked_on = RTP_OBJREM;
enq_ready_task(task);
#ifdef CONFIG_SMP
set_bit(task->runnable_on_cpus & 0x1F, &schedmap);
#endif
}
}
RT_SCHEDULE_MAP(schedmap);
rt_global_restore_flags(flags);
return 0;
}
#define TEST_BUF(x, y) do { (x)->retval = (unsigned long)(y); } while (0)
#define TEST_FUN(x) ((long *)((unsigned long)(x)->retval))[0]
#define TEST_MASK(x) ((unsigned long *)((unsigned long)(x)->retval))[1]
RTAI_SYSCALL_MODE unsigned long rt_get_bits(BITS *bits)
{
return bits->mask;
}
RTAI_SYSCALL_MODE unsigned long rt_bits_reset(BITS *bits, unsigned long mask)
{
unsigned long flags, schedmap, oldmask;
RT_TASK *task;
QUEUE *q;
CHECK_BITS_MAGIC(bits);
schedmap = 0;
q = &bits->queue;
flags = rt_global_save_flags_and_cli();
oldmask = bits->mask;
bits->mask = mask;
while ((q = q->next) != &bits->queue) {
dequeue_blocked(task = q->task);
rem_timed_task(task);
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
enq_ready_task(task);
#ifdef CONFIG_SMP
set_bit(task->runnable_on_cpus & 0x1F, &schedmap);
#endif
}
}
bits->queue.prev = bits->queue.next = &bits->queue;
RT_SCHEDULE_MAP(schedmap);
rt_global_restore_flags(flags);
return oldmask;
}
RTAI_SYSCALL_MODE unsigned long rt_bits_signal(BITS *bits, int setfun, unsigned long masks)
{
unsigned long flags, schedmap;
RT_TASK *task;
QUEUE *q;
CHECK_BITS_MAGIC(bits);
schedmap = 0;
q = &bits->queue;
flags = rt_global_save_flags_and_cli();
exec_fun[setfun](bits, masks);
masks = bits->mask;
while ((q = q->next) != &bits->queue) {
task = q->task;
if (test_fun[TEST_FUN(task)](bits, TEST_MASK(task))) {
dequeue_blocked(task);
rem_timed_task(task);
if (task->state != RT_SCHED_READY && (task->state &= ~(RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED)) == RT_SCHED_READY) {
enq_ready_task(task);
#ifdef CONFIG_SMP
set_bit(task->runnable_on_cpus & 0x1F, &schedmap);
#endif
}
}
}
RT_SCHEDULE_MAP(schedmap);
rt_global_restore_flags(flags);
return masks;
}
RTAI_SYSCALL_MODE int _rt_bits_wait(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask, int space)
{
RT_TASK *rt_current;
unsigned long flags, mask = 0;
int retval;
CHECK_BITS_MAGIC(bits);
flags = rt_global_save_flags_and_cli();
if (!test_fun[testfun](bits, testmasks)) {
void *retpnt;
long bits_test[2];
rt_current = RT_CURRENT;
TEST_BUF(rt_current, bits_test);
TEST_FUN(rt_current) = testfun;
TEST_MASK(rt_current) = testmasks;
rt_current->state |= RT_SCHED_SEMAPHORE;
rem_ready_current(rt_current);
enqueue_blocked(rt_current, &bits->queue, 1);
rt_schedule();
if (unlikely((retpnt = rt_current->blocked_on) != NULL)) {
if (likely(retpnt != RTP_OBJREM)) {
dequeue_blocked(rt_current);
retval = RTE_UNBLKD;
} else {
rt_current->prio_passed_to = NULL;
retval = RTE_OBJREM;
}
goto retmask;
}
}
retval = 0;
mask = bits->mask;
exec_fun[exitfun](bits, exitmasks);
retmask:
rt_global_restore_flags(flags);
if (resulting_mask) {
if (space) {
*resulting_mask = mask;
} else {
rt_copy_to_user(resulting_mask, &mask, sizeof(mask));
}
}
return retval;
}
RTAI_SYSCALL_MODE int _rt_bits_wait_if(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, unsigned long *resulting_mask, int space)
{
unsigned long flags, mask;
int retval;
CHECK_BITS_MAGIC(bits);
flags = rt_global_save_flags_and_cli();
mask = bits->mask;
if (test_fun[testfun](bits, testmasks)) {
exec_fun[exitfun](bits, exitmasks);
retval = 1;
} else {
retval = 0;
}
rt_global_restore_flags(flags);
if (resulting_mask) {
if (space) {
*resulting_mask = mask;
} else {
rt_copy_to_user(resulting_mask, &mask, sizeof(mask));
}
}
return retval;
}
RTAI_SYSCALL_MODE int _rt_bits_wait_until(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME time, unsigned long *resulting_mask, int space)
{
RT_TASK *rt_current;
unsigned long flags, mask = 0;
int retval;
CHECK_BITS_MAGIC(bits);
flags = rt_global_save_flags_and_cli();
if (!test_fun[testfun](bits, testmasks)) {
void *retpnt;
long bits_test[2];
rt_current = RT_CURRENT;
TEST_BUF(rt_current, bits_test);
TEST_FUN(rt_current) = testfun;
TEST_MASK(rt_current) = testmasks;
rt_current->blocked_on = &bits->queue;
if ((rt_current->resume_time = time) > get_time()) {
rt_current->state |= (RT_SCHED_SEMAPHORE | RT_SCHED_DELAYED);
rem_ready_current(rt_current);
enqueue_blocked(rt_current, &bits->queue, 1);
enq_timed_task(rt_current);
rt_schedule();
} else {
rt_current->queue.prev = rt_current->queue.next = &rt_current->queue;
}
if (unlikely((retpnt = rt_current->blocked_on) != NULL)) {
if (likely(retpnt != RTP_OBJREM)) {
dequeue_blocked(rt_current);
retval = likely(retpnt > RTP_HIGERR) ? RTE_TIMOUT : RTE_UNBLKD;
} else {
rt_current->prio_passed_to = NULL;
retval = RTE_OBJREM;
}
goto retmask;
}
}
retval = 0;
mask = bits->mask;
exec_fun[exitfun](bits, exitmasks);
retmask:
rt_global_restore_flags(flags);
if (resulting_mask) {
if (space) {
*resulting_mask = mask;
} else {
rt_copy_to_user(resulting_mask, &mask, sizeof(mask));
}
}
return retval;
}
RTAI_SYSCALL_MODE int _rt_bits_wait_timed(BITS *bits, int testfun, unsigned long testmasks, int exitfun, unsigned long exitmasks, RTIME delay, unsigned long *resulting_mask, int space)
{
return _rt_bits_wait_until(bits, testfun, testmasks, exitfun, exitmasks, get_time() + delay, resulting_mask, space);
}
/* +++++++++++++++++++++++++++++ NAMED BITS +++++++++++++++++++++++++++++++++ */
#include <rtai_registry.h>
RTAI_SYSCALL_MODE BITS *rt_named_bits_init(const char *bits_name, unsigned long mask)
{
BITS *bits;
unsigned long name;
if ((bits = rt_get_adr(name = nam2num(bits_name)))) {
return bits;
}
if ((bits = rt_malloc(sizeof(SEM)))) {
rt_bits_init(bits, mask);
if (rt_register(name, bits, IS_BIT, 0)) {
return bits;
}
rt_bits_delete(bits);
}
rt_free(bits);
return NULL;
}
RTAI_SYSCALL_MODE int rt_named_bits_delete(BITS *bits)
{
if (!rt_bits_delete(bits)) {
rt_free(bits);
}
return rt_drg_on_adr(bits);
}
RTAI_SYSCALL_MODE void *rt_bits_init_u(unsigned long name, unsigned long mask)
{
BITS *bits;
if (rt_get_adr(name)) {
return NULL;
}
if ((bits = rt_malloc(sizeof(BITS)))) {
rt_bits_init(bits, mask);
if (rt_register(name, bits, IS_BIT, current)) {
return bits;
} else {
rt_free(bits);
}
}
return NULL;
}
RTAI_SYSCALL_MODE int rt_bits_delete_u(BITS *bits)
{
if (rt_bits_delete(bits)) {
return -EFAULT;
}
rt_free(bits);
return rt_drg_on_adr(bits);
}
/* ++++++++++++++++++++++++++++ BITS ENTRIES ++++++++++++++++++++++++++++++++ */
struct rt_native_fun_entry rt_bits_entries[] = {
{ { 0, rt_bits_init_u }, BITS_INIT },
{ { 0, rt_bits_delete_u }, BITS_DELETE },
{ { 0, rt_named_bits_init }, NAMED_BITS_INIT },
{ { 0, rt_named_bits_delete }, NAMED_BITS_DELETE },
{ { 1, rt_get_bits }, BITS_GET },
{ { 1, rt_bits_reset }, BITS_RESET },
{ { 1, rt_bits_signal }, BITS_SIGNAL },
{ { 1, _rt_bits_wait }, BITS_WAIT },
{ { 1, _rt_bits_wait_if }, BITS_WAIT_IF },
{ { 1, _rt_bits_wait_until }, BITS_WAIT_UNTIL },
{ { 1, _rt_bits_wait_timed }, BITS_WAIT_TIMED },
{ { 0, 0 }, 000 }
};
extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);
extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);
int __rtai_bits_init(void)
{
return set_rt_fun_entries(rt_bits_entries);
}
void __rtai_bits_exit(void)
{
reset_rt_fun_entries(rt_bits_entries);
}
#ifndef CONFIG_RTAI_BITS_BUILTIN
module_init(__rtai_bits_init);
module_exit(__rtai_bits_exit);
#endif /* !CONFIG_RTAI_BITS_BUILTIN */
#ifdef CONFIG_KBUILD
EXPORT_SYMBOL(rt_bits_init);
EXPORT_SYMBOL(rt_bits_delete);
EXPORT_SYMBOL(rt_get_bits);
EXPORT_SYMBOL(rt_bits_reset);
EXPORT_SYMBOL(rt_bits_signal);
EXPORT_SYMBOL(_rt_bits_wait);
EXPORT_SYMBOL(_rt_bits_wait_if);
EXPORT_SYMBOL(_rt_bits_wait_until);
EXPORT_SYMBOL(_rt_bits_wait_timed);
EXPORT_SYMBOL(rt_named_bits_init);
EXPORT_SYMBOL(rt_named_bits_delete);
EXPORT_SYMBOL(rt_bits_init_u);
EXPORT_SYMBOL(rt_bits_delete_u);
#endif /* CONFIG_KBUILD */

View file

@ -8,7 +8,6 @@ Their structuring within RTAI is eased in the new experimental layout, which
much eases features expansions, without bloating the core code of the much eases features expansions, without bloating the core code of the
schedulers. schedulers.
Message queues have the advantage of allowing fully prioritised send/receives, Message queues have the advantage of allowing fully prioritised send/receives,
TBX has just the possibility of urging ahead of anything already sent, MBX none.
However to avoid the nightmare of managing etherougeneously fragmented buffers, However to avoid the nightmare of managing etherougeneously fragmented buffers,
under hard real time constraints, they require that a maximum per message size under hard real time constraints, they require that a maximum per message size
is assigned at their creation. So once more the RTAI user is provided another is assigned at their creation. So once more the RTAI user is provided another

View file

@ -2,8 +2,6 @@ moduledir = @RTAI_MODULE_DIR@
modext = @RTAI_MODULE_EXT@ modext = @RTAI_MODULE_EXT@
libnetrpc_a_SOURCES = netrpc.c rtnetP.h libnetrpc_a_SOURCES = netrpc.c rtnetP.h
if CONFIG_KBUILD if CONFIG_KBUILD
@ -27,7 +25,6 @@ libnetrpc_a_AR = ar cru
AM_CPPFLAGS = \ AM_CPPFLAGS = \
@RTAI_KMOD_CFLAGS@ \ @RTAI_KMOD_CFLAGS@ \
-I$(top_srcdir)/base/include \ -I$(top_srcdir)/base/include \
-I$(top_srcdir)/addons/rtdm \
-I$(srcdir)/rtnet \ -I$(srcdir)/rtnet \
-I../../include -I../../include

View file

@ -1,48 +0,0 @@
moduledir = @RTAI_MODULE_DIR@
modext = @RTAI_MODULE_EXT@
libtbx_a_SOURCES = tbx.c
if CONFIG_KBUILD
if CONFIG_RTAI_TBX_BUILTIN
rtai_tbx.ko:
else
rtai_tbx.ko: @RTAI_KBUILD_ENV@
rtai_tbx.ko: $(libtbx_a_SOURCES)
@RTAI_KBUILD_TOP@ \
@RTAI_KBUILD_CMD@ \
@RTAI_KBUILD_BOTTOM@
clean-local:
@RTAI_KBUILD_CLEAN@
endif
else
noinst_LIBRARIES = libtbx.a
libtbx_a_AR = ar cru
AM_CPPFLAGS = \
@RTAI_KMOD_CFLAGS@ \
-I$(top_srcdir)/base/include \
-I../../include
rtai_tbx.o: libtbx.a
$(LD) --whole-archive $< -r -o $@
endif
all-local: rtai_tbx$(modext)
if !CONFIG_RTAI_TBX_BUILTIN
if CONFIG_RTAI_OLD_FASHIONED_BUILD
$(mkinstalldirs) $(top_srcdir)/modules
$(INSTALL_DATA) $^ $(top_srcdir)/modules
endif
install-exec-local: rtai_tbx$(modext)
$(mkinstalldirs) $(DESTDIR)$(moduledir)
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
endif
EXTRA_DIST = Makefile.kbuild

View file

@ -1,8 +0,0 @@
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
-I$(src)/../../include \
-I$(src)/../../.. \
-D__IN_RTAI__
obj-m += rtai_tbx.o
rtai_tbx-objs := $(rtai_objs)

View file

@ -1,80 +0,0 @@
Typed mailboxes and POSIX message queues modules for RTAI
=========================================================
------------------------ T Y P E D M A I L B O X E S -------------------------
COPYRIGHT (C) 2001 G.M. Bertani (gmbertani@yahoo.it)
(http://www.geocities.com/gmbertani)
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This 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 Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Softwre Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
Introduction
------------
Typed mailboxes (TBX) are an alternative to the default RTAI ones that offers:
1-Message broadcasting, that means send a message to ALL the tasks that are
pending on the same TBX.
2-Urgent sending of messages: these messages are not enqueued, but inserted in
the head of the queue, bypassing all the other messages already present in TBX.
3-The PRIORITY/FIFO wakeup policy can be set at runtime when creating the TBX
Features (1) and (2) are achieved by adding a type field (1 byte) to every
message inserted in a TBX, so when receiving it is possible to discriminate
normal, urgent and broadcast messages. The type field is silently removed by
the receiving functions, so from the user point of view it is not visible.
Users must consider type fields only when specifying the TBX sizes.
System requirements
-------------------
RTAI-24.x.y (Linux 2.4.x) : http://www.rtai.org
Acknowledgements
----------------
Thanks to Paolo Mantegazza (mantegazza@aero.polimi.it) for his work in
changing this code from a simple upsched.c patch to an autonomous RTAI
module.
------------------- P O S I X M E S S A G E Q U E U E S --------------------
After discovering that Trevor's (Woolven) kernel space implementation of POSIX
message queues was usable directly, almost unchanged, with RTAI, i.e. without
the specific kernel POSIX support found within RTAI itself, it followed that
it had to work symmetrically in user space also.
Its structuring within RTAI appears similar to TBXes, i.e an extension of RTAI
intertask communication APIs, not born in the RTAI schedulers directly. So it
goes into the existing "tbx" directory, along with its (NEW)LXRT user space
extension module.
So to use POSIX message queues everywhere you'll have just to care of insmoding
the related modules: rtai_pqueue.o and rtai_pqueue_lxrt.o found here, the
related header file, rtai_pqueue.h, is found in directory "include". It is the
same for both kernel and user space applications.
It should be remarked that the rtai_pqueue.c file found here contains also
timed version of send/receive, that are missing in its native parent found
under the "/posix/src" directory.
On the lucky side is that POSIX message queues are all natively based on the
POSIX standard naming, thanks to the fact that RTAI core APIs had nothing
similar to them yet.
Paolo Mantegazza.

View file

@ -1,455 +0,0 @@
/*
* Copyright (C) 2005 Paolo Mantegazza <mantegazza@aero.polimi.it>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <rtai_registry.h>
#include <rtai_schedcore.h>
#include <rtai_tbx.h>
MODULE_LICENSE("GPL");
static inline void enq_msg(RT_MSGQ *q, RT_MSGH *msg)
{
RT_MSGH *prev, *next;
for (prev = next = q->firstmsg; msg->priority >= next->priority; prev = next, next = next->next);
if (next == prev) {
msg->next = next;
q->firstmsg = msg;
} else {
msg->next = prev->next;
prev->next = msg;
}
}
RTAI_SYSCALL_MODE int rt_msgq_init(RT_MSGQ *mq, int nmsg, int msg_size)
{
int i;
void *p;
if (!(mq->slots = rt_malloc((msg_size + RT_MSGH_SIZE + sizeof(void *))*nmsg + RT_MSGH_SIZE))) {
return -ENOMEM;
}
mq->nmsg = nmsg;
mq->fastsize = msg_size;
mq->slot = 0;
p = mq->slots + nmsg;
for (i = 0; i < nmsg; i++) {
mq->slots[i] = p;
((RT_MSGH *)p)->priority = 0;
p += (msg_size + RT_MSGH_SIZE);
}
((RT_MSGH *)(mq->firstmsg = p))->priority = (0xFFFFFFFF/2);
rt_typed_sem_init(&mq->receivers, 1, RES_SEM);
rt_typed_sem_init(&mq->senders, 1, RES_SEM);
rt_typed_sem_init(&mq->received, 0, CNT_SEM);
rt_typed_sem_init(&mq->freslots, nmsg, CNT_SEM);
spin_lock_init(&mq->lock);
return 0;
}
RTAI_SYSCALL_MODE int rt_msgq_delete(RT_MSGQ *mq)
{
int err;
err = rt_sem_delete(&mq->receivers) || rt_sem_delete(&mq->senders) || rt_sem_delete(&mq->received) || rt_sem_delete(&mq->freslots);
rt_sem_delete(&mq->broadcast);
rt_free(mq->slots);
return err ? -EFAULT : 0;
}
RTAI_SYSCALL_MODE RT_MSGQ *_rt_named_msgq_init(unsigned long msgq_name, int nmsg, int msg_size)
{
RT_MSGQ *msgq;
if ((msgq = rt_get_adr_cnt(msgq_name))) {
return msgq;
}
if ((msgq = rt_malloc(sizeof(RT_MSGQ)))) {
rt_msgq_init(msgq, nmsg, msg_size);
if (rt_register(msgq_name, msgq, IS_MBX, 0)) {
return msgq;
}
rt_msgq_delete(msgq);
}
rt_free(msgq);
return NULL;
}
RTAI_SYSCALL_MODE int rt_named_msgq_delete(RT_MSGQ *msgq)
{
int ret;
if (!(ret = rt_drg_on_adr_cnt(msgq))) {
if (!rt_msgq_delete(msgq)) {
rt_free(msgq);
return 0;
} else {
return -EFAULT;
}
}
return ret;
}
static int _send(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, int space)
{
unsigned long flags;
RT_MSG *msg_ptr;
void *p;
if (msg_size > mq->fastsize) {
if (!(p = rt_malloc(msg_size))) {
rt_sem_signal(&mq->freslots);
rt_sem_signal(&mq->senders);
return -ENOMEM;
}
} else {
p = NULL;
}
flags = rt_spin_lock_irqsave(&mq->lock);
msg_ptr = mq->slots[mq->slot++];
rt_spin_unlock_irqrestore(flags, &mq->lock);
msg_ptr->hdr.size = msg_size;
msg_ptr->hdr.priority = msgpri;
msg_ptr->hdr.malloc = p;
msg_ptr->hdr.broadcast = 0;
if (space) {
memcpy(p ? p : msg_ptr->msg, msg, msg_size);
} else {
rt_copy_from_user(p ? p : msg_ptr->msg, msg, msg_size);
}
flags = rt_spin_lock_irqsave(&mq->lock);
enq_msg(mq, &msg_ptr->hdr);
rt_spin_unlock_irqrestore(flags, &mq->lock);
rt_sem_signal(&mq->received);
rt_sem_signal(&mq->senders);
return 0;
}
#define TBX_RET(msg_size, retval) \
(CONFIG_RTAI_USE_NEWERR ? retval : msg_size)
RTAI_SYSCALL_MODE int _rt_msg_send(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, int space)
{
int retval;
if ((retval = rt_sem_wait(&mq->senders)) >= RTE_LOWERR) {
return TBX_RET(msg_size, retval);
}
if (rt_sem_wait(&mq->freslots) >= RTE_LOWERR) {
rt_sem_signal(&mq->senders);
return TBX_RET(msg_size, retval);
}
return _send(mq, msg, msg_size, msgpri, space);
}
RTAI_SYSCALL_MODE int _rt_msg_send_if(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, int space)
{
if (rt_sem_wait_if(&mq->senders) <= 0) {
return msg_size;
}
if (rt_sem_wait_if(&mq->freslots) <= 0) {
rt_sem_signal(&mq->senders);
return msg_size;
}
return _send(mq, msg, msg_size, msgpri, space);
}
RTAI_SYSCALL_MODE int _rt_msg_send_until(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, RTIME until, int space)
{
int retval;
if ((retval = rt_sem_wait_until(&mq->senders, until)) >= RTE_LOWERR) {
return TBX_RET(msg_size, retval);
}
if ((retval = rt_sem_wait_until(&mq->freslots, until)) >= RTE_LOWERR) {
rt_sem_signal(&mq->senders);
return TBX_RET(msg_size, retval);
}
return _send(mq, msg, msg_size, msgpri, space);
}
RTAI_SYSCALL_MODE int _rt_msg_send_timed(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, RTIME delay, int space)
{
return _rt_msg_send_until(mq, msg, msg_size, msgpri, get_time() + delay, space);
}
static int _receive(RT_MSGQ *mq, void *msg, int msg_size, int *msgpri, int space)
{
int size;
RT_MSG *msg_ptr;
void *p;
size = min((msg_ptr = mq->firstmsg)->hdr.size, msg_size);
if (space) {
memcpy(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
if (msgpri) {
*msgpri = msg_ptr->hdr.priority;
}
} else {
rt_copy_to_user(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
if (msgpri) {
rt_put_user(msg_ptr->hdr.priority, msgpri);
}
}
if (msg_ptr->hdr.broadcast) {
if (!--msg_ptr->hdr.broadcast) {
rt_sem_wait_barrier(&mq->broadcast);
goto relslot;
} else {
rt_sem_signal(&mq->received);
rt_sem_signal(&mq->receivers);
rt_sem_wait_barrier(&mq->broadcast);
}
} else {
unsigned long flags;
relslot: flags = rt_spin_lock_irqsave(&mq->lock);
mq->firstmsg = msg_ptr->hdr.next;
mq->slots[--mq->slot] = msg_ptr;
rt_spin_unlock_irqrestore(flags, &mq->lock);
rt_sem_signal(&mq->freslots);
rt_sem_signal(&mq->receivers);
if (p) {
rt_free(p);
}
}
return msg_size - size;
}
RTAI_SYSCALL_MODE int _rt_msg_receive(RT_MSGQ *mq, void *msg, int msg_size, int *msgpri, int space)
{
int retval;
if ((retval = rt_sem_wait(&mq->receivers)) >= RTE_LOWERR) {
return TBX_RET(msg_size, retval);
}
if ((retval = rt_sem_wait(&mq->received)) >= RTE_LOWERR) { ;
rt_sem_signal(&mq->receivers);
return TBX_RET(msg_size, retval);
}
return _receive(mq, msg, msg_size, msgpri, space);
}
RTAI_SYSCALL_MODE int _rt_msg_receive_if(RT_MSGQ *mq, void *msg, int msg_size, int *msgpri, int space)
{
if (rt_sem_wait_if(&mq->receivers) <= 0) {
return msg_size;
}
if (rt_sem_wait_if(&mq->received) <= 0) { ;
rt_sem_signal(&mq->receivers);
return msg_size;
}
return _receive(mq, msg, msg_size, msgpri, space);
}
RTAI_SYSCALL_MODE int _rt_msg_receive_until(RT_MSGQ *mq, void *msg, int msg_size, int *msgpri, RTIME until, int space)
{
int retval;
if ((retval = rt_sem_wait_until(&mq->receivers, until)) >= RTE_LOWERR) {
return TBX_RET(msg_size, retval);
}
if ((retval = rt_sem_wait_until(&mq->received, until)) >= RTE_LOWERR) {
rt_sem_signal(&mq->receivers);
return TBX_RET(msg_size, retval);
}
return _receive(mq, msg, msg_size, msgpri, space);
}
RTAI_SYSCALL_MODE int _rt_msg_receive_timed(RT_MSGQ *mq, void *msg, int msg_size, int *msgpri, RTIME delay, int space)
{
return _rt_msg_receive_until(mq, msg, msg_size, msgpri, get_time() + delay, space);
}
RTAI_SYSCALL_MODE int _rt_msg_evdrp(RT_MSGQ *mq, void *msg, int msg_size, int *msgpri, int space)
{
int size;
RT_MSG *msg_ptr;
void *p;
size = min((msg_ptr = mq->firstmsg)->hdr.size, msg_size);
if (space) {
memcpy(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
if (msgpri) {
*msgpri = msg_ptr->hdr.priority;
}
} else {
rt_copy_to_user(msg, (p = msg_ptr->hdr.malloc) ? p : msg_ptr->msg, size);
if (msgpri) {
rt_put_user(msg_ptr->hdr.priority, msgpri);
}
}
return 0;
}
static int _broadcast(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, int broadcast, int space)
{
unsigned long flags;
RT_MSG *msg_ptr;
void *p;
if (msg_size > mq->fastsize) {
if (!(p = rt_malloc(msg_size))) {
rt_sem_signal(&mq->freslots);
rt_sem_signal(&mq->senders);
return -ENOMEM;
}
} else {
p = NULL;
}
flags = rt_spin_lock_irqsave(&mq->lock);
msg_ptr = mq->slots[mq->slot++];
rt_spin_unlock_irqrestore(flags, &mq->lock);
msg_ptr->hdr.size = msg_size;
msg_ptr->hdr.priority = msgpri;
msg_ptr->hdr.malloc = p;
if (space) {
memcpy(p ? p : msg_ptr->msg, msg, msg_size);
} else {
rt_copy_from_user(p ? p : msg_ptr->msg, msg, msg_size);
}
rt_typed_sem_init(&mq->broadcast, broadcast + 1, CNT_SEM | PRIO_Q);
msg_ptr->hdr.broadcast = broadcast;
flags = rt_spin_lock_irqsave(&mq->lock);
enq_msg(mq, &msg_ptr->hdr);
rt_spin_unlock_irqrestore(flags, &mq->lock);
rt_sem_signal(&mq->received);
rt_sem_wait_barrier(&mq->broadcast);
rt_sem_signal(&mq->senders);
return broadcast;
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, int space)
{
int retval;
if ((retval = rt_sem_wait(&mq->senders)) >= RTE_LOWERR) {
return TBX_RET(0, retval);
}
if (mq->received.count >= 0) {
rt_sem_signal(&mq->senders);
return 0;
}
if ((retval = rt_sem_wait(&mq->freslots)) >= RTE_LOWERR) {
rt_sem_signal(&mq->senders);
return TBX_RET(0, retval);
}
return _broadcast(mq, msg, msg_size, msgpri, -(mq->received.count + mq->receivers.count), space);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast_if(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, int space)
{
if (rt_sem_wait_if(&mq->senders) <= 0) {
return 0;
}
if (mq->received.count >= 0) {
rt_sem_signal(&mq->senders);
return 0;
}
if (rt_sem_wait_if(&mq->freslots) <= 0) {
rt_sem_signal(&mq->senders);
return 0;
}
return _broadcast(mq, msg, msg_size, msgpri, -(mq->received.count + mq->receivers.count), space);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast_until(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, RTIME until, int space)
{
int retval;
if ((retval = rt_sem_wait_until(&mq->senders, until)) >= RTE_LOWERR) {
return TBX_RET(0, retval);
}
if (mq->received.count >= 0) {
rt_sem_signal(&mq->senders);
return 0;
}
if ((retval = rt_sem_wait_until(&mq->freslots, until)) >= RTE_LOWERR) {
rt_sem_signal(&mq->senders);
return TBX_RET(0, retval);
}
return _broadcast(mq, msg, msg_size, msgpri, -(mq->received.count + mq->receivers.count), space);
}
RTAI_SYSCALL_MODE int _rt_msg_broadcast_timed(RT_MSGQ *mq, void *msg, int msg_size, int msgpri, RTIME delay, int space)
{
return _rt_msg_broadcast_until(mq, msg, msg_size, msgpri, get_time() + delay, space);
}
struct rt_native_fun_entry rt_msg_queue_entries[] = {
{ { 0, rt_msgq_init }, MSGQ_INIT },
{ { 1, rt_msgq_delete }, MSGQ_DELETE },
{ { 0, _rt_named_msgq_init }, NAMED_MSGQ_INIT },
{ { 1, rt_named_msgq_delete }, NAMED_MSGQ_DELETE },
{ { 1, _rt_msg_send }, MSG_SEND },
{ { 1, _rt_msg_send_if }, MSG_SEND_IF },
{ { 1, _rt_msg_send_until }, MSG_SEND_UNTIL },
{ { 1, _rt_msg_send_timed }, MSG_SEND_TIMED },
{ { 1, _rt_msg_receive }, MSG_RECEIVE },
{ { 1, _rt_msg_receive_if }, MSG_RECEIVE_IF },
{ { 1, _rt_msg_receive_until }, MSG_RECEIVE_UNTIL },
{ { 1, _rt_msg_receive_timed }, MSG_RECEIVE_TIMED },
{ { 1, _rt_msg_broadcast }, MSG_BROADCAST },
{ { 1, _rt_msg_broadcast_if }, MSG_BROADCAST_IF },
{ { 1, _rt_msg_broadcast_until }, MSG_BROADCAST_UNTIL },
{ { 1, _rt_msg_broadcast_timed }, MSG_BROADCAST_TIMED },
{ { 1, _rt_msg_evdrp }, MSG_EVDRP },
{ { 0, 0 }, 000 }
};
extern int set_rt_fun_entries(struct rt_native_fun_entry *entry);
extern void reset_rt_fun_entries(struct rt_native_fun_entry *entry);
int __rtai_msg_queue_init(void)
{
printk(KERN_INFO "RTAI[rtai_msgq]: loaded.\n");
return set_rt_fun_entries(rt_msg_queue_entries);
}
void __rtai_msg_queue_exit(void)
{
reset_rt_fun_entries(rt_msg_queue_entries);
printk(KERN_INFO "RTAI[rtai_msgq]: unloaded.\n");
}
#ifndef CONFIG_RTAI_TBX_BUILTIN
module_init(__rtai_msg_queue_init);
module_exit(__rtai_msg_queue_exit);
#endif /* !CONFIG_RTAI_TBX_BUILTIN */
#ifdef CONFIG_KBUILD
EXPORT_SYMBOL(rt_msgq_init);
EXPORT_SYMBOL(rt_msgq_delete);
EXPORT_SYMBOL(_rt_named_msgq_init);
EXPORT_SYMBOL(rt_named_msgq_delete);
EXPORT_SYMBOL(_rt_msg_send);
EXPORT_SYMBOL(_rt_msg_send_if);
EXPORT_SYMBOL(_rt_msg_send_until);
EXPORT_SYMBOL(_rt_msg_send_timed);
EXPORT_SYMBOL(_rt_msg_receive);
EXPORT_SYMBOL(_rt_msg_receive_if);
EXPORT_SYMBOL(_rt_msg_receive_until);
EXPORT_SYMBOL(_rt_msg_receive_timed);
EXPORT_SYMBOL(_rt_msg_broadcast);
EXPORT_SYMBOL(_rt_msg_broadcast_if);
EXPORT_SYMBOL(_rt_msg_broadcast_until);
EXPORT_SYMBOL(_rt_msg_broadcast_timed);
EXPORT_SYMBOL(_rt_msg_evdrp);
#endif /* CONFIG_KBUILD */

View file

@ -2,36 +2,21 @@ moduledir = @RTAI_MODULE_DIR@
modext = @RTAI_MODULE_EXT@ modext = @RTAI_MODULE_EXT@
if CONFIG_RTAI_MATH_C99
libmath_a_SOURCES = \ libmath_a_SOURCES = \
ceilfloor.c e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c \ e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c \
e_exp.c e_fmod.c e_gamma.c e_gamma_r.c e_hypot.c e_j0.c e_j1.c e_jn.c \ e_exp.c e_fmax.c e_fmin.c e_fmod.c e_gamma.c e_gamma_r.c e_hypot.c e_j0.c e_j1.c e_jn.c \
e_lgamma.c e_lgamma_r.c e_log.c e_log10.c e_pow.c e_rem_pio2.c e_remainder.c \ e_lgamma.c e_lgamma_r.c e_log.c e_log10.c e_pow.c e_rem_pio2.c e_remainder.c \
e_scalb.c e_sinh.c e_sqrt.c fpmacros.c frexpldexp.c k_cos.c k_rem_pio2.c \ e_scalb.c e_sinh.c e_sqrt.c k_cos.c k_rem_pio2.c \
k_sin.c k_standard.c k_tan.c logb.c rndint.c s_asinh.c s_atan.c s_cbrt.c \ k_sin.c k_standard.c k_tan.c s_asinh.c s_atan.c s_cbrt.c \
s_ceil.c s_copysign.c s_cos.c s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c \ s_ceil.c s_copysign.c s_cos.c s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c \
s_frexp.c s_ilogb.c s_ldexp.c s_lib_version.c s_log1p.c s_logb.c s_matherr.c \ s_frexp.c s_ilogb.c s_ldexp.c s_lib_version.c s_log1p.c s_matherr.c \
s_modf.c s_nextafter.c s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c \ s_modf.c s_nextafter.c s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c \
s_tan.c s_tanh.c scalb.c sign.c w_acos.c w_acosh.c w_asin.c w_atan2.c w_atanh.c \ s_tan.c s_tanh.c w_acos.c w_acosh.c w_asin.c w_atan2.c w_atanh.c \
w_cabs.c w_cosh.c w_drem.c w_exp.c w_fmod.c w_gamma.c w_gamma_r.c w_hypot.c \ w_cabs.c w_cosh.c w_drem.c w_exp.c w_fmax.c w_fmin.c w_fmod.c w_gamma.c w_gamma_r.c w_hypot.c \
w_j0.c w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c w_log.c w_log10.c w_pow.c \ w_j0.c w_j1.c w_jn.c w_lgamma.c w_lgamma_r.c w_log.c w_log10.c w_pow.c \
w_remainder.c w_scalb.c w_sinh.c w_sqrt.c libm.c w_remainder.c w_scalb.c w_sinh.c w_sqrt.c libm.c
else libmath_a_SOURCES += mathP.h
libmath_a_SOURCES = \
e_acos.c e_asin.c e_atan2.c e_cosh.c e_exp.c e_fmod.c e_log.c e_log10.c \
e_pow.c e_rem_pio2.c e_sinh.c e_sqrt.c k_cos.c k_rem_pio2.c k_sin.c k_tan.c \
s_atan.c s_ceil.c s_copysign.c s_cos.c s_expm1.c s_fabs.c s_floor.c s_frexp.c \
s_modf.c s_scalbn.c s_sin.c s_tan.c s_tanh.c sign.c w_acos.c w_asin.c w_atan2.c \
w_cosh.c w_exp.c w_fmod.c w_log.c w_log10.c w_pow.c w_sinh.c w_sqrt.c libm.c
endif
libmath_a_SOURCES += fpP.h mathP.h
if CONFIG_KBUILD if CONFIG_KBUILD
rtai_math.ko: @RTAI_KBUILD_ENV@ rtai_math.ko: @RTAI_KBUILD_ENV@
@ -59,7 +44,6 @@ rtai_math.o: libmath.a
endif endif
all-local: rtai_math$(modext) all-local: rtai_math$(modext)
if !CONFIG_RTAI_MATH_BUILTIN
if CONFIG_RTAI_OLD_FASHIONED_BUILD if CONFIG_RTAI_OLD_FASHIONED_BUILD
$(mkinstalldirs) $(top_srcdir)/modules $(mkinstalldirs) $(top_srcdir)/modules
$(INSTALL_DATA) $^ $(top_srcdir)/modules $(INSTALL_DATA) $^ $(top_srcdir)/modules
@ -68,6 +52,5 @@ endif
install-exec-local: rtai_math$(modext) install-exec-local: rtai_math$(modext)
$(mkinstalldirs) $(DESTDIR)$(moduledir) $(mkinstalldirs) $(DESTDIR)$(moduledir)
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir) $(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
endif
EXTRA_DIST = Makefile.kbuild EXTRA_DIST = Makefile.kbuild

View file

@ -1,8 +1,6 @@
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \ EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
-I$(src)/../include \ -I$(src)/../include \
-I$(src)/../.. \ -I$(src)/../.. \
-I/usr/include \
-isystem $(shell $(CC) -print-file-name=include-fixed) \
$(rtai_extradef) \ $(rtai_extradef) \
-D_IEEE_LIBM \ -D_IEEE_LIBM \
-D_ISOC99_SOURCE \ -D_ISOC99_SOURCE \

View file

@ -1,179 +0,0 @@
#if defined(__ppc__)
/*******************************************************************************
* *
* File ceilfloor.c, *
* Function ceil(x) and floor(x), *
* Implementation of ceil and floor for the PowerPC. *
* *
* Copyright © 1991 Apple Computer, Inc. All rights reserved. *
* *
* Written by Ali Sazegari, started on November 1991, *
* *
* based on math.h, library code for Macintoshes with a 68881/68882 *
* by Jim Thomas. *
* *
* W A R N I N G: This routine expects a 64 bit double model. *
* *
* December 03 1992: first rs6000 port. *
* July 14 1993: comment changes and addition of #pragma fenv_access. *
* May 06 1997: port of the ibm/taligent ceil and floor routines. *
* April 11 2001: first port to os x using gcc. *
* June 13 2001: replaced __setflm with in-line assembly *
* *
*******************************************************************************/
#if !defined(__ppc__)
#define asm(x)
#endif
static const double twoTo52 = 4503599627370496.0;
static const unsigned long signMask = 0x80000000ul;
typedef union
{
struct {
#if defined(__BIG_ENDIAN__)
unsigned long int hi;
unsigned long int lo;
#else
unsigned long int lo;
unsigned long int hi;
#endif
} words;
double dbl;
} DblInHex;
/*******************************************************************************
* Functions needed for the computation. *
*******************************************************************************/
/*******************************************************************************
* Ceil(x) returns the smallest integer not less than x. *
*******************************************************************************/
double ceil ( double x )
{
DblInHex xInHex,OldEnvironment;
register double y;
register unsigned long int xhi;
register int target;
xInHex.dbl = x;
xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x|
target = ( xInHex.words.hi < signMask );
if ( xhi < 0x43300000ul )
/*******************************************************************************
* Is |x| < 2.0^52? *
*******************************************************************************/
{
if ( xhi < 0x3ff00000ul )
/*******************************************************************************
* Is |x| < 1.0? *
*******************************************************************************/
{
if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case
return ( x );
else
{ // inexact case
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
OldEnvironment.words.lo |= 0x02000000ul;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
if ( target )
return ( 1.0 );
else
return ( -0.0 );
}
}
/*******************************************************************************
* Is 1.0 < |x| < 2.0^52? *
*******************************************************************************/
if ( target )
{
y = ( x + twoTo52 ) - twoTo52; // round at binary pt.
if ( y < x )
return ( y + 1.0 );
else
return ( y );
}
else
{
y = ( x - twoTo52 ) + twoTo52; // round at binary pt.
if ( y < x )
return ( y + 1.0 );
else
return ( y );
}
}
/*******************************************************************************
* |x| >= 2.0^52 or x is a NaN. *
*******************************************************************************/
return ( x );
}
/*******************************************************************************
* Floor(x) returns the largest integer not greater than x. *
*******************************************************************************/
double floor ( double x )
{
DblInHex xInHex,OldEnvironment;
register double y;
register unsigned long int xhi;
register long int target;
xInHex.dbl = x;
xhi = xInHex.words.hi & 0x7fffffffUL; // xhi is the high half of |x|
target = ( xInHex.words.hi < signMask );
if ( xhi < 0x43300000ul )
/*******************************************************************************
* Is |x| < 2.0^52? *
*******************************************************************************/
{
if ( xhi < 0x3ff00000ul )
/*******************************************************************************
* Is |x| < 1.0? *
*******************************************************************************/
{
if ( ( xhi | xInHex.words.lo ) == 0ul ) // zero x is exact case
return ( x );
else
{ // inexact case
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
OldEnvironment.words.lo |= 0x02000000ul;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
if ( target )
return ( 0.0 );
else
return ( -1.0 );
}
}
/*******************************************************************************
* Is 1.0 < |x| < 2.0^52? *
*******************************************************************************/
if ( target )
{
y = ( x + twoTo52 ) - twoTo52; // round at binary pt.
if ( y > x )
return ( y - 1.0 );
else
return ( y );
}
else
{
y = ( x - twoTo52 ) + twoTo52; // round at binary pt.
if ( y > x )
return ( y - 1.0 );
else
return ( y );
}
}
/*******************************************************************************
* |x| >= 2.0^52 or x is a NaN. *
*******************************************************************************/
return ( x );
}
#endif /* __ppc__ */

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_acos.c,v 1.9 1995/05/12 04:57:13 jtc Exp $";
#endif
/* __ieee754_acos(x) /* __ieee754_acos(x)
* Method : * Method :
* acos(x) = pi/2 - asin(x) * acos(x) = pi/2 - asin(x)
@ -38,14 +34,9 @@ static char rcsid[] = "$NetBSD: e_acos.c,v 1.9 1995/05/12 04:57:13 jtc Exp $";
* Function needed: __ieee754_sqrt * Function needed: __ieee754_sqrt
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
@ -61,12 +52,7 @@ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
#ifdef __STDC__
double __ieee754_acos(double x) double __ieee754_acos(double x)
#else
double __ieee754_acos(x)
double x;
#endif
{ {
double z,p,q,r,w,s,c,df; double z,p,q,r,w,s,c,df;
int32_t hx,ix; int32_t hx,ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_acosh.c,v 1.9 1995/05/12 04:57:18 jtc Exp $";
#endif
/* __ieee754_acosh(x) /* __ieee754_acosh(x)
* Method : * Method :
* Based on * Based on
@ -28,23 +24,13 @@ static char rcsid[] = "$NetBSD: e_acosh.c,v 1.9 1995/05/12 04:57:18 jtc Exp $";
* acosh(NaN) is NaN without signal. * acosh(NaN) is NaN without signal.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.0, one = 1.0,
ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */
#ifdef __STDC__
double __ieee754_acosh(double x) double __ieee754_acosh(double x)
#else
double __ieee754_acosh(x)
double x;
#endif
{ {
double t; double t;
int32_t hx; int32_t hx;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_asin.c,v 1.9 1995/05/12 04:57:22 jtc Exp $";
#endif
/* __ieee754_asin(x) /* __ieee754_asin(x)
* Method : * Method :
* Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ... * Since asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
@ -44,15 +40,9 @@ static char rcsid[] = "$NetBSD: e_asin.c,v 1.9 1995/05/12 04:57:22 jtc Exp $";
* *
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
huge = 1.000e+300, huge = 1.000e+300,
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
@ -70,12 +60,7 @@ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
#ifdef __STDC__
double __ieee754_asin(double x) double __ieee754_asin(double x)
#else
double __ieee754_asin(x)
double x;
#endif
{ {
double t,w,p,q,c,r,s; double t,w,p,q,c,r,s;
int32_t hx,ix; int32_t hx,ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_atan2.c,v 1.8 1995/05/10 20:44:51 jtc Exp $";
#endif
/* __ieee754_atan2(y,x) /* __ieee754_atan2(y,x)
* Method : * Method :
* 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x).
@ -41,14 +37,9 @@ static char rcsid[] = "$NetBSD: e_atan2.c,v 1.8 1995/05/10 20:44:51 jtc Exp $";
* to produce the hexadecimal values shown. * to produce the hexadecimal values shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
tiny = 1.0e-300, tiny = 1.0e-300,
zero = 0.0, zero = 0.0,
pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
@ -56,12 +47,7 @@ pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
#ifdef __STDC__
double __ieee754_atan2(double y, double x) double __ieee754_atan2(double y, double x)
#else
double __ieee754_atan2(y,x)
double y,x;
#endif
{ {
double z; double z;
int32_t k,m,hx,hy,ix,iy; int32_t k,m,hx,hy,ix,iy;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_atanh.c,v 1.8 1995/05/10 20:44:55 jtc Exp $";
#endif
/* __ieee754_atanh(x) /* __ieee754_atanh(x)
* Method : * Method :
* 1.Reduced x to positive by atanh(-x) = -atanh(x) * 1.Reduced x to positive by atanh(-x) = -atanh(x)
@ -32,27 +28,13 @@ static char rcsid[] = "$NetBSD: e_atanh.c,v 1.8 1995/05/10 20:44:55 jtc Exp $";
* *
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double one = 1.0, huge = 1e300; static const double one = 1.0, huge = 1e300;
#else
static double one = 1.0, huge = 1e300;
#endif
#ifdef __STDC__
static const double zero = 0.0; static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_atanh(double x) double __ieee754_atanh(double x)
#else
double __ieee754_atanh(x)
double x;
#endif
{ {
double t; double t;
int32_t hx,ix; int32_t hx,ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_cosh.c,v 1.7 1995/05/10 20:44:58 jtc Exp $";
#endif
/* __ieee754_cosh(x) /* __ieee754_cosh(x)
* Method : * Method :
* mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
@ -35,21 +31,11 @@ static char rcsid[] = "$NetBSD: e_cosh.c,v 1.7 1995/05/10 20:44:58 jtc Exp $";
* only cosh(0)=1 is exact for finite x. * only cosh(0)=1 is exact for finite x.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double one = 1.0, half=0.5, huge = 1.0e300; static const double one = 1.0, half=0.5, huge = 1.0e300;
#else
static double one = 1.0, half=0.5, huge = 1.0e300;
#endif
#ifdef __STDC__
double __ieee754_cosh(double x) double __ieee754_cosh(double x)
#else
double __ieee754_cosh(x)
double x;
#endif
{ {
double t,w; double t,w;
int32_t ix; int32_t ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_exp.c,v 1.8 1995/05/10 20:45:03 jtc Exp $";
#endif
/* __ieee754_exp(x) /* __ieee754_exp(x)
* Returns the exponential of x. * Returns the exponential of x.
* *
@ -77,14 +73,9 @@ static char rcsid[] = "$NetBSD: e_exp.c,v 1.8 1995/05/10 20:45:03 jtc Exp $";
* to produce the hexadecimal values shown. * to produce the hexadecimal values shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.0, one = 1.0,
halF[2] = {0.5,-0.5,}, halF[2] = {0.5,-0.5,},
huge = 1.0e+300, huge = 1.0e+300,
@ -103,12 +94,7 @@ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
#ifdef __STDC__
double __ieee754_exp(double x) /* default IEEE double exp */ double __ieee754_exp(double x) /* default IEEE double exp */
#else
double __ieee754_exp(x) /* default IEEE double exp */
double x;
#endif
{ {
double y,hi,lo,c,t; double y,hi,lo,c,t;
int32_t k,xsb; int32_t k,xsb;

11
base/math/e_fmax.c Normal file
View file

@ -0,0 +1,11 @@
/*
* e_fmax.c
* Written by Alec Ari, feel free to modify, don't care
*/
#include "mathP.h"
double __ieee754_fmax(double __x, double __y)
{
return __y < __x || __builtin_isnan(__x) ? __y : __x;
}

11
base/math/e_fmin.c Normal file
View file

@ -0,0 +1,11 @@
/*
* e_fmin.c
* Written by Alec Ari, feel free to modify, don't care
*/
#include "mathP.h"
double __ieee754_fmin(double __x, double __y)
{
return __y < __x || __builtin_isnan(__x) ? __y : __x;
}

View file

@ -9,32 +9,17 @@
* is preserved. * is preserved.
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_fmod.c,v 1.8 1995/05/10 20:45:07 jtc Exp $";
#endif
/* /*
* __ieee754_fmod(x,y) * __ieee754_fmod(x,y)
* Return x mod y in exact arithmetic * Return x mod y in exact arithmetic
* Method: shift and subtract * Method: shift and subtract
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double one = 1.0, Zero[] = {0.0, -0.0,}; static const double one = 1.0, Zero[] = {0.0, -0.0,};
#else
static double one = 1.0, Zero[] = {0.0, -0.0,};
#endif
#ifdef __STDC__
double __ieee754_fmod(double x, double y) double __ieee754_fmod(double x, double y)
#else
double __ieee754_fmod(x,y)
double x,y ;
#endif
{ {
int32_t n,hx,hy,hz,ix,iy,sx,i; int32_t n,hx,hy,hz,ix,iy,sx,i;
u_int32_t lx,ly,lz; u_int32_t lx,ly,lz;

View file

@ -1,4 +1,3 @@
/* @(#)e_gamma.c 5.1 93/09/24 */ /* @(#)e_gamma.c 5.1 93/09/24 */
/* /*
* ==================================================== * ====================================================
@ -22,13 +21,7 @@
extern int signgam; extern int signgam;
#ifdef __STDC__
//__private_extern__
double __ieee754_gamma(double x) double __ieee754_gamma(double x)
#else
double __ieee754_gamma(x)
double x;
#endif
{ {
return __ieee754_gamma_r(x,&signgam); return __ieee754_gamma_r(x,&signgam);
} }

View file

@ -21,13 +21,7 @@
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
//__private_extern__
double __ieee754_gamma_r(double x, int *signgamp) double __ieee754_gamma_r(double x, int *signgamp)
#else
double __ieee754_gamma_r(x,signgamp)
double x; int *signgamp;
#endif
{ {
return __ieee754_lgamma_r(x,signgamp); return __ieee754_lgamma_r(x,signgamp);
} }

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $";
#endif
/* __ieee754_hypot(x,y) /* __ieee754_hypot(x,y)
* *
* Method : * Method :
@ -46,15 +42,9 @@ static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $";
* than 1 ulps (units in the last place) * than 1 ulps (units in the last place)
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
double __ieee754_hypot(double x, double y) double __ieee754_hypot(double x, double y)
#else
double __ieee754_hypot(x,y)
double x, y;
#endif
{ {
double a=x,b=y,t1,t2,y1,y2,w; double a=x,b=y,t1,t2,y1,y2,w;
int32_t j,k,ha,hb; int32_t j,k,ha,hb;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_j0.c,v 1.8 1995/05/10 20:45:23 jtc Exp $";
#endif
/* __ieee754_j0(x), __ieee754_y0(x) /* __ieee754_j0(x), __ieee754_y0(x)
* Bessel function of the first and second kinds of order zero. * Bessel function of the first and second kinds of order zero.
* Method -- j0(x): * Method -- j0(x):
@ -59,20 +55,11 @@ static char rcsid[] = "$NetBSD: e_j0.c,v 1.8 1995/05/10 20:45:23 jtc Exp $";
* 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static double pzero(double), qzero(double); static double pzero(double), qzero(double);
#else
static double pzero(), qzero();
#endif
#ifdef __STDC__
static const double static const double
#else
static double
#endif
huge = 1e300, huge = 1e300,
one = 1.0, one = 1.0,
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
@ -87,18 +74,9 @@ S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */
S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
#ifdef __STDC__
static const double zero = 0.0; static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_j0(double x) double __ieee754_j0(double x)
#else
double __ieee754_j0(x)
double x;
#endif
{ {
double z, s,c,ss,cc,r,u,v; double z, s,c,ss,cc,r,u,v;
int32_t hx,ix; int32_t hx,ix;
@ -145,11 +123,7 @@ static double zero = 0.0;
} }
} }
#ifdef __STDC__
static const double static const double
#else
static double
#endif
u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */
u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */
u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */
@ -162,12 +136,7 @@ v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
#ifdef __STDC__
double __ieee754_y0(double x) double __ieee754_y0(double x)
#else
double __ieee754_y0(x)
double x;
#endif
{ {
double z, s,c,ss,cc,u,v; double z, s,c,ss,cc,u,v;
int32_t hx,ix,lx; int32_t hx,ix,lx;
@ -228,11 +197,7 @@ v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
* and * and
* | pzero(x)-1-R/S | <= 2 ** ( -60.26) * | pzero(x)-1-R/S | <= 2 ** ( -60.26)
*/ */
#ifdef __STDC__
static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
-7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */
-8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */
@ -240,11 +205,8 @@ static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
-2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */
-5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */
}; };
#ifdef __STDC__
static const double pS8[5] = { static const double pS8[5] = {
#else
static double pS8[5] = {
#endif
1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */
3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */
4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */
@ -252,11 +214,7 @@ static double pS8[5] = {
4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */
}; };
#ifdef __STDC__
static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
-1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */
-7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */
-4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */
@ -264,11 +222,8 @@ static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
-3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */
-3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */
}; };
#ifdef __STDC__
static const double pS5[5] = { static const double pS5[5] = {
#else
static double pS5[5] = {
#endif
6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */
1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */
5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */
@ -276,11 +231,7 @@ static double pS5[5] = {
2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */
}; };
#ifdef __STDC__
static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#else
static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
-2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */
-7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */
-2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */
@ -288,11 +239,8 @@ static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
-5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */
-3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */
}; };
#ifdef __STDC__
static const double pS3[5] = { static const double pS3[5] = {
#else
static double pS3[5] = {
#endif
3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */
3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */
1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */
@ -300,11 +248,7 @@ static double pS3[5] = {
1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */
}; };
#ifdef __STDC__
static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
-8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */
-7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */
-1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */
@ -312,11 +256,8 @@ static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
-1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */
-3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */
}; };
#ifdef __STDC__
static const double pS2[5] = { static const double pS2[5] = {
#else
static double pS2[5] = {
#endif
2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */
1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */
2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */
@ -324,18 +265,9 @@ static double pS2[5] = {
1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
}; };
#ifdef __STDC__
static double pzero(double x) static double pzero(double x)
#else
static double pzero(x)
double x;
#endif
{ {
#ifdef __STDC__
const double *p = 0,*q = 0; const double *p = 0,*q = 0;
#else
double *p = 0,*q = 0;
#endif
double z,r,s; double z,r,s;
int32_t ix; int32_t ix;
GET_HIGH_WORD(ix,x); GET_HIGH_WORD(ix,x);
@ -360,11 +292,7 @@ static double pS2[5] = {
* and * and
* | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
*/ */
#ifdef __STDC__
static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */
1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */
@ -372,11 +300,8 @@ static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */
3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */
}; };
#ifdef __STDC__
static const double qS8[6] = { static const double qS8[6] = {
#else
static double qS8[6] = {
#endif
1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */
8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */
1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */
@ -385,11 +310,7 @@ static double qS8[6] = {
-3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */
}; };
#ifdef __STDC__
static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */
7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */
5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */
@ -397,11 +318,8 @@ static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */
1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */
}; };
#ifdef __STDC__
static const double qS5[6] = { static const double qS5[6] = {
#else
static double qS5[6] = {
#endif
8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */
2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */
1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */
@ -410,11 +328,7 @@ static double qS5[6] = {
-5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */
}; };
#ifdef __STDC__
static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#else
static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */
7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */
3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */
@ -422,11 +336,8 @@ static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */
1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */
}; };
#ifdef __STDC__
static const double qS3[6] = { static const double qS3[6] = {
#else
static double qS3[6] = {
#endif
4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */
7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */
3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */
@ -435,11 +346,7 @@ static double qS3[6] = {
-1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */
}; };
#ifdef __STDC__
static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */
7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */
1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */
@ -447,11 +354,8 @@ static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */
1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */
}; };
#ifdef __STDC__
static const double qS2[6] = { static const double qS2[6] = {
#else
static double qS2[6] = {
#endif
3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */
2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */
8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */
@ -460,18 +364,9 @@ static double qS2[6] = {
-5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
}; };
#ifdef __STDC__
static double qzero(double x) static double qzero(double x)
#else
static double qzero(x)
double x;
#endif
{ {
#ifdef __STDC__
const double *p = 0,*q = 0; const double *p = 0,*q = 0;
#else
double *p = 0,*q = 0;
#endif
double s,r,z; double s,r,z;
int32_t ix; int32_t ix;
GET_HIGH_WORD(ix,x); GET_HIGH_WORD(ix,x);

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_j1.c,v 1.8 1995/05/10 20:45:27 jtc Exp $";
#endif
/* __ieee754_j1(x), __ieee754_y1(x) /* __ieee754_j1(x), __ieee754_y1(x)
* Bessel function of the first and second kinds of order zero. * Bessel function of the first and second kinds of order zero.
* Method -- j1(x): * Method -- j1(x):
@ -59,20 +55,11 @@ static char rcsid[] = "$NetBSD: e_j1.c,v 1.8 1995/05/10 20:45:27 jtc Exp $";
* by method mentioned above. * by method mentioned above.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static double pone(double), qone(double); static double pone(double), qone(double);
#else
static double pone(), qone();
#endif
#ifdef __STDC__
static const double static const double
#else
static double
#endif
huge = 1e300, huge = 1e300,
one = 1.0, one = 1.0,
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
@ -88,18 +75,9 @@ s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */
s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */
s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
#ifdef __STDC__
static const double zero = 0.0; static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_j1(double x) double __ieee754_j1(double x)
#else
double __ieee754_j1(x)
double x;
#endif
{ {
double z, s,c,ss,cc,r,u,v,y; double z, s,c,ss,cc,r,u,v,y;
int32_t hx,ix; int32_t hx,ix;
@ -140,22 +118,15 @@ static double zero = 0.0;
return(x*0.5+r/s); return(x*0.5+r/s);
} }
#ifdef __STDC__
static const double U0[5] = { static const double U0[5] = {
#else
static double U0[5] = {
#endif
-1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */
5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */
-1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */
2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */
-9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */
}; };
#ifdef __STDC__
static const double V0[5] = { static const double V0[5] = {
#else
static double V0[5] = {
#endif
1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */
2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */
1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */
@ -163,12 +134,7 @@ static double V0[5] = {
1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
}; };
#ifdef __STDC__
double __ieee754_y1(double x) double __ieee754_y1(double x)
#else
double __ieee754_y1(x)
double x;
#endif
{ {
double z, s,c,ss,cc,u,v; double z, s,c,ss,cc,u,v;
int32_t hx,ix,lx; int32_t hx,ix,lx;
@ -226,11 +192,7 @@ static double V0[5] = {
* | pone(x)-1-R/S | <= 2 ** ( -60.06) * | pone(x)-1-R/S | <= 2 ** ( -60.06)
*/ */
#ifdef __STDC__
static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */
1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */
@ -238,11 +200,8 @@ static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */
7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */
}; };
#ifdef __STDC__
static const double ps8[5] = { static const double ps8[5] = {
#else
static double ps8[5] = {
#endif
1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */
3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */
3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */
@ -250,11 +209,7 @@ static double ps8[5] = {
3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */
}; };
#ifdef __STDC__
static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */
1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */
6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */
@ -262,11 +217,8 @@ static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */
5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */
}; };
#ifdef __STDC__
static const double ps5[5] = { static const double ps5[5] = {
#else
static double ps5[5] = {
#endif
5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */
9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */
5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */
@ -274,11 +226,7 @@ static double ps5[5] = {
1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */
}; };
#ifdef __STDC__
static const double pr3[6] = { static const double pr3[6] = {
#else
static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */
1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */
3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */
@ -286,11 +234,8 @@ static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */
4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */
}; };
#ifdef __STDC__
static const double ps3[5] = { static const double ps3[5] = {
#else
static double ps3[5] = {
#endif
3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */
3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */
1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */
@ -298,11 +243,7 @@ static double ps3[5] = {
1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */
}; };
#ifdef __STDC__
static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */
1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */
2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */
@ -310,11 +251,8 @@ static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */
5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */
}; };
#ifdef __STDC__
static const double ps2[5] = { static const double ps2[5] = {
#else
static double ps2[5] = {
#endif
2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */
1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */
2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */
@ -322,18 +260,9 @@ static double ps2[5] = {
8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
}; };
#ifdef __STDC__
static double pone(double x) static double pone(double x)
#else
static double pone(x)
double x;
#endif
{ {
#ifdef __STDC__
const double *p = 0,*q = 0; const double *p = 0,*q = 0;
#else
double *p = 0,*q = 0;
#endif
double z,r,s; double z,r,s;
int32_t ix; int32_t ix;
GET_HIGH_WORD(ix,x); GET_HIGH_WORD(ix,x);
@ -359,11 +288,7 @@ static double ps2[5] = {
* | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
*/ */
#ifdef __STDC__
static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
-1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */
-1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */
@ -371,11 +296,8 @@ static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
-1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */
-4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */
}; };
#ifdef __STDC__
static const double qs8[6] = { static const double qs8[6] = {
#else
static double qs8[6] = {
#endif
1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */
7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */
1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */
@ -384,11 +306,7 @@ static double qs8[6] = {
-2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */
}; };
#ifdef __STDC__
static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
-2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */
-1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */
-8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */
@ -396,11 +314,8 @@ static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
-1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */
-2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */
}; };
#ifdef __STDC__
static const double qs5[6] = { static const double qs5[6] = {
#else
static double qs5[6] = {
#endif
8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */
1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */
1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */
@ -409,11 +324,7 @@ static double qs5[6] = {
-4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */
}; };
#ifdef __STDC__
static const double qr3[6] = { static const double qr3[6] = {
#else
static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
-5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */
-1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */
-4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */
@ -421,11 +332,8 @@ static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
-2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */
-2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */
}; };
#ifdef __STDC__
static const double qs3[6] = { static const double qs3[6] = {
#else
static double qs3[6] = {
#endif
4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */
6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */
3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */
@ -434,11 +342,7 @@ static double qs3[6] = {
-1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */
}; };
#ifdef __STDC__
static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
-1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */
-1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */
-2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */
@ -446,11 +350,8 @@ static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
-4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */
-2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */
}; };
#ifdef __STDC__
static const double qs2[6] = { static const double qs2[6] = {
#else
static double qs2[6] = {
#endif
2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */
2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */
7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */
@ -459,18 +360,9 @@ static double qs2[6] = {
-4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
}; };
#ifdef __STDC__
static double qone(double x) static double qone(double x)
#else
static double qone(x)
double x;
#endif
{ {
#ifdef __STDC__
const double *p = 0,*q = 0; const double *p = 0,*q = 0;
#else
double *p = 0,*q = 0;
#endif
double s,r,z; double s,r,z;
int32_t ix; int32_t ix;
GET_HIGH_WORD(ix,x); GET_HIGH_WORD(ix,x);

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_jn.c,v 1.9 1995/05/10 20:45:34 jtc Exp $";
#endif
/* /*
* __ieee754_jn(n, x), __ieee754_yn(n, x) * __ieee754_jn(n, x), __ieee754_yn(n, x)
* floating point Bessel's function of the 1st and 2nd kind * floating point Bessel's function of the 1st and 2nd kind
@ -40,30 +36,16 @@ static char rcsid[] = "$NetBSD: e_jn.c,v 1.9 1995/05/10 20:45:34 jtc Exp $";
* *
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
#ifdef __STDC__
static const double zero = 0.00000000000000000000e+00; static const double zero = 0.00000000000000000000e+00;
#else
static double zero = 0.00000000000000000000e+00;
#endif
#ifdef __STDC__
double __ieee754_jn(int n, double x) double __ieee754_jn(int n, double x)
#else
double __ieee754_jn(n,x)
int n; double x;
#endif
{ {
int32_t i,hx,ix,lx, sgn; int32_t i,hx,ix,lx, sgn;
double a, b, temp, di; double a, b, temp, di;
@ -219,12 +201,7 @@ static double zero = 0.00000000000000000000e+00;
if(sgn==1) return -b; else return b; if(sgn==1) return -b; else return b;
} }
#ifdef __STDC__
double __ieee754_yn(int n, double x) double __ieee754_yn(int n, double x)
#else
double __ieee754_yn(n,x)
int n; double x;
#endif
{ {
int32_t i,hx,ix,lx; int32_t i,hx,ix,lx;
int32_t sign; int32_t sign;

View file

@ -1,4 +1,3 @@
/* @(#)e_lgamma.c 5.1 93/09/24 */ /* @(#)e_lgamma.c 5.1 93/09/24 */
/* /*
* ==================================================== * ====================================================
@ -22,13 +21,7 @@
extern int signgam; extern int signgam;
#ifdef __STDC__
//__private_extern__
double __ieee754_lgamma(double x) double __ieee754_lgamma(double x)
#else
double __ieee754_lgamma(x)
double x;
#endif
{ {
return __ieee754_lgamma_r(x,&signgam); return __ieee754_lgamma_r(x,&signgam);
} }

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_lgamma_r.c,v 1.7 1995/05/10 20:45:42 jtc Exp $";
#endif
/* __ieee754_lgamma_r(x, signgamp) /* __ieee754_lgamma_r(x, signgamp)
* Reentrant version of the logarithm of the Gamma function * Reentrant version of the logarithm of the Gamma function
* with user provide pointer for the sign of Gamma(x). * with user provide pointer for the sign of Gamma(x).
@ -81,14 +77,9 @@ static char rcsid[] = "$NetBSD: e_lgamma_r.c,v 1.7 1995/05/10 20:45:42 jtc Exp $
* *
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
@ -156,22 +147,9 @@ w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */
w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */
w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */
#ifdef __STDC__
static const double zero= 0.00000000000000000000e+00; static const double zero= 0.00000000000000000000e+00;
#else
static double zero= 0.00000000000000000000e+00;
#endif
static static __inline__ double sin_pi(double x)
#ifdef __GNUC__
__inline__
#endif
#ifdef __STDC__
double sin_pi(double x)
#else
double sin_pi(x)
double x;
#endif
{ {
double y,z; double y,z;
int n,ix; int n,ix;
@ -215,13 +193,7 @@ __inline__
return -y; return -y;
} }
#ifdef __STDC__
double __ieee754_lgamma_r(double x, int *signgamp) double __ieee754_lgamma_r(double x, int *signgamp)
#else
double __ieee754_lgamma_r(x,signgamp)
double x; int *signgamp;
#endif
{ {
double t,y,z,nadj=0.0,p,p1,p2,p3,q,r,w; double t,y,z,nadj=0.0,p,p1,p2,p3,q,r,w;
int i,hx,lx,ix; int i,hx,lx,ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $";
#endif
/* __ieee754_log(x) /* __ieee754_log(x)
* Return the logrithm of x * Return the logrithm of x
* *
@ -65,14 +61,9 @@ static char rcsid[] = "$NetBSD: e_log.c,v 1.8 1995/05/10 20:45:49 jtc Exp $";
* to produce the hexadecimal values shown. * to produce the hexadecimal values shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
@ -84,18 +75,9 @@ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
#ifdef __STDC__
static const double zero = 0.0; static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_log(double x) double __ieee754_log(double x)
#else
double __ieee754_log(x)
double x;
#endif
{ {
double hfsq,f,s,z,R,w,t1,t2,dk; double hfsq,f,s,z,R,w,t1,t2,dk;
int32_t k,hx,i,j; int32_t k,hx,i,j;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_log10.c,v 1.9 1995/05/10 20:45:51 jtc Exp $";
#endif
/* __ieee754_log10(x) /* __ieee754_log10(x)
* Return the base 10 logarithm of x * Return the base 10 logarithm of x
* *
@ -47,31 +43,17 @@ static char rcsid[] = "$NetBSD: e_log10.c,v 1.9 1995/05/10 20:45:51 jtc Exp $";
* shown. * shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */ ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
#ifdef __STDC__
static const double zero = 0.0; static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_log10(double x) double __ieee754_log10(double x)
#else
double __ieee754_log10(x)
double x;
#endif
{ {
double y,z; double y,z;
int32_t i,k,hx; int32_t i,k,hx;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $";
#endif
/* __ieee754_pow(x,y) return x**y /* __ieee754_pow(x,y) return x**y
* *
* n * n
@ -59,14 +55,9 @@ static char rcsid[] = "$NetBSD: e_pow.c,v 1.9 1995/05/12 04:57:32 jtc Exp $";
* to produce the hexadecimal values shown. * to produce the hexadecimal values shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
bp[] = {1.0, 1.5,}, bp[] = {1.0, 1.5,},
dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
@ -99,12 +90,7 @@ ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
#ifdef __STDC__
double __ieee754_pow(double x, double y) double __ieee754_pow(double x, double y)
#else
double __ieee754_pow(x,y)
double x, y;
#endif
{ {
double z,ax,z_h,z_l,p_h,p_l; double z,ax,z_h,z_l,p_h,p_l;
double y1,t1,t2,r,s,t,u,v,w; double y1,t1,t2,r,s,t,u,v,w;

View file

@ -10,27 +10,18 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_rem_pio2.c,v 1.8 1995/05/10 20:46:02 jtc Exp $";
#endif
/* __ieee754_rem_pio2(x,y) /* __ieee754_rem_pio2(x,y)
* *
* return the remainder of x rem pi/2 in y[0]+y[1] * return the remainder of x rem pi/2 in y[0]+y[1]
* use __kernel_rem_pio2() * use __kernel_rem_pio2()
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
/* /*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
*/ */
#ifdef __STDC__
static const int32_t two_over_pi[] = { static const int32_t two_over_pi[] = {
#else
static int32_t two_over_pi[] = {
#endif
0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
@ -44,11 +35,7 @@ static int32_t two_over_pi[] = {
0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
}; };
#ifdef __STDC__
static const int32_t npio2_hw[] = { static const int32_t npio2_hw[] = {
#else
static int32_t npio2_hw[] = {
#endif
0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
@ -67,11 +54,7 @@ static int32_t npio2_hw[] = {
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/ */
#ifdef __STDC__
static const double static const double
#else
static double
#endif
zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
@ -83,12 +66,7 @@ pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
#ifdef __STDC__
int32_t __ieee754_rem_pio2(double x, double *y) int32_t __ieee754_rem_pio2(double x, double *y)
#else
int32_t __ieee754_rem_pio2(x,y)
double x,y[];
#endif
{ {
double z,w,t,r,fn; double z,w,t,r,fn;
double tx[3]; double tx[3];

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_remainder.c,v 1.8 1995/05/10 20:46:05 jtc Exp $";
#endif
/* __ieee754_remainder(x,p) /* __ieee754_remainder(x,p)
* Return : * Return :
* returns x REM p = x - [x/p]*p as if in infinite * returns x REM p = x - [x/p]*p as if in infinite
@ -23,22 +19,11 @@ static char rcsid[] = "$NetBSD: e_remainder.c,v 1.8 1995/05/10 20:46:05 jtc Exp
* Based on fmod() return x-[x/p]chopped*p exactlp. * Based on fmod() return x-[x/p]chopped*p exactlp.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double zero = 0.0; static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_remainder(double x, double p) double __ieee754_remainder(double x, double p)
#else
double __ieee754_remainder(x,p)
double x,p;
#endif
{ {
int32_t hx,hp; int32_t hx,hp;
u_int32_t sx,lx,lp; u_int32_t sx,lx,lp;

View file

@ -10,38 +10,16 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_scalb.c,v 1.6 1995/05/10 20:46:09 jtc Exp $";
#endif
/* /*
* __ieee754_scalb(x, fn) is provide for * __ieee754_scalb(x, fn) is provide for
* passing various standard test suite. One * passing various standard test suite. One
* should use scalbn() instead. * should use scalbn() instead.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef _SCALB_INT
#ifdef __STDC__
double __ieee754_scalb(double x, int fn)
#else
double __ieee754_scalb(x,fn)
double x; int fn;
#endif
#else
#ifdef __STDC__
double __ieee754_scalb(double x, double fn) double __ieee754_scalb(double x, double fn)
#else
double __ieee754_scalb(x,fn)
double x, fn;
#endif
#endif
{ {
#ifdef _SCALB_INT
return scalbn(x,fn);
#else
if (isnan(x)||isnan(fn)) return x*fn; if (isnan(x)||isnan(fn)) return x*fn;
if (!finite(fn)) { if (!finite(fn)) {
if(fn>0.0) return x*fn; if(fn>0.0) return x*fn;
@ -51,5 +29,4 @@ static char rcsid[] = "$NetBSD: e_scalb.c,v 1.6 1995/05/10 20:46:09 jtc Exp $";
if ( fn > 65000.0) return scalbn(x, 65000); if ( fn > 65000.0) return scalbn(x, 65000);
if (-fn > 65000.0) return scalbn(x,-65000); if (-fn > 65000.0) return scalbn(x,-65000);
return scalbn(x,(int)fn); return scalbn(x,(int)fn);
#endif
} }

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_sinh.c,v 1.7 1995/05/10 20:46:13 jtc Exp $";
#endif
/* __ieee754_sinh(x) /* __ieee754_sinh(x)
* Method : * Method :
* mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
@ -32,21 +28,11 @@ static char rcsid[] = "$NetBSD: e_sinh.c,v 1.7 1995/05/10 20:46:13 jtc Exp $";
* only sinh(0)=0 is exact for finite x. * only sinh(0)=0 is exact for finite x.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double one = 1.0, shuge = 1.0e307; static const double one = 1.0, shuge = 1.0e307;
#else
static double one = 1.0, shuge = 1.0e307;
#endif
#ifdef __STDC__
double __ieee754_sinh(double x) double __ieee754_sinh(double x)
#else
double __ieee754_sinh(x)
double x;
#endif
{ {
double t,w,h; double t,w,h;
int32_t ix,jx; int32_t ix,jx;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $";
#endif
/* __ieee754_sqrt(x) /* __ieee754_sqrt(x)
* Return correctly rounded sqrt. * Return correctly rounded sqrt.
* ------------------------------------------ * ------------------------------------------
@ -84,21 +80,11 @@ static char rcsid[] = "$NetBSD: e_sqrt.c,v 1.8 1995/05/10 20:46:17 jtc Exp $";
*--------------- *---------------
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double one = 1.0, tiny=1.0e-300; static const double one = 1.0, tiny=1.0e-300;
#else
static double one = 1.0, tiny=1.0e-300;
#endif
#ifdef __STDC__
double __ieee754_sqrt(double x) double __ieee754_sqrt(double x)
#else
double __ieee754_sqrt(x)
double x;
#endif
{ {
double z; double z;
int32_t sign = (int)0x80000000; int32_t sign = (int)0x80000000;

View file

@ -1,112 +0,0 @@
/*******************************************************************************
* *
* File fpP.h, *
* All pack 4 dependencies for the MathLib elems plus some defines used *
* throughout MathLib. *
* *
* Copyright © 1991 Apple Computer, Inc. All rights reserved. *
* *
* Written by Ali Sazegari, started on October 1991, *
* *
* W A R N I N G: This routine expects a 64 bit double model. *
* *
*******************************************************************************/
#define NoException 0
/*******************************************************************************
* Values of constants. *
*******************************************************************************/
//#define SgnMask 0x8000
#define dSgnMask 0x80000000
#define sSgnMask 0x7FFFFFFF
//#define ExpMask 0x7FFF
#define dExpMask 0x7FF00000
#define sExpMask 0xFF000000
/* according to rounding BIG & SMALL are: */
#define BIG 1.1e+300 /* used to deliver ±° or largest number, */
#define SMALL 1.1e-300 /* used to deliver ±0 or smallest number. */
#define InfExp 0x7FF
#define dMaxExp 0x7FF00000
#define MaxExpP1 1024
#define MaxExp 1023
#define DenormLimit -52
//#define ManMask 0x80000000
#define dManMask 0x00080000
//#define IsItDenorm 0x80000000
#define dIsItDenorm 0x00080000
//#define xIsItSNaN 0x40000000
#define dIsItSNaN 0x00080000
#define dHighMan 0x000FFFFF
#define dFirstBitSet 0x00080000
#define BIAS 0x3FF
//#define GetSign 0x8000
#define dGetSign 0x80000000
#define sGetSign 0x80000000
//#define Infinity(x) ( x.hex.exponent & ExpMask ) == ExpMask
#define dInfinity(x) ( x.hex.high & dExpMask ) == dExpMask
#define sInfinity(x) ( ( x.hexsgl << 1 ) & sExpMask ) == sExpMask
//#define Exponent(x) x.hex.exponent & ExpMask
#define dExponent(x) x.hex.high & dExpMask
#define sExponent(x) ( ( x.hexsgl << 1 ) & sExpMask )
#define sZero(x) ( x.hexsgl & sSgnMask ) == 0
//#define Sign(x) ( x.hex.exponent & SgnMask ) == SgnMask
/*******************************************************************************
* Types used in the auxiliary functions. *
*******************************************************************************/
typedef struct /* Hex representation of a double. */
{
#if defined(__BIG_ENDIAN__)
unsigned long int high;
unsigned long int low;
#else
unsigned long int low;
unsigned long int high;
#endif
} dHexParts;
typedef union
{
unsigned char byties[8];
double dbl;
} DblInHex;
//enum boolean { FALSE, TRUE };
/*******************************************************************************
* Macros to access long subfields of a double value. *
*******************************************************************************/
#define highpartd(x) *((long *) &x)
#define lowpartd(x) *((long *) &x + 1)
enum {
FP_SNAN = 0, /* signaling NaN
*/
FP_QNAN = 1, /* quiet NaN
*/
FP_INFINITE = 2, /* + or - infinity
*/
FP_ZERO = 3, /* + or - zero
*/
FP_NORMAL = 4, /* all normal numbers
*/
FP_SUBNORMAL = 5 /* denormal numbers
*/
};

View file

@ -1,239 +0,0 @@
/***********************************************************************
** File: fpmacros.c
**
** Contains: C source code for implementations of floating-point
** functions which involve float format numbers, as
** defined in header <fp.h>. In particular, this file
** contains implementations of functions
** __fpclassify(d,f), __isnormal(d,f), __isfinite(d,f),
** __isnan(d,f), and __signbit(d,f). This file targets
** PowerPC platforms.
**
** Written by: Robert A. Murley, Ali Sazegari
**
** Copyright: c 2001 by Apple Computer, Inc., all rights reserved
**
** Change History (most recent first):
**
** 07 Jul 01 ram First created from fpfloatfunc.c, fp.c,
** classify.c and sign.c in MathLib v3 Mac OS9.
**
***********************************************************************/
#include "fpP.h"
#define SIGN_MASK 0x80000000
#define NSIGN_MASK 0x7fffffff
#define FEXP_MASK 0x7f800000
#define FFRAC_MASK 0x007fffff
/***********************************************************************
long int __fpclassifyf(float x) returns the classification code of the
argument x, as defined in <fp.h>.
Exceptions: INVALID signaled if x is a signaling NaN; in this case,
the FP_QNAN code is returned.
Calls: none
***********************************************************************/
long int __fpclassifyf ( float x )
{
unsigned long int iexp;
union {
unsigned long int lval;
float fval;
} z;
z.fval = x;
iexp = z.lval & FEXP_MASK; /* isolate float exponent */
if (iexp == FEXP_MASK) { /* NaN or INF case */
if ((z.lval & 0x007fffff) == 0)
return (long int) FP_INFINITE;
else if ((z.lval & 0x00400000) != 0)
return (long int) FP_QNAN;
else
return (long int) FP_SNAN;
}
if (iexp != 0) /* normal float */
return (long int) FP_NORMAL;
if (x == 0.0)
return (long int) FP_ZERO; /* zero */
else
return (long int) FP_SUBNORMAL; /* must be subnormal */
}
/***********************************************************************
Function __fpclassify,
Implementation of classify of a double number for the PowerPC.
Exceptions: INVALID signaled if x is a signaling NaN; in this case,
the FP_QNAN code is returned.
Calls: none
***********************************************************************/
long int __fpclassify ( double arg )
{
register unsigned long int exponent;
union
{
dHexParts hex;
double dbl;
} x;
x.dbl = arg;
exponent = x.hex.high & dExpMask;
if ( exponent == dExpMask )
{
if ( ( ( x.hex.high & dHighMan ) | x.hex.low ) == 0 )
return (long int) FP_INFINITE;
else
return ( x.hex.high & 0x00080000 ) ? FP_QNAN : FP_SNAN;
}
else if ( exponent != 0)
return (long int) FP_NORMAL;
else {
if ( arg == 0.0 )
return (long int) FP_ZERO;
else
return (long int) FP_SUBNORMAL;
}
}
/***********************************************************************
long int __isnormalf(float x) returns nonzero if and only if x is a
normalized float number and zero otherwise.
Exceptions: INVALID is raised if x is a signaling NaN; in this case,
zero is returned.
Calls: none
***********************************************************************/
long int __isnormalf ( float x )
{
unsigned long int iexp;
union {
unsigned long int lval;
float fval;
} z;
z.fval = x;
iexp = z.lval & FEXP_MASK; /* isolate float exponent */
return ((iexp != FEXP_MASK) && (iexp != 0));
}
long int __isnorma ( double x )
{
return ( __fpclassify ( x ) == FP_NORMAL );
}
/***********************************************************************
long int __isfinitef(float x) returns nonzero if and only if x is a
finite (normal, subnormal, or zero) float number and zero otherwise.
Exceptions: INVALID is raised if x is a signaling NaN; in this case,
zero is returned.
Calls: none
***********************************************************************/
long int __isfinitef ( float x )
{
union {
unsigned long int lval;
float fval;
} z;
z.fval = x;
return ((z.lval & FEXP_MASK) != FEXP_MASK);
}
long int __isfinite ( double x )
{
return ( __fpclassify ( x ) >= FP_ZERO );
}
/***********************************************************************
long int __isnanf(float x) returns nonzero if and only if x is a
NaN and zero otherwise.
Exceptions: INVALID is raised if x is a signaling NaN; in this case,
nonzero is returned.
Calls: none
***********************************************************************/
long int __isnanf ( float x )
{
union {
unsigned long int lval;
float fval;
} z;
z.fval = x;
return (((z.lval&FEXP_MASK) == FEXP_MASK) && ((z.lval&FFRAC_MASK) != 0));
}
long int __isnan ( double x )
{
long int class = __fpclassify(x);
return ( ( class == FP_SNAN ) || ( class == FP_QNAN ) );
}
/***********************************************************************
long int __signbitf(float x) returns nonzero if and only if the sign
bit of x is set and zero otherwise.
Exceptions: INVALID is raised if x is a signaling NaN.
Calls: none
***********************************************************************/
long int __signbitf ( float x )
{
union {
unsigned long int lval;
float fval;
} z;
z.fval = x;
return ((z.lval & SIGN_MASK) != 0);
}
/***********************************************************************
Function sign of a double.
Implementation of sign bit for the PowerPC.
Calls: none
***********************************************************************/
long int __signbit ( double arg )
{
union
{
dHexParts hex;
double dbl;
} x;
long int sign;
x.dbl = arg;
sign = ( ( x.hex.high & dSgnMask ) == dSgnMask ) ? 1 : 0;
return sign;
}

View file

@ -1,73 +0,0 @@
#if defined(__ppc__)
/*******************************************************************************
* *
* File frexpldexp.c, *
* Functions frexp(x) and ldexp(x), *
* Implementation of frexp and ldexp functions for the PowerPC. *
* *
* Copyright © 1991 Apple Computer, Inc. All rights reserved. *
* *
* Written by Ali Sazegari, started on January 1991, *
* *
* W A R N I N G: This routine expects a 64 bit double model. *
* *
* December03 1992: first rs6000 implementation. *
* October 05 1993: added special cases for NaN and ° in frexp. *
* May 27 1997: improved the performance of frexp by eliminating the *
* switch statement. *
* June 13 2001: (ram) rewrote frexp to eliminate calls to scalb and *
* logb. *
* *
*******************************************************************************/
#include <limits.h>
#include <math.h>
static const double two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
typedef union
{
struct {
#if defined(__BIG_ENDIAN__)
unsigned long int hi;
unsigned long int lo;
#else
unsigned long int lo;
unsigned long int hi;
#endif
} words;
double dbl;
} DblInHex;
double ldexp ( double value, int exp )
{
if ( exp > SHRT_MAX )
exp = SHRT_MAX;
else if ( exp < -SHRT_MAX )
exp = -SHRT_MAX;
return scalb ( value, exp );
}
double frexp ( double value, int *eptr )
{
DblInHex argument;
unsigned long int valueHead;
argument.dbl = value;
valueHead = argument.words.hi & 0x7fffffffUL; // valueHead <- |x|
*eptr = 0;
if ( valueHead >= 0x7ff00000 || ( valueHead | argument.words.lo ) == 0 )
return value; // 0, inf, or NaN
if ( valueHead < 0x00100000 )
{ // denorm
argument.dbl = two54 * value;
valueHead = argument.words.hi &0x7fffffff;
*eptr = -54;
}
*eptr += ( valueHead >> 20 ) - 1022;
argument.words.hi = ( argument.words.hi & 0x800fffff ) | 0x3fe00000;
return argument.dbl;
}
#endif /* __ppc__ */

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_cos.c,v 1.8 1995/05/10 20:46:22 jtc Exp $";
#endif
/* /*
* __kernel_cos( x, y ) * __kernel_cos( x, y )
* kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
@ -49,14 +45,9 @@ static char rcsid[] = "$NetBSD: k_cos.c,v 1.8 1995/05/10 20:46:22 jtc Exp $";
* thus, reducing the rounding error in the subtraction. * thus, reducing the rounding error in the subtraction.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
@ -65,12 +56,7 @@ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
#ifdef __STDC__
double __kernel_cos(double x, double y) double __kernel_cos(double x, double y)
#else
double __kernel_cos(x, y)
double x,y;
#endif
{ {
double a,hz,z,r,qx; double a,hz,z,r,qx;
int32_t ix; int32_t ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_rem_pio2.c,v 1.7 1995/05/10 20:46:25 jtc Exp $";
#endif
/* /*
* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
* double x[],y[]; int e0,nx,prec; int ipio2[]; * double x[],y[]; int e0,nx,prec; int ipio2[];
@ -130,20 +126,11 @@ static char rcsid[] = "$NetBSD: k_rem_pio2.c,v 1.7 1995/05/10 20:46:25 jtc Exp $
* to produce the hexadecimal values shown. * to produce the hexadecimal values shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
#else
static int init_jk[] = {2,3,4,6};
#endif
#ifdef __STDC__
static const double PIo2[] = { static const double PIo2[] = {
#else
static double PIo2[] = {
#endif
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
@ -154,22 +141,13 @@ static double PIo2[] = {
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
}; };
#ifdef __STDC__
static const double static const double
#else
static double
#endif
zero = 0.0, zero = 0.0,
one = 1.0, one = 1.0,
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
#ifdef __STDC__
int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2) int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
#else
int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
double x[], y[]; int e0,nx,prec; int32_t ipio2[];
#endif
{ {
int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
double z,fw,f[20],fq[20],q[20]; double z,fw,f[20],fq[20],q[20];

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_sin.c,v 1.8 1995/05/10 20:46:31 jtc Exp $";
#endif
/* __kernel_sin( x, y, iy) /* __kernel_sin( x, y, iy)
* kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude. * Input x is assumed to be bounded by ~pi/4 in magnitude.
@ -42,14 +38,9 @@ static char rcsid[] = "$NetBSD: k_sin.c,v 1.8 1995/05/10 20:46:31 jtc Exp $";
* sin(x) = x + (S1*x + (x *(r-y/2)+y)) * sin(x) = x + (S1*x + (x *(r-y/2)+y))
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
@ -58,12 +49,7 @@ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
#ifdef __STDC__
double __kernel_sin(double x, double y, int iy) double __kernel_sin(double x, double y, int iy)
#else
double __kernel_sin(x, y, iy)
double x,y; int iy; /* iy=0 if y is zero */
#endif
{ {
double z,r,v; double z,r,v;
int32_t ix; int32_t ix;

View file

@ -10,13 +10,7 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_standard.c,v 1.6 1995/05/10 20:46:35 jtc Exp $";
#endif
#include "math.h"
#include "mathP.h" #include "mathP.h"
#include <linux/errno.h> /* FIXME */
extern int libm_errno; extern int libm_errno;
@ -24,11 +18,7 @@ extern int printk(const char *, ...);
#define WRITE2(u,v) printk("%.*s",v,u) #define WRITE2(u,v) printk("%.*s",v,u)
#ifdef __STDC__
static const double zero = 0.0; /* used as const */ static const double zero = 0.0; /* used as const */
#else
static double zero = 0.0; /* used as const */
#endif
/* /*
* Standard conformance (non-IEEE) on exception cases. * Standard conformance (non-IEEE) on exception cases.
@ -77,13 +67,7 @@ static double zero = 0.0; /* used as const */
* 42-- pow(NaN,0.0) * 42-- pow(NaN,0.0)
*/ */
#ifdef __STDC__
double __kernel_standard(double x, double y, int type) double __kernel_standard(double x, double y, int type)
#else
double __kernel_standard(x,y,type)
double x,y; int type;
#endif
{ {
struct exception exc; struct exception exc;
#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ #ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */
@ -103,12 +87,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "acos" : "acosf"; exc.name = type < 100 ? "acos" : "acosf";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if(_LIB_VERSION == _SVID_) { if(_LIB_VERSION == _SVID_) {
(void) WRITE2("acos: DOMAIN error\n", 19); (void) WRITE2("acos: DOMAIN error\n", 19);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 2: case 2:
@ -118,12 +102,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "asin" : "asinf"; exc.name = type < 100 ? "asin" : "asinf";
exc.retval = zero; exc.retval = zero;
if(_LIB_VERSION == _POSIX_) if(_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if(_LIB_VERSION == _SVID_) { if(_LIB_VERSION == _SVID_) {
(void) WRITE2("asin: DOMAIN error\n", 19); (void) WRITE2("asin: DOMAIN error\n", 19);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 3: case 3:
@ -135,12 +119,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "atan2" : "atan2f"; exc.name = type < 100 ? "atan2" : "atan2f";
exc.retval = zero; exc.retval = zero;
if(_LIB_VERSION == _POSIX_) if(_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if(_LIB_VERSION == _SVID_) { if(_LIB_VERSION == _SVID_) {
(void) WRITE2("atan2: DOMAIN error\n", 20); (void) WRITE2("atan2: DOMAIN error\n", 20);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 4: case 4:
@ -153,9 +137,9 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 5: case 5:
@ -168,9 +152,9 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 6: case 6:
@ -183,9 +167,9 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 7: case 7:
@ -195,9 +179,9 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "exp" : "expf"; exc.name = type < 100 ? "exp" : "expf";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 8: case 8:
@ -210,12 +194,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("y0: DOMAIN error\n", 17); (void) WRITE2("y0: DOMAIN error\n", 17);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 9: case 9:
@ -228,12 +212,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("y0: DOMAIN error\n", 17); (void) WRITE2("y0: DOMAIN error\n", 17);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 10: case 10:
@ -246,12 +230,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("y1: DOMAIN error\n", 17); (void) WRITE2("y1: DOMAIN error\n", 17);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 11: case 11:
@ -264,12 +248,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("y1: DOMAIN error\n", 17); (void) WRITE2("y1: DOMAIN error\n", 17);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 12: case 12:
@ -282,12 +266,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("yn: DOMAIN error\n", 17); (void) WRITE2("yn: DOMAIN error\n", 17);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 13: case 13:
@ -300,12 +284,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("yn: DOMAIN error\n", 17); (void) WRITE2("yn: DOMAIN error\n", 17);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 14: case 14:
@ -318,9 +302,9 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 15: case 15:
@ -333,12 +317,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("lgamma: SING error\n", 19); (void) WRITE2("lgamma: SING error\n", 19);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 16: case 16:
@ -351,12 +335,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("log: SING error\n", 16); (void) WRITE2("log: SING error\n", 16);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 17: case 17:
@ -369,12 +353,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("log: DOMAIN error\n", 18); (void) WRITE2("log: DOMAIN error\n", 18);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 18: case 18:
@ -387,12 +371,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("log10: SING error\n", 18); (void) WRITE2("log10: SING error\n", 18);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 19: case 19:
@ -405,12 +389,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("log10: DOMAIN error\n", 20); (void) WRITE2("log10: DOMAIN error\n", 20);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 20: case 20:
@ -423,7 +407,7 @@ static double zero = 0.0; /* used as const */
if (_LIB_VERSION != _SVID_) exc.retval = 1.0; if (_LIB_VERSION != _SVID_) exc.retval = 1.0;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
(void) WRITE2("pow(0,0): DOMAIN error\n", 23); (void) WRITE2("pow(0,0): DOMAIN error\n", 23);
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 21: case 21:
@ -441,9 +425,9 @@ static double zero = 0.0; /* used as const */
if(x<zero&&rint(y)!=y) exc.retval = -HUGE_VAL; if(x<zero&&rint(y)!=y) exc.retval = -HUGE_VAL;
} }
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 22: case 22:
@ -453,9 +437,9 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "pow" : "powf"; exc.name = type < 100 ? "pow" : "powf";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 23: case 23:
@ -468,12 +452,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = -HUGE_VAL; exc.retval = -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("pow(0,neg): DOMAIN error\n", 25); (void) WRITE2("pow(0,neg): DOMAIN error\n", 25);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 24: case 24:
@ -486,12 +470,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = zero/zero; /* X/Open allow NaN */ exc.retval = zero/zero; /* X/Open allow NaN */
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("neg**non-integral: DOMAIN error\n", 32); (void) WRITE2("neg**non-integral: DOMAIN error\n", 32);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 25: case 25:
@ -504,9 +488,9 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL); exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL);
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 26: case 26:
@ -519,12 +503,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = zero/zero; exc.retval = zero/zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("sqrt: DOMAIN error\n", 19); (void) WRITE2("sqrt: DOMAIN error\n", 19);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 27: case 27:
@ -537,12 +521,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = zero/zero; exc.retval = zero/zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("fmod: DOMAIN error\n", 20); (void) WRITE2("fmod: DOMAIN error\n", 20);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 28: case 28:
@ -552,12 +536,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "remainder" : "remainderf"; exc.name = type < 100 ? "remainder" : "remainderf";
exc.retval = zero/zero; exc.retval = zero/zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("remainder: DOMAIN error\n", 24); (void) WRITE2("remainder: DOMAIN error\n", 24);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 29: case 29:
@ -567,12 +551,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "acosh" : "acoshf"; exc.name = type < 100 ? "acosh" : "acoshf";
exc.retval = zero/zero; exc.retval = zero/zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("acosh: DOMAIN error\n", 20); (void) WRITE2("acosh: DOMAIN error\n", 20);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 30: case 30:
@ -582,12 +566,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "atanh" : "atanhf"; exc.name = type < 100 ? "atanh" : "atanhf";
exc.retval = zero/zero; exc.retval = zero/zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("atanh: DOMAIN error\n", 20); (void) WRITE2("atanh: DOMAIN error\n", 20);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 31: case 31:
@ -597,12 +581,12 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "atanh" : "atanhf"; exc.name = type < 100 ? "atanh" : "atanhf";
exc.retval = x/zero; /* sign(x)*inf */ exc.retval = x/zero; /* sign(x)*inf */
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("atanh: SING error\n", 18); (void) WRITE2("atanh: SING error\n", 18);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 32: case 32:
@ -612,9 +596,9 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "scalb" : "scalbf"; exc.name = type < 100 ? "scalb" : "scalbf";
exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL; exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 33: case 33:
@ -624,9 +608,9 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "scalb" : "scalbf"; exc.name = type < 100 ? "scalb" : "scalbf";
exc.retval = copysign(zero,x); exc.retval = copysign(zero,x);
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 34: case 34:
@ -636,13 +620,13 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "j0" : "j0f"; exc.name = type < 100 ? "j0" : "j0f";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2(exc.name, 2); (void) WRITE2(exc.name, 2);
(void) WRITE2(": TLOSS error\n", 14); (void) WRITE2(": TLOSS error\n", 14);
} }
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 35: case 35:
@ -652,13 +636,13 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "y0" : "y0f"; exc.name = type < 100 ? "y0" : "y0f";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2(exc.name, 2); (void) WRITE2(exc.name, 2);
(void) WRITE2(": TLOSS error\n", 14); (void) WRITE2(": TLOSS error\n", 14);
} }
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 36: case 36:
@ -668,13 +652,13 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "j1" : "j1f"; exc.name = type < 100 ? "j1" : "j1f";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2(exc.name, 2); (void) WRITE2(exc.name, 2);
(void) WRITE2(": TLOSS error\n", 14); (void) WRITE2(": TLOSS error\n", 14);
} }
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 37: case 37:
@ -684,13 +668,13 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "y1" : "y1f"; exc.name = type < 100 ? "y1" : "y1f";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2(exc.name, 2); (void) WRITE2(exc.name, 2);
(void) WRITE2(": TLOSS error\n", 14); (void) WRITE2(": TLOSS error\n", 14);
} }
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 38: case 38:
@ -700,13 +684,13 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "jn" : "jnf"; exc.name = type < 100 ? "jn" : "jnf";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2(exc.name, 2); (void) WRITE2(exc.name, 2);
(void) WRITE2(": TLOSS error\n", 14); (void) WRITE2(": TLOSS error\n", 14);
} }
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 39: case 39:
@ -716,13 +700,13 @@ static double zero = 0.0; /* used as const */
exc.name = type < 100 ? "yn" : "ynf"; exc.name = type < 100 ? "yn" : "ynf";
exc.retval = zero; exc.retval = zero;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2(exc.name, 2); (void) WRITE2(exc.name, 2);
(void) WRITE2(": TLOSS error\n", 14); (void) WRITE2(": TLOSS error\n", 14);
} }
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 40: case 40:
@ -735,9 +719,9 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = ERANGE; libm_errno = 34;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = ERANGE; libm_errno = 34;
} }
break; break;
case 41: case 41:
@ -750,12 +734,12 @@ static double zero = 0.0; /* used as const */
else else
exc.retval = HUGE_VAL; exc.retval = HUGE_VAL;
if (_LIB_VERSION == _POSIX_) if (_LIB_VERSION == _POSIX_)
libm_errno = EDOM; libm_errno = 33;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
if (_LIB_VERSION == _SVID_) { if (_LIB_VERSION == _SVID_) {
(void) WRITE2("gamma: SING error\n", 18); (void) WRITE2("gamma: SING error\n", 18);
} }
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
case 42: case 42:
@ -768,7 +752,7 @@ static double zero = 0.0; /* used as const */
if (_LIB_VERSION == _IEEE_ || if (_LIB_VERSION == _IEEE_ ||
_LIB_VERSION == _POSIX_) exc.retval = 1.0; _LIB_VERSION == _POSIX_) exc.retval = 1.0;
else if (!matherr(&exc)) { else if (!matherr(&exc)) {
libm_errno = EDOM; libm_errno = 33;
} }
break; break;
} }

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_tan.c,v 1.8 1995/05/10 20:46:37 jtc Exp $";
#endif
/* __kernel_tan( x, y, k ) /* __kernel_tan( x, y, k )
* kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude. * Input x is assumed to be bounded by ~pi/4 in magnitude.
@ -48,13 +44,9 @@ static char rcsid[] = "$NetBSD: k_tan.c,v 1.8 1995/05/10 20:46:37 jtc Exp $";
* = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
@ -74,12 +66,7 @@ T[] = {
2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
}; };
#ifdef __STDC__
double __kernel_tan(double x, double y, int iy) double __kernel_tan(double x, double y, int iy)
#else
double __kernel_tan(x, y, iy)
double x,y; int iy;
#endif
{ {
double z,r,v,w,s; double z,r,v,w,s;
int32_t ix,hx; int32_t ix,hx;

View file

@ -21,6 +21,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#define __USE_MISC
#define __USE_SVID
#define __USE_ISOC99 1
#include <rtai_math.h> #include <rtai_math.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
@ -44,12 +47,9 @@ void __rtai_math_exit(void)
} }
} }
#ifndef CONFIG_RTAI_MATH_BUILTIN
module_init(__rtai_math_init); module_init(__rtai_math_init);
module_exit(__rtai_math_exit); module_exit(__rtai_math_exit);
#endif /* CONFIG_RTAI_MATH_BUILTIN */
#ifdef CONFIG_KBUILD
EXPORT_SYMBOL(acos); EXPORT_SYMBOL(acos);
EXPORT_SYMBOL(asin); EXPORT_SYMBOL(asin);
EXPORT_SYMBOL(atan); EXPORT_SYMBOL(atan);
@ -61,6 +61,7 @@ EXPORT_SYMBOL(cosh);
EXPORT_SYMBOL(exp); EXPORT_SYMBOL(exp);
EXPORT_SYMBOL(expm1); EXPORT_SYMBOL(expm1);
EXPORT_SYMBOL(fabs); EXPORT_SYMBOL(fabs);
EXPORT_SYMBOL(finite);
EXPORT_SYMBOL(floor); EXPORT_SYMBOL(floor);
EXPORT_SYMBOL(fmod); EXPORT_SYMBOL(fmod);
EXPORT_SYMBOL(frexp); EXPORT_SYMBOL(frexp);
@ -74,8 +75,6 @@ EXPORT_SYMBOL(sinh);
EXPORT_SYMBOL(sqrt); EXPORT_SYMBOL(sqrt);
EXPORT_SYMBOL(tan); EXPORT_SYMBOL(tan);
EXPORT_SYMBOL(tanh); EXPORT_SYMBOL(tanh);
#ifdef CONFIG_RTAI_MATH_C99
EXPORT_SYMBOL(acosh); EXPORT_SYMBOL(acosh);
EXPORT_SYMBOL(asinh); EXPORT_SYMBOL(asinh);
EXPORT_SYMBOL(atanh); EXPORT_SYMBOL(atanh);
@ -95,22 +94,14 @@ EXPORT_SYMBOL(ldexp);
EXPORT_SYMBOL(lgamma); EXPORT_SYMBOL(lgamma);
EXPORT_SYMBOL(lgamma_r); EXPORT_SYMBOL(lgamma_r);
EXPORT_SYMBOL(log1p); EXPORT_SYMBOL(log1p);
EXPORT_SYMBOL(logb);
EXPORT_SYMBOL(matherr); EXPORT_SYMBOL(matherr);
EXPORT_SYMBOL(nearbyint);
EXPORT_SYMBOL(nextafter); EXPORT_SYMBOL(nextafter);
EXPORT_SYMBOL(remainder); EXPORT_SYMBOL(remainder);
EXPORT_SYMBOL(rint); EXPORT_SYMBOL(rint);
EXPORT_SYMBOL(rinttol);
EXPORT_SYMBOL(round);
EXPORT_SYMBOL(roundtol);
EXPORT_SYMBOL(scalb); EXPORT_SYMBOL(scalb);
EXPORT_SYMBOL(signgam); EXPORT_SYMBOL(signgam);
EXPORT_SYMBOL(significand); EXPORT_SYMBOL(significand);
EXPORT_SYMBOL(trunc);
EXPORT_SYMBOL(y0); EXPORT_SYMBOL(y0);
EXPORT_SYMBOL(y1); EXPORT_SYMBOL(y1);
EXPORT_SYMBOL(yn); EXPORT_SYMBOL(yn);
EXPORT_SYMBOL(libm_errno); EXPORT_SYMBOL(libm_errno);
#endif /* CONFIG_RTAI_MATH_C99 */
#endif /* CONFIG_KBUILD */

View file

@ -1,104 +0,0 @@
#if defined(__ppc__)
/*******************************************************************************
* *
* File logb.c, *
* Functions logb. *
* Implementation of logb for the PowerPC. *
* *
* Copyright © 1991 Apple Computer, Inc. All rights reserved. *
* *
* Written by Ali Sazegari, started on June 1991, *
* *
* August 26 1991: removed CFront Version 1.1d17 warnings. *
* August 27 1991: no errors reported by the test suite. *
* November 11 1991: changed CLASSEXTENDED to the macro CLASSIFY and *
* + or - infinity to constants. *
* November 18 1991: changed the macro CLASSIFY to CLASSEXTENDEDint to *
* improve performance. *
* February 07 1992: changed bit operations to macros ( object size is *
* unchanged ). *
* September24 1992: took the "#include support.h" out. *
* December 03 1992: first rs/6000 port. *
* August 30 1992: set the divide by zero for the zero argument case. *
* October 05 1993: corrected the environment. *
* October 17 1994: replaced all environmental functions with __setflm. *
* May 28 1997: made speed improvements. *
* April 30 2001: forst mac os x port using gcc. *
* *
********************************************************************************
* The C math library offers a similar function called "frexp". It is *
* different in details from logb, but similar in spirit. This current *
* implementation of logb follows the recommendation in IEEE Standard 854 *
* which is different in its handling of denormalized numbers from the IEEE *
* Standard 754. *
*******************************************************************************/
typedef union
{
struct {
#if defined(__BIG_ENDIAN__)
unsigned long int hi;
unsigned long int lo;
#else
unsigned long int lo;
unsigned long int hi;
#endif
} words;
double dbl;
} DblInHex;
static const double twoTo52 = 4.50359962737049600e15; // 0x1p52
static const double klTod = 4503601774854144.0; // 0x1.000008p52
static const unsigned long int signMask = 0x80000000ul;
static const DblInHex minusInf = {{ 0xFFF00000, 0x00000000 }};
/*******************************************************************************
********************************************************************************
* L O G B *
********************************************************************************
*******************************************************************************/
double logb ( double x )
{
DblInHex xInHex;
long int shiftedExp;
xInHex.dbl = x;
shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20;
if ( shiftedExp == 2047 )
{ // NaN or INF
if ( ( ( xInHex.words.hi & signMask ) == 0 ) || ( x != x ) )
return x; // NaN or +INF return x
else
return -x; // -INF returns +INF
}
if ( shiftedExp != 0 ) // normal number
shiftedExp -= 1023; // unbias exponent
else if ( x == 0.0 )
{ // zero
xInHex.words.hi = 0x0UL; // return -infinity
return ( minusInf.dbl );
}
else
{ // subnormal number
xInHex.dbl *= twoTo52; // scale up
shiftedExp = ( xInHex.words.hi & 0x7ff00000UL ) >> 20;
shiftedExp -= 1075; // unbias exponent
}
if ( shiftedExp == 0 ) // zero result
return ( 0.0 );
else
{ // nonzero result
xInHex.dbl = klTod;
xInHex.words.lo += shiftedExp;
return ( xInHex.dbl - klTod );
}
}
#endif /* __ppc__ */

View file

@ -17,8 +17,9 @@
#ifndef _MATH_PRIVATE_H_ #ifndef _MATH_PRIVATE_H_
#define _MATH_PRIVATE_H_ #define _MATH_PRIVATE_H_
#include <endian.h> #include <asm/types.h>
#include <sys/types.h> typedef u32 u_int32_t;
typedef s32 int32_t;
/* The original fdlibm code used statements like: /* The original fdlibm code used statements like:
n0 = ((*(int*)&one)>>29)^1; * index of high word * n0 = ((*(int*)&one)>>29)^1; * index of high word *
@ -39,7 +40,7 @@
* big endian. * big endian.
*/ */
#if (__BYTE_ORDER == __BIG_ENDIAN) || defined(__arm__) #if defined(__BIG_ENDIAN)
typedef union typedef union
{ {
@ -51,9 +52,8 @@ typedef union
} parts; } parts;
} ieee_double_shape_type; } ieee_double_shape_type;
#endif
#if (__BYTE_ORDER == __LITTLE_ENDIAN) && !defined(__arm__) #else
typedef union typedef union
{ {
@ -153,79 +153,83 @@ do { \
} while (0) } while (0)
/* ieee style elementary functions */ /* ieee style elementary functions */
extern double __ieee754_sqrt __P((double)); extern double __ieee754_sqrt(double);
extern double __ieee754_acos __P((double)); extern double __ieee754_acos(double);
extern double __ieee754_acosh __P((double)); extern double __ieee754_acosh(double);
extern double __ieee754_log __P((double)); extern double __ieee754_log(double);
extern double __ieee754_atanh __P((double)); extern double __ieee754_atanh(double);
extern double __ieee754_asin __P((double)); extern double __ieee754_asin(double);
extern double __ieee754_atan2 __P((double,double)); extern double __ieee754_atan2(double,double);
extern double __ieee754_exp __P((double)); extern double __ieee754_exp(double);
extern double __ieee754_cosh __P((double)); extern double __ieee754_cosh(double);
extern double __ieee754_fmod __P((double,double)); extern double __ieee754_fmod(double,double);
extern double __ieee754_pow __P((double,double)); extern double __ieee754_pow(double,double);
extern double __ieee754_lgamma_r __P((double,int *)); extern double __ieee754_lgamma_r(double,int *);
extern double __ieee754_gamma_r __P((double,int *)); extern double __ieee754_gamma_r(double,int *);
extern double __ieee754_lgamma __P((double)); extern double __ieee754_lgamma(double);
extern double __ieee754_gamma __P((double)); extern double __ieee754_gamma(double);
extern double __ieee754_log10 __P((double)); extern double __ieee754_log10(double);
extern double __ieee754_sinh __P((double)); extern double __ieee754_sinh(double);
extern double __ieee754_hypot __P((double,double)); extern double __ieee754_hypot(double,double);
extern double __ieee754_j0 __P((double)); extern double __ieee754_j0(double);
extern double __ieee754_j1 __P((double)); extern double __ieee754_j1(double);
extern double __ieee754_y0 __P((double)); extern double __ieee754_y0(double);
extern double __ieee754_y1 __P((double)); extern double __ieee754_y1(double);
extern double __ieee754_jn __P((int,double)); extern double __ieee754_jn(int,double);
extern double __ieee754_yn __P((int,double)); extern double __ieee754_yn(int,double);
extern double __ieee754_remainder __P((double,double)); extern double __ieee754_remainder(double,double);
extern int __ieee754_rem_pio2 __P((double,double*)); extern int __ieee754_rem_pio2(double,double*);
#if defined(_SCALB_INT) extern double __ieee754_fmin(double,double);
extern double __ieee754_scalb __P((double,int)); extern double __ieee754_fmax(double,double);
#else extern double __ieee754_scalb(double,double);
extern double __ieee754_scalb __P((double,double));
#endif
/* fdlibm kernel function */ /* fdlibm kernel function */
extern double __kernel_standard __P((double,double,int)); extern double __kernel_standard(double,double,int);
extern double __kernel_sin __P((double,double,int)); extern double __kernel_sin(double,double,int);
extern double __kernel_cos __P((double,double)); extern double __kernel_cos(double,double);
extern double __kernel_tan __P((double,double,int)); extern double __kernel_tan(double,double,int);
extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*)); extern int __kernel_rem_pio2(double*,double*,int,int,int,const int*);
/* ieee style elementary float functions */ /* ieee style elementary float functions */
extern float __ieee754_sqrtf __P((float)); extern float __ieee754_sqrtf(float);
extern float __ieee754_acosf __P((float)); extern float __ieee754_acosf(float);
extern float __ieee754_acoshf __P((float)); extern float __ieee754_acoshf(float);
extern float __ieee754_logf __P((float)); extern float __ieee754_logf(float);
extern float __ieee754_atanhf __P((float)); extern float __ieee754_atanhf(float);
extern float __ieee754_asinf __P((float)); extern float __ieee754_asinf(float);
extern float __ieee754_atan2f __P((float,float)); extern float __ieee754_atan2f(float,float);
extern float __ieee754_expf __P((float)); extern float __ieee754_expf(float);
extern float __ieee754_coshf __P((float)); extern float __ieee754_coshf(float);
extern float __ieee754_fmodf __P((float,float)); extern float __ieee754_fmodf(float,float);
extern float __ieee754_powf __P((float,float)); extern float __ieee754_powf(float,float);
extern float __ieee754_lgammaf_r __P((float,int *)); extern float __ieee754_lgammaf_r(float,int *);
extern float __ieee754_gammaf_r __P((float,int *)); extern float __ieee754_gammaf_r(float,int *);
extern float __ieee754_lgammaf __P((float)); extern float __ieee754_lgammaf(float);
extern float __ieee754_gammaf __P((float)); extern float __ieee754_gammaf(float);
extern float __ieee754_log10f __P((float)); extern float __ieee754_log10f(float);
extern float __ieee754_sinhf __P((float)); extern float __ieee754_sinhf(float);
extern float __ieee754_hypotf __P((float,float)); extern float __ieee754_hypotf(float,float);
extern float __ieee754_j0f __P((float)); extern float __ieee754_j0f(float);
extern float __ieee754_j1f __P((float)); extern float __ieee754_j1f(float);
extern float __ieee754_y0f __P((float)); extern float __ieee754_y0f(float);
extern float __ieee754_y1f __P((float)); extern float __ieee754_y1f(float);
extern float __ieee754_jnf __P((int,float)); extern float __ieee754_jnf(int,float);
extern float __ieee754_ynf __P((int,float)); extern float __ieee754_ynf(int,float);
extern float __ieee754_remainderf __P((float,float)); extern float __ieee754_remainderf(float,float);
extern int __ieee754_rem_pio2f __P((float,float*)); extern int __ieee754_rem_pio2f(float,float*);
extern float __ieee754_scalbf __P((float,float)); extern float __ieee754_scalbf(float,float);
/* float versions of fdlibm kernel functions */ /* float versions of fdlibm kernel functions */
extern float __kernel_sinf __P((float,float,int)); extern float __kernel_sinf(float,float,int);
extern float __kernel_cosf __P((float,float)); extern float __kernel_cosf(float,float);
extern float __kernel_tanf __P((float,float,int)); extern float __kernel_tanf(float,float,int);
extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int*)); extern int __kernel_rem_pio2f(float*,float*,int,int,int,const int*);
#define __USE_MISC
#define __USE_SVID
#define __USE_ISOC99 1
#include <rtai_math.h>
extern int finite(double);
#endif /* _MATH_PRIVATE_H_ */ #endif /* _MATH_PRIVATE_H_ */

View file

@ -1,632 +0,0 @@
/*******************************************************************************
** File: rndint.c
**
** Contains: C source code for implementations of floating-point
** functions which round to integral value or format, as
** defined in header <fp.h>. In particular, this file
** contains implementations of functions rint, nearbyint,
** rinttol, round, roundtol, trunc, modf and modfl. This file
** targets PowerPC or Power platforms.
**
** Written by: A. Sazegari, Apple AltiVec Group
** Created originally by Jon Okada, Apple Numerics Group
**
** Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved
**
** Change History (most recent first):
**
** 13 Jul 01 ram replaced --setflm calls with inline assembly
** 03 Mar 01 ali first port to os x using gcc, added the crucial __setflm
** definition.
** 1. removed double_t, put in double for now.
** 2. removed iclass from nearbyint.
** 3. removed wrong comments intrunc.
** 4.
** 13 May 97 ali made performance improvements in rint, rinttol, roundtol
** and trunc by folding some of the taligent ideas into this
** implementation. nearbyint is faster than the one in taligent,
** rint is more elegant, but slower by %30 than the taligent one.
** 09 Apr 97 ali deleted modfl and deferred to AuxiliaryDD.c
** 15 Sep 94 ali Major overhaul and performance improvements of all functions.
** 20 Jul 94 PAF New faster version
** 16 Jul 93 ali Added the modfl function.
** 18 Feb 93 ali Changed the return value of fenv functions
** feclearexcept and feraiseexcept to their new
** NCEG X3J11.1/93-001 definitions.
** 16 Dec 92 JPO Removed __itrunc implementation to a
** separate file.
** 15 Dec 92 JPO Added __itrunc implementation and modified
** rinttol to include conversion from double
** to long int format. Modified roundtol to
** call __itrunc.
** 10 Dec 92 JPO Added modf (double) implementation.
** 04 Dec 92 JPO First created.
**
*******************************************************************************/
#include <limits.h>
#include <math.h>
#if !defined(__ppc__)
#define asm(x)
#endif
#define SET_INVALID 0x01000000UL
typedef union
{
struct {
#if defined(__BIG_ENDIAN__)
unsigned long int hi;
unsigned long int lo;
#else
unsigned long int lo;
unsigned long int hi;
#endif
} words;
double dbl;
} DblInHex;
static const unsigned long int signMask = 0x80000000ul;
static const double twoTo52 = 4503599627370496.0;
static const double doubleToLong = 4503603922337792.0; // 2^52
static const DblInHex Huge = {{ 0x7FF00000, 0x00000000 }};
static const DblInHex TOWARDZERO = {{ 0x00000000, 0x00000001 }};
/*******************************************************************************
* *
* The function rint rounds its double argument to integral value *
* according to the current rounding direction and returns the result in *
* double format. This function signals inexact if an ordered return *
* value is not equal to the operand. *
* *
********************************************************************************
* *
* This function calls: fabs. *
* *
*******************************************************************************/
/*******************************************************************************
* First, an elegant implementation. *
********************************************************************************
*
*double rint ( double x )
* {
* double y;
*
* y = twoTo52.fval;
*
* if ( fabs ( x ) >= y ) // huge case is exact
* return x;
* if ( x < 0 ) y = -y; // negative case
* y = ( x + y ) - y; // force rounding
* if ( y == 0.0 ) // zero results mirror sign of x
* y = copysign ( y, x );
* return ( y );
* }
********************************************************************************
* Now a bit twidling version that is about %30 faster. *
*******************************************************************************/
#if defined(__ppc__)
double rint ( double x )
{
DblInHex argument;
register double y;
unsigned long int xHead;
register long int target;
argument.dbl = x;
xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x|
target = ( argument.words.hi < signMask ); // flags positive sign
if ( xHead < 0x43300000ul )
/*******************************************************************************
* Is |x| < 2.0^52? *
*******************************************************************************/
{
if ( xHead < 0x3ff00000ul )
/*******************************************************************************
* Is |x| < 1.0? *
*******************************************************************************/
{
if ( target )
y = ( x + twoTo52 ) - twoTo52; // round at binary point
else
y = ( x - twoTo52 ) + twoTo52; // round at binary point
if ( y == 0.0 )
{ // fix sign of zero result
if ( target )
return ( 0.0 );
else
return ( -0.0 );
}
return y;
}
/*******************************************************************************
* Is 1.0 < |x| < 2.0^52? *
*******************************************************************************/
if ( target )
return ( ( x + twoTo52 ) - twoTo52 ); // round at binary pt.
else
return ( ( x - twoTo52 ) + twoTo52 );
}
/*******************************************************************************
* |x| >= 2.0^52 or x is a NaN. *
*******************************************************************************/
return ( x );
}
#endif /* __ppc__ */
/*******************************************************************************
* *
* The function nearbyint rounds its double argument to integral value *
* according to the current rounding direction and returns the result in *
* double format. This function does not signal inexact. *
* *
********************************************************************************
* *
* This function calls fabs and copysign. *
* *
*******************************************************************************/
double nearbyint ( double x )
{
double y;
#if defined(__ppc__)
double OldEnvironment;
#endif /* __ppc__ */
y = twoTo52;
asm ("mffs %0" : "=f" (OldEnvironment)); /* get the environement */
if ( fabs ( x ) >= y ) /* huge case is exact */
return x;
if ( x < 0 ) y = -y; /* negative case */
y = ( x + y ) - y; /* force rounding */
if ( y == 0.0 ) /* zero results mirror sign of x */
y = copysign ( y, x );
// restore old flags
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment ));
return ( y );
}
/*******************************************************************************
* *
* The function rinttol converts its double argument to integral value *
* according to the current rounding direction and returns the result in *
* long int format. This conversion signals invalid if the argument is a *
* NaN or the rounded intermediate result is out of range of the *
* destination long int format, and it delivers an unspecified result in *
* this case. This function signals inexact if the rounded result is *
* within range of the long int format but unequal to the operand. *
* *
*******************************************************************************/
long int rinttol ( double x )
{
register double y;
DblInHex argument, OldEnvironment;
unsigned long int xHead;
register long int target;
argument.dbl = x;
target = ( argument.words.hi < signMask ); // flag positive sign
xHead = argument.words.hi & 0x7ffffffful; // high 32 bits of x
if ( target )
/*******************************************************************************
* Sign of x is positive. *
*******************************************************************************/
{
if ( xHead < 0x41dffffful )
{ // x is safely in long range
y = ( x + twoTo52 ) - twoTo52; // round at binary point
argument.dbl = y + doubleToLong; // force result into argument.words.lo
return ( ( long ) argument.words.lo );
}
asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
if ( xHead > 0x41dffffful )
{ // x is safely out of long range
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( LONG_MAX );
}
/*******************************************************************************
* x > 0.0 and may or may not be out of range of long. *
*******************************************************************************/
y = ( x + twoTo52 ) - twoTo52; // do rounding
if ( y > ( double ) LONG_MAX )
{ // out of range of long
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( LONG_MAX );
}
argument.dbl = y + doubleToLong; // in range
return ( ( long ) argument.words.lo ); // return result & flags
}
/*******************************************************************************
* Sign of x is negative. *
*******************************************************************************/
if ( xHead < 0x41e00000ul )
{ // x is safely in long range
y = ( x - twoTo52 ) + twoTo52;
argument.dbl = y + doubleToLong;
return ( ( long ) argument.words.lo );
}
asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
if ( xHead > 0x41e00000ul )
{ // x is safely out of long range
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( LONG_MIN );
}
/*******************************************************************************
* x < 0.0 and may or may not be out of range of long. *
*******************************************************************************/
y = ( x - twoTo52 ) + twoTo52; // do rounding
if ( y < ( double ) LONG_MIN )
{ // out of range of long
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( LONG_MIN );
}
argument.dbl = y + doubleToLong; // in range
return ( ( long ) argument.words.lo ); // return result & flags
}
/*******************************************************************************
* *
* The function round rounds its double argument to integral value *
* according to the "add half to the magnitude and truncate" rounding of *
* Pascal's Round function and FORTRAN's ANINT function and returns the *
* result in double format. This function signals inexact if an ordered *
* return value is not equal to the operand. *
* *
*******************************************************************************/
double round ( double x )
{
DblInHex argument, OldEnvironment;
register double y, z;
register unsigned long int xHead;
register long int target;
argument.dbl = x;
xHead = argument.words.hi & 0x7fffffffUL; // xHead <- high half of |x|
target = ( argument.words.hi < signMask ); // flag positive sign
if ( xHead < 0x43300000ul )
/*******************************************************************************
* Is |x| < 2.0^52? *
*******************************************************************************/
{
if ( xHead < 0x3ff00000ul )
/*******************************************************************************
* Is |x| < 1.0? *
*******************************************************************************/
{
asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
if ( xHead < 0x3fe00000ul )
/*******************************************************************************
* Is |x| < 0.5? *
*******************************************************************************/
{
if ( ( xHead | argument.words.lo ) != 0ul )
OldEnvironment.words.lo |= 0x02000000ul;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
if ( target )
return ( 0.0 );
else
return ( -0.0 );
}
/*******************************************************************************
* Is 0.5 ² |x| < 1.0? *
*******************************************************************************/
OldEnvironment.words.lo |= 0x02000000ul;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
if ( target )
return ( 1.0 );
else
return ( -1.0 );
}
/*******************************************************************************
* Is 1.0 < |x| < 2.0^52? *
*******************************************************************************/
if ( target )
{ // positive x
y = ( x + twoTo52 ) - twoTo52; // round at binary point
if ( y == x ) // exact case
return ( x );
z = x + 0.5; // inexact case
y = ( z + twoTo52 ) - twoTo52; // round at binary point
if ( y > z )
return ( y - 1.0 );
else
return ( y );
}
/*******************************************************************************
* Is x < 0? *
*******************************************************************************/
else
{
y = ( x - twoTo52 ) + twoTo52; // round at binary point
if ( y == x )
return ( x );
z = x - 0.5;
y = ( z - twoTo52 ) + twoTo52; // round at binary point
if ( y < z )
return ( y + 1.0 );
else
return ( y );
}
}
/*******************************************************************************
* |x| >= 2.0^52 or x is a NaN. *
*******************************************************************************/
return ( x );
}
/*******************************************************************************
* *
* The function roundtol converts its double argument to integral format *
* according to the "add half to the magnitude and chop" rounding mode of *
* Pascal's Round function and FORTRAN's NINT function. This conversion *
* signals invalid if the argument is a NaN or the rounded intermediate *
* result is out of range of the destination long int format, and it *
* delivers an unspecified result in this case. This function signals *
* inexact if the rounded result is within range of the long int format but *
* unequal to the operand. *
* *
*******************************************************************************/
long int roundtol ( double x )
{
register double y, z;
DblInHex argument, OldEnvironment;
register unsigned long int xhi;
register long int target;
#if defined(__ppc__)
const DblInHex kTZ = {{ 0x0, 0x1 }};
const DblInHex kUP = {{ 0x0, 0x2 }};
#endif /* __ppc__ */
argument.dbl = x;
xhi = argument.words.hi & 0x7ffffffful; // high 32 bits of x
target = ( argument.words.hi < signMask ); // flag positive sign
if ( xhi > 0x41e00000ul )
/*******************************************************************************
* Is x is out of long range or NaN? *
*******************************************************************************/
{
asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // get environment
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
if ( target ) // pin result
return ( LONG_MAX );
else
return ( LONG_MIN );
}
if ( target )
/*******************************************************************************
* Is sign of x is "+"? *
*******************************************************************************/
{
if ( x < 2147483647.5 )
/*******************************************************************************
* x is in the range of a long. *
*******************************************************************************/
{
y = ( x + doubleToLong ) - doubleToLong; // round at binary point
if ( y != x )
{ // inexact case
asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kTZ.dbl )); // truncate rounding
z = x + 0.5; // truncate x + 0.5
argument.dbl = z + doubleToLong;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( ( long ) argument.words.lo );
}
argument.dbl = y + doubleToLong; // force result into argument.words.lo
return ( ( long ) argument.words.lo ); // return long result
}
/*******************************************************************************
* Rounded positive x is out of the range of a long. *
*******************************************************************************/
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( LONG_MAX ); // return pinned result
}
/*******************************************************************************
* x < 0.0 and may or may not be out of the range of a long. *
*******************************************************************************/
if ( x > -2147483648.5 )
/*******************************************************************************
* x is in the range of a long. *
*******************************************************************************/
{
y = ( x + doubleToLong ) - doubleToLong; // round at binary point
if ( y != x )
{ // inexact case
asm ("mffs %0" : "=f" (OldEnvironment.dbl)); // save environment
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( kUP.dbl )); // round up
z = x - 0.5; // truncate x - 0.5
argument.dbl = z + doubleToLong;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( ( long ) argument.words.lo );
}
argument.dbl = y + doubleToLong;
return ( ( long ) argument.words.lo ); // return long result
}
/*******************************************************************************
* Rounded negative x is out of the range of a long. *
*******************************************************************************/
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
OldEnvironment.words.lo |= SET_INVALID;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
return ( LONG_MIN ); // return pinned result
}
/*******************************************************************************
* *
* The function trunc truncates its double argument to integral value *
* and returns the result in double format. This function signals *
* inexact if an ordered return value is not equal to the operand. *
* *
*******************************************************************************/
double trunc ( double x )
{
DblInHex argument,OldEnvironment;
register double y;
register unsigned long int xhi;
register long int target;
argument.dbl = x;
xhi = argument.words.hi & 0x7fffffffUL; // xhi <- high half of |x|
target = ( argument.words.hi < signMask ); // flag positive sign
if ( xhi < 0x43300000ul )
/*******************************************************************************
* Is |x| < 2.0^53? *
*******************************************************************************/
{
if ( xhi < 0x3ff00000ul )
/*******************************************************************************
* Is |x| < 1.0? *
*******************************************************************************/
{
if ( ( xhi | argument.words.lo ) != 0ul )
{ // raise deserved INEXACT
asm ("mffs %0" : "=f" (OldEnvironment.dbl));
OldEnvironment.words.lo |= 0x02000000ul;
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment.dbl ));
}
if ( target ) // return properly signed zero
return ( 0.0 );
else
return ( -0.0 );
}
/*******************************************************************************
* Is 1.0 < |x| < 2.0^52? *
*******************************************************************************/
if ( target )
{
y = ( x + twoTo52 ) - twoTo52; // round at binary point
if ( y > x )
return ( y - 1.0 );
else
return ( y );
}
else
{
y = ( x - twoTo52 ) + twoTo52; // round at binary point.
if ( y < x )
return ( y + 1.0 );
else
return ( y );
}
}
/*******************************************************************************
* Is |x| >= 2.0^52 or x is a NaN. *
*******************************************************************************/
return ( x );
}
/*******************************************************************************
* The modf family of functions separate a floating-point number into its *
* fractional and integral parts, returning the fractional part and writing *
* the integral part in floating-point format to the object pointed to by a *
* pointer argument. If the input argument is integral or infinite in *
* value, the return value is a zero with the sign of the input argument. *
* The modf family of functions raises no floating-point exceptions. older *
* implemenation set the INVALID flag due to signaling NaN input. *
* *
*******************************************************************************/
/*******************************************************************************
* modf is the double implementation. *
*******************************************************************************/
#if defined(__ppc__)
double modf ( double x, double *iptr )
{
register double OldEnvironment, xtrunc;
register unsigned long int xHead, signBit;
DblInHex argument;
argument.dbl = x;
xHead = argument.words.hi & 0x7ffffffful; // |x| high bit pattern
signBit = ( argument.words.hi & 0x80000000ul ); // isolate sign bit
if (xHead == 0x7ff81fe0)
signBit = signBit | 0;
if ( xHead < 0x43300000ul )
/*******************************************************************************
* Is |x| < 2.0^53? *
*******************************************************************************/
{
if ( xHead < 0x3ff00000ul )
/*******************************************************************************
* Is |x| < 1.0? *
*******************************************************************************/
{
argument.words.hi = signBit; // truncate to zero
argument.words.lo = 0ul;
*iptr = argument.dbl;
return ( x );
}
/*******************************************************************************
* Is 1.0 < |x| < 2.0^52? *
*******************************************************************************/
asm ("mffs %0" : "=f" (OldEnvironment)); // save environment
// round toward zero
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( TOWARDZERO.dbl ));
if ( signBit == 0ul ) // truncate to integer
xtrunc = ( x + twoTo52 ) - twoTo52;
else
xtrunc = ( x - twoTo52 ) + twoTo52;
// restore caller's env
asm ("mtfsf 255,%0" : /*NULLOUT*/ : /*IN*/ "f" ( OldEnvironment ));
*iptr = xtrunc; // store integral part
if ( x != xtrunc ) // nonzero fraction
return ( x - xtrunc );
else
{ // zero with x's sign
argument.words.hi = signBit;
argument.words.lo = 0ul;
return ( argument.dbl );
}
}
*iptr = x; // x is integral or NaN
if ( x != x ) // NaN is returned
return x;
else
{ // zero with x's sign
argument.words.hi = signBit;
argument.words.lo = 0ul;
return ( argument.dbl );
}
}
#endif /* __ppc__ */

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_asinh.c,v 1.9 1995/05/12 04:57:37 jtc Exp $";
#endif
/* asinh(x) /* asinh(x)
* Method : * Method :
* Based on * Based on
@ -25,24 +21,14 @@ static char rcsid[] = "$NetBSD: s_asinh.c,v 1.9 1995/05/12 04:57:37 jtc Exp $";
* := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
huge= 1.00000000000000000000e+300; huge= 1.00000000000000000000e+300;
#ifdef __STDC__
double asinh(double x) double asinh(double x)
#else
double asinh(x)
double x;
#endif
{ {
double t,w; double t,w;
int32_t hx,ix; int32_t hx,ix;

View file

@ -10,10 +10,6 @@
* ==================================================== * ====================================================
*/ */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_atan.c,v 1.8 1995/05/10 20:46:45 jtc Exp $";
#endif
/* atan(x) /* atan(x)
* Method * Method
* 1. Reduce x to positive by atan(x) = -atan(-x). * 1. Reduce x to positive by atan(x) = -atan(-x).
@ -34,36 +30,23 @@ static char rcsid[] = "$NetBSD: s_atan.c,v 1.8 1995/05/10 20:46:45 jtc Exp $";
* to produce the hexadecimal values shown. * to produce the hexadecimal values shown.
*/ */
#include "math.h"
#include "mathP.h" #include "mathP.h"
#ifdef __STDC__
static const double atanhi[] = { static const double atanhi[] = {
#else
static double atanhi[] = {
#endif
4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
}; };
#ifdef __STDC__
static const double atanlo[] = { static const double atanlo[] = {
#else
static double atanlo[] = {
#endif
2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
}; };
#ifdef __STDC__
static const double aT[] = { static const double aT[] = {
#else
static double aT[] = {
#endif
3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
-1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
@ -77,20 +60,11 @@ static double aT[] = {
1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
}; };
#ifdef __STDC__
static const double static const double
#else
static double
#endif
one = 1.0, one = 1.0,
huge = 1.0e300; huge = 1.0e300;
#ifdef __STDC__
double atan(double x) double atan(double x)
#else
double atan(x)
double x;
#endif
{ {
double w,s1,s2,z; double w,s1,s2,z;
int32_t ix,hx,id; int32_t ix,hx,id;

Some files were not shown because too many files have changed in this diff Show more