Compare commits
38 commits
master
...
libm-no-us
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f29a48653 | ||
|
|
ce81999e66 | ||
|
|
fa71c0c76d | ||
|
|
a29b0bee30 | ||
|
|
3b1a9dd0f2 | ||
|
|
08618bbf48 | ||
|
|
c0282fe4ea | ||
|
|
47a1f7f74b | ||
|
|
2f749c34ce | ||
|
|
d4cf50bee7 | ||
|
|
2df23cc0de | ||
|
|
037c704ccc | ||
|
|
783893c929 | ||
|
|
2fb9c58762 | ||
|
|
3086517cd2 | ||
|
|
d897f9c2d7 | ||
|
|
9839efa96b | ||
|
|
edb6c1a7ce | ||
|
|
ea85023591 | ||
|
|
b39e77aaf7 | ||
|
|
de529b0c0d | ||
|
|
26da62c969 | ||
|
|
5c10841066 | ||
|
|
b01be3d331 | ||
|
|
e2bb11fcf5 | ||
|
|
c98c84fe9b | ||
|
|
d2deb6292b | ||
|
|
550aeaed4b | ||
|
|
96857bcbae | ||
|
|
7960e1643b | ||
|
|
3e171e8003 | ||
|
|
0adf90be69 | ||
|
|
3e16737bf2 | ||
|
|
42ab605bfa | ||
|
|
24815b03e9 | ||
|
|
659fd69c1b | ||
|
|
fbb1f385cd | ||
|
|
04c0b06102 |
232 changed files with 11304 additions and 29457 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -25,6 +25,7 @@ configure
|
|||
aclocal.m4
|
||||
ltversion.m4
|
||||
bin/
|
||||
m4/*
|
||||
doc/guide/*.html
|
||||
addons/drivers/16550A/FORCE
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,6 @@
|
|||
OPTDIRS =
|
||||
SUBDIRS = base
|
||||
|
||||
OPTDIRS += addons
|
||||
|
||||
SUBDIRS = base $(OPTDIRS)
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
base \
|
||||
addons
|
||||
DIST_SUBDIRS = base
|
||||
|
||||
EXTRA_DIST = \
|
||||
README.INSTALL \
|
||||
|
|
@ -76,7 +70,8 @@ clean-local:
|
|||
distclean-local:
|
||||
$(MAKE) -C $(srcdir)/base/config/kconfig \
|
||||
-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
|
||||
clean-local:
|
||||
rm -f .cfchanged
|
||||
|
|
@ -98,9 +93,7 @@ install-exec-local: devices
|
|||
|
||||
dist-hook:
|
||||
$(MAKE) -C $(distdir)/base/config/kconfig \
|
||||
-f Makefile.kconfig distclean srctree=$(distdir)
|
||||
rm -fr `find $(distdir) -name CVS`
|
||||
test -e $(srcdir)/doc || rm -fr $(distdir)/doc
|
||||
-f Makefile.kconfig distclean srctree=$(srcdir)
|
||||
|
||||
dev devices:
|
||||
@if test -r $(DESTDIR)/etc/udev/udev.rules ; then \
|
||||
|
|
|
|||
344
README.INSTALL
344
README.INSTALL
|
|
@ -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
|
||||
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.
|
||||
1.) Download the RTAI source
|
||||
|
||||
On recent distributions, managing udev/sysfs, devices created by following
|
||||
this installation procedure will disappear at each machine halting. Then they
|
||||
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.
|
||||
$ cd ~/ && git clone https://github.com/NTULINUX/RTAI.git
|
||||
$ sudo cp -v base/arch/x86/patches/hal-linux-3.14.17-x86-1.patch /usr/src/
|
||||
|
||||
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
|
||||
autoconf/automake/libtool. Therefore, you can either build RTAI:
|
||||
Configure to your needs
|
||||
|
||||
1.1.1 Interactive configuration
|
||||
-------------------------------
|
||||
# make
|
||||
# make modules_install
|
||||
|
||||
1) Into the source tree like with 24.1.x (your_source_dir ==
|
||||
your_build_dir). Just run either:
|
||||
3.) Update grub
|
||||
|
||||
$ make xconfig # (Qt-based)
|
||||
$ make gconfig # (GTK-based)
|
||||
$ make menuconfig (dialog-based as in 24.1.x)
|
||||
Refer to your distribution documentation to do this
|
||||
|
||||
Save your configuration, wait for the shell prompt to come back after
|
||||
the configuration script has fully finished, then run "make".
|
||||
4.) Compile, configure and install RTAI (MUST BE BOOTED INTO YOUR NEW KERNEL)
|
||||
|
||||
2) Outside the source tree. From your fresh build directory,
|
||||
either run:
|
||||
$ cd ~/RTAI
|
||||
$ ./autogen.sh
|
||||
$ make menuconfig
|
||||
|
||||
$ make -f $source_tree/makefile srctree=$source_tree xconfig
|
||||
$ make -f $source_tree/makefile srctree=$source_tree gconfig
|
||||
$ make -f $source_tree/makefile srctree=$source_tree menuconfig
|
||||
Configure to your needs
|
||||
|
||||
If you are using a version of make >= 3.80, then you can even get rid
|
||||
of the "srctree=$source_tree" setting. The makefile will infere its
|
||||
value properly.
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
1.1.2 Non-interactive configuration
|
||||
-----------------------------------
|
||||
|
||||
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
|
||||
5.) Go get LinuxCNC and compile that.
|
||||
|
|
|
|||
|
|
@ -1 +1,7 @@
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
OPTDIRS =
|
||||
|
||||
OPTDIRS += rtdm
|
||||
|
||||
SUBDIRS = $(OPTDIRS)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
||||
1527
addons/rtdm/core.c
1527
addons/rtdm/core.c
File diff suppressed because it is too large
Load diff
|
|
@ -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(®_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(®_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);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -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 */
|
||||
2372
addons/rtdm/drvlib.c
2372
addons/rtdm/drvlib.c
File diff suppressed because it is too large
Load diff
|
|
@ -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 */
|
||||
|
|
@ -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)/../..
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
|
@ -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 */
|
||||
|
|
@ -34,29 +34,15 @@ endmenu
|
|||
|
||||
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
|
||||
string "Number of CPUs (SMP-only)"
|
||||
default 2
|
||||
default 4
|
||||
help
|
||||
RTAI has native support for Symmetrical Multi-Processing
|
||||
machines. If it is your case, you may want to enter here the
|
||||
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
|
||||
bool "Diagnose out of sync MP-TSCs"
|
||||
|
|
@ -207,7 +193,7 @@ config RTAI_USER_BUSY_ALIGN_RET_DELAY
|
|||
|
||||
config RTAI_SCHED_LXRT_NUMSLOTS
|
||||
string "Number of registrable RTAI objects"
|
||||
default 256
|
||||
default 1024
|
||||
help
|
||||
The maximum number of registrable objects in RTAI.
|
||||
|
||||
|
|
@ -264,7 +250,7 @@ config RTAI_FULL_PRINHER
|
|||
|
||||
config RTAI_ALIGN_LINUX_PRIORITY
|
||||
bool "Keep Linux task priority aligned to RTAI"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
|
||||
By enabling this option the RTAI scheduler will keep Linux tasks
|
||||
|
|
@ -275,7 +261,7 @@ config RTAI_ALIGN_LINUX_PRIORITY
|
|||
|
||||
config RTAI_ONE_SHOT
|
||||
bool "One-shot timer mode"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
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
|
||||
|
|
@ -313,22 +299,6 @@ endmenu
|
|||
|
||||
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
|
||||
tristate "Fifo"
|
||||
default m
|
||||
|
|
@ -463,28 +433,6 @@ config RTAI_MBX
|
|||
Mailboxes depend on semaphores.
|
||||
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
|
||||
tristate "Tasklets"
|
||||
default m
|
||||
|
|
@ -577,20 +525,6 @@ config RTAI_USE_NEWERR
|
|||
to choose what to do, without forcing any adaption for already
|
||||
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
|
||||
tristate "Real-time malloc support"
|
||||
default y
|
||||
|
|
@ -687,47 +621,3 @@ config RTAI_HARD_SOFT_TOGGLER
|
|||
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
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ moduledir = @RTAI_MODULE_DIR@
|
|||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
|
||||
|
||||
libcalibrate_rt_a_SOURCES = calibrate-module.c calibrate.h
|
||||
libsmi_rt_a_SOURCES = smi-module.c
|
||||
|
||||
|
|
@ -57,7 +55,7 @@ calibration_PROGRAMS += calibration_helper
|
|||
calibrate_SOURCES = calibrate.c calibrate.h
|
||||
|
||||
calibrate_CPPFLAGS = \
|
||||
@RTAI_REAL_USER_CFLAGS@ \
|
||||
@RTAI_USER_CFLAGS@ \
|
||||
-DKERNEL_HELPER_PATH="\"$(calibrationdir)/rtai_calibrate$(modext)\"" \
|
||||
-DUSER_HELPER_PATH="\"$(calibrationdir)/calibration_helper\"" \
|
||||
-I$(top_srcdir)/base/include \
|
||||
|
|
@ -66,7 +64,7 @@ calibrate_CPPFLAGS = \
|
|||
calibration_helper_SOURCES = calibration_helper.c
|
||||
|
||||
calibration_helper_CPPFLAGS = \
|
||||
@RTAI_REAL_USER_CFLAGS@ \
|
||||
@RTAI_USER_CFLAGS@ \
|
||||
-DHAL_SCHED_PATH="\"$(DESTDIR)$(moduledir)\"" \
|
||||
-DHAL_SCHED_MODEXT="\"$(modext)\"" \
|
||||
-I$(top_srcdir)/base/include \
|
||||
|
|
|
|||
3348
base/arch/x86/configs/rtai_32_defconfig
Normal file
3348
base/arch/x86/configs/rtai_32_defconfig
Normal file
File diff suppressed because it is too large
Load diff
3297
base/arch/x86/configs/rtai_64_defconfig
Normal file
3297
base/arch/x86/configs/rtai_64_defconfig
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,6 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# RTAI/x86 configuration
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_RTAI_VERSION="4.0 (vulcano)"
|
||||
|
|
@ -11,22 +12,9 @@ CONFIG_RTAI_INSTALLDIR="/usr/realtime"
|
|||
CONFIG_RTAI_LINUXDIR="/usr/src/linux"
|
||||
|
||||
#
|
||||
# RTAI Documentation
|
||||
# Machine (x86 / x86_64)
|
||||
#
|
||||
# CONFIG_RTAI_DOX_DOC is not set
|
||||
# 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_CPUS="4"
|
||||
# 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_APIC_LATENCY="3944"
|
||||
# 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_ALLOW_RR=y
|
||||
# CONFIG_RTAI_FULL_PRINHER is not set
|
||||
# CONFIG_RTAI_ALIGN_LINUX_PRIORITY is not set
|
||||
# CONFIG_RTAI_ONE_SHOT is not set
|
||||
CONFIG_RTAI_ALIGN_LINUX_PRIORITY=y
|
||||
CONFIG_RTAI_ONE_SHOT=y
|
||||
CONFIG_RTAI_CAL_FREQS_FACT="0"
|
||||
|
||||
#
|
||||
# Supported services
|
||||
#
|
||||
CONFIG_RTAI_BITS=m
|
||||
CONFIG_RTAI_FIFOS=m
|
||||
CONFIG_RTAI_NETRPC=m
|
||||
# CONFIG_RTAI_NETRPC_RTNET is not set
|
||||
CONFIG_RTAI_SHM=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_MBX=m
|
||||
CONFIG_RTAI_TBX=m
|
||||
CONFIG_RTAI_TASKLETS=m
|
||||
CONFIG_RTAI_MQ=m
|
||||
CONFIG_RTAI_CLOCK_REALTIME=y
|
||||
|
|
@ -69,33 +56,11 @@ CONFIG_RTAI_CLOCK_REALTIME=y
|
|||
#
|
||||
# Other features
|
||||
#
|
||||
# CONFIG_RTAI_USE_NEWERR is not set
|
||||
# CONFIG_RTAI_MATH is not set
|
||||
CONFIG_RTAI_USE_NEWERR=y
|
||||
CONFIG_RTAI_MALLOC=y
|
||||
# CONFIG_RTAI_USE_TLSF is not set
|
||||
CONFIG_RTAI_MALLOC_VMALLOC=y
|
||||
CONFIG_RTAI_MALLOC_HEAPSZ="2048"
|
||||
CONFIG_RTAI_KSTACK_HEAPSZ="512"
|
||||
# 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
|
||||
|
||||
#
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -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_critical_exit(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -956,8 +956,8 @@ void rt_free_apic_timers(void)
|
|||
rtai_release_tickdev();
|
||||
rtai_sync_level = 3;
|
||||
rtai_setup_periodic_apic(RTAI_APIC_ICOUNT,LOCAL_TIMER_VECTOR);
|
||||
rtai_critical_exit(flags);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (rtai_cpufreq_arg == 0) {
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static void rtai_release_tickdev(void);
|
|||
static inline void rtai_setup_periodic_apic (unsigned count, unsigned vector)
|
||||
{
|
||||
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_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)
|
||||
{
|
||||
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_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_critical_exit(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -942,8 +942,8 @@ void rt_free_apic_timers(void)
|
|||
rtai_release_tickdev();
|
||||
rtai_sync_level = 3;
|
||||
rtai_setup_periodic_apic(RTAI_APIC_ICOUNT,LOCAL_TIMER_VECTOR);
|
||||
rtai_critical_exit(flags);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
if (rtai_cpufreq_arg == 0) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5250,6 +5250,67 @@ index f04e25f..5fa6be6 100644
|
|||
select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE)
|
||||
select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE)
|
||||
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
|
||||
index 6e373ea..f32da7b 100644
|
||||
--- a/drivers/pci/htirq.c
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ ARCHDIR = asm-x86
|
|||
nobase_include_HEADERS = \
|
||||
rtai.h \
|
||||
rtai_hal_names.h \
|
||||
rtai_bits.h \
|
||||
rtai_fifos.h \
|
||||
rtai_lxrt.h \
|
||||
rtai_malloc.h \
|
||||
|
|
@ -30,7 +29,6 @@ nobase_include_HEADERS = \
|
|||
rtai_signal.h \
|
||||
rtai_spl.h \
|
||||
rtai_tasklets.h \
|
||||
rtai_tbx.h \
|
||||
rtai_trace.h \
|
||||
rtai_types.h \
|
||||
rtai_version.h \
|
||||
|
|
@ -41,7 +39,7 @@ install-data-local:
|
|||
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
distclean-local:
|
||||
rm -f $(DESTDIR)$(includedir)/asm $(DESTDIR)$(includedir)/rtai_config.h
|
||||
rm -f $(srcdir)$(includedir)/asm $(srcdir)$(includedir)/rtai_config.h
|
||||
endif
|
||||
|
||||
SUBDIRS = $(ARCHDIR)
|
||||
|
|
|
|||
|
|
@ -32,20 +32,10 @@
|
|||
#include <asm/processor.h>
|
||||
#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;
|
||||
#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 { \
|
||||
__asm__ __volatile__ ("clts"); \
|
||||
|
|
@ -62,7 +52,7 @@ typedef union thread_xstate FPU_ENV;
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
// initialise the hard fpu unit directly
|
||||
/* initialise the hard fpu unit directly */
|
||||
#define init_hard_fpenv() do { \
|
||||
__asm__ __volatile__ ("clts; fninit"); \
|
||||
if (cpu_has_xmm) { \
|
||||
|
|
@ -71,7 +61,7 @@ typedef union thread_xstate FPU_ENV;
|
|||
} \
|
||||
} 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 { \
|
||||
if (cpu_has_fxsr) { \
|
||||
memset(&(fpenv)->fxsave, 0, sizeof(struct i387_fxsave_struct));\
|
||||
|
|
@ -104,14 +94,14 @@ typedef union thread_xstate FPU_ENV;
|
|||
} \
|
||||
} 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 save_fpenv(fpenv) do { __save_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 { \
|
||||
init_hard_fpenv(); \
|
||||
set_lnxtsk_uses_fpu(lnxtsk); \
|
||||
|
|
@ -129,73 +119,18 @@ typedef union thread_xstate FPU_ENV;
|
|||
set_lnxtsk_using_fpu(lnxtsk); \
|
||||
} 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) \
|
||||
do { set_stopped_child_used_math(lnxtsk); } while(0)
|
||||
#define clear_lnxtsk_uses_fpu(lnxtsk) \
|
||||
do { clear_stopped_child_used_math(lnxtsk); } while(0)
|
||||
#define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk))
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
|
||||
#undef init_fpu
|
||||
#include <asm/i387.h>
|
||||
#include <asm/fpu-internal.h>
|
||||
#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) \
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -34,20 +34,10 @@
|
|||
#include <asm/processor.h>
|
||||
#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;
|
||||
#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 { \
|
||||
__asm__ __volatile__ ("clts"); \
|
||||
|
|
@ -68,7 +58,7 @@ typedef union thread_xstate FPU_ENV;
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
// initialise the hard fpu unit directly
|
||||
/* initialise the hard fpu unit directly */
|
||||
#define init_hard_fpenv() do { \
|
||||
unsigned long __mxcsr; \
|
||||
__asm__ __volatile__ ("clts; fninit"); \
|
||||
|
|
@ -76,7 +66,7 @@ typedef union thread_xstate FPU_ENV;
|
|||
__asm__ __volatile__ ("ldmxcsr %0": : "m" (__mxcsr)); \
|
||||
} 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 { \
|
||||
memset(fpenv, 0, sizeof(struct i387_fxsave_struct)); \
|
||||
(fpenv)->cwd = 0x37f; \
|
||||
|
|
@ -84,7 +74,6 @@ typedef union thread_xstate FPU_ENV;
|
|||
} while (0)
|
||||
|
||||
/* taken from Linux i387.h */
|
||||
|
||||
static inline int __save_fpenv(struct i387_fxsave_struct __user *fx)
|
||||
{
|
||||
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 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 { \
|
||||
init_hard_fpenv(); \
|
||||
|
|
@ -148,58 +137,18 @@ static inline int __restore_fpenv(struct i387_fxsave_struct *fx)
|
|||
set_lnxtsk_using_fpu(lnxtsk); \
|
||||
} 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) \
|
||||
do { set_stopped_child_used_math(lnxtsk); } while(0)
|
||||
#define clear_lnxtsk_uses_fpu(lnxtsk) \
|
||||
do { clear_stopped_child_used_math(lnxtsk); } while(0)
|
||||
#define lnxtsk_uses_fpu(lnxtsk) (tsk_used_math(lnxtsk))
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)
|
||||
#undef init_fpu
|
||||
#include <asm/i387.h>
|
||||
#include <asm/fpu-internal.h>
|
||||
#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) \
|
||||
do { rtai_set_fpu_used(lnxtsk); } while(0) //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,11) */
|
||||
|
||||
do { rtai_set_fpu_used(lnxtsk); } while(0)
|
||||
|
||||
#endif /* !_RTAI_ASM_X86_64_FPU_H */
|
||||
|
|
|
|||
|
|
@ -120,7 +120,9 @@ extern "C" {
|
|||
static inline void _lxrt_context_switch (struct task_struct *prev, struct task_struct *next, int cpuid)
|
||||
{
|
||||
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;
|
||||
#endif
|
||||
context_switch(0, prev, next);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -231,28 +231,6 @@
|
|||
#define BITS_WAIT_UNTIL 142
|
||||
#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
|
||||
#define MQ_OPEN 164
|
||||
#define MQ_RECEIVE 165
|
||||
|
|
|
|||
|
|
@ -34,121 +34,69 @@
|
|||
#ifdef __attribute_used__
|
||||
#undef __attribute_used__
|
||||
#endif
|
||||
#include <features.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* 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>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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'. */
|
||||
extern int signgam;
|
||||
#endif
|
||||
|
||||
|
||||
/* ISO C99 defines some generic macros which work on any data type. */
|
||||
#if defined(__USE_ISOC99) && __USE_ISOC99
|
||||
|
||||
/* Get the architecture specific values describing the floating-point
|
||||
|
|
@ -239,16 +187,16 @@ enum
|
|||
# define isnormal(x) (fpclassify (x) == FP_NORMAL)
|
||||
|
||||
/* 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
|
||||
# define isnan(x) \
|
||||
(sizeof (x) == sizeof (float) ? __isnanf (x) : __isnan (x))
|
||||
(sizeof (x) == sizeof (float) ? __builtin_isnanf (x) : __builtin_isnan (x))
|
||||
# else
|
||||
# define isnan(x) \
|
||||
(sizeof (x) == sizeof (float) \
|
||||
? __isnanf (x) \
|
||||
? __builtin_isnanf (x) \
|
||||
: sizeof (x) == sizeof (double) \
|
||||
? __isnan (x) : __isnanl (x))
|
||||
? __builtin_isnan (x) : __builtin_isnanl (x))
|
||||
# endif
|
||||
|
||||
/* Return nonzero value is X is positive or negative infinity. */
|
||||
|
|
@ -442,21 +390,16 @@ extern int matherr (struct exception *__exc);
|
|||
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
/* Missing declarations */
|
||||
|
||||
struct complex {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
double cabs __P((struct complex));
|
||||
|
||||
double gamma_r(double x, int *signgamp); /* wrapper lgamma_r */
|
||||
|
||||
long int rinttol(double x);
|
||||
|
||||
long int roundtol(double x);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_RTAI_MATH_H */
|
||||
|
|
|
|||
|
|
@ -49,9 +49,7 @@ struct rt_registry_entry {
|
|||
#define IS_SPL 3
|
||||
#define IS_MBX 4
|
||||
#define IS_PRX 5
|
||||
#define IS_BIT 6
|
||||
#define IS_TBX 7
|
||||
#define IS_HPCK 8
|
||||
#define IS_HPCK 6
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
|
|
|||
|
|
@ -47,9 +47,7 @@
|
|||
#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_tasklets.h>
|
||||
#include <rtai_fifos.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)
|
||||
|
||||
{
|
||||
#ifdef CONFIG_RTAI_LEDS_BUILTIN
|
||||
__rtai_leds_init();
|
||||
#endif /* CONFIG_RTAI_LEDS_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_SEM_BUILTIN
|
||||
__rtai_sem_init();
|
||||
#endif /* CONFIG_RTAI_SEM_BUILTIN */
|
||||
|
|
@ -555,15 +550,9 @@ static inline int rtai_init_features (void)
|
|||
#ifdef CONFIG_RTAI_MBX_BUILTIN
|
||||
__rtai_mbx_init();
|
||||
#endif /* CONFIG_RTAI_MBX_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_TBX_BUILTIN
|
||||
__rtai_msg_queue_init();
|
||||
#endif /* CONFIG_RTAI_TBX_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_MQ_BUILTIN
|
||||
__rtai_mq_init();
|
||||
#endif /* CONFIG_RTAI_MQ_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_BITS_BUILTIN
|
||||
__rtai_bits_init();
|
||||
#endif /* CONFIG_RTAI_BITS_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_TASKLETS_BUILTIN
|
||||
__rtai_tasklets_init();
|
||||
#endif /* CONFIG_RTAI_TASKLETS_BUILTIN */
|
||||
|
|
@ -579,9 +568,6 @@ static inline int rtai_init_features (void)
|
|||
#ifdef CONFIG_RTAI_MATH_BUILTIN
|
||||
__rtai_math_init();
|
||||
#endif /* CONFIG_RTAI_MATH_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_USI
|
||||
printk(KERN_INFO "RTAI[usi]: enabled.\n");
|
||||
#endif /* CONFIG_RTAI_USI */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -603,15 +589,9 @@ static inline void rtai_cleanup_features (void) {
|
|||
#ifdef CONFIG_RTAI_TASKLETS_BUILTIN
|
||||
__rtai_tasklets_exit();
|
||||
#endif /* CONFIG_RTAI_TASKLETS_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_BITS_BUILTIN
|
||||
__rtai_bits_exit();
|
||||
#endif /* CONFIG_RTAI_BITS_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_MQ_BUILTIN
|
||||
__rtai_mq_exit();
|
||||
#endif /* CONFIG_RTAI_MQ_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_TBX_BUILTIN
|
||||
__rtai_msg_queue_exit();
|
||||
#endif /* CONFIG_RTAI_TBX_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_MBX_BUILTIN
|
||||
__rtai_mbx_exit();
|
||||
#endif /* CONFIG_RTAI_MBX_BUILTIN */
|
||||
|
|
@ -621,9 +601,6 @@ static inline void rtai_cleanup_features (void) {
|
|||
#ifdef CONFIG_RTAI_SEM_BUILTIN
|
||||
__rtai_sem_exit();
|
||||
#endif /* CONFIG_RTAI_SEM_BUILTIN */
|
||||
#ifdef CONFIG_RTAI_LEDS_BUILTIN
|
||||
__rtai_leds_exit();
|
||||
#endif /* CONFIG_RTAI_LEDS_BUILTIN */
|
||||
}
|
||||
|
||||
int rt_check_current_stack(void);
|
||||
|
|
@ -647,30 +624,6 @@ int rt_kthread_init_cpuid(RT_TASK *task,
|
|||
|
||||
#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 /* !_RTAI_SCHEDCORE_H */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -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)
|
||||
{
|
||||
#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;
|
||||
#endif
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
#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;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -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;
|
||||
#define DECLARE_XNSELECT(name)
|
||||
#define xnselect_init(block)
|
||||
|
|
@ -162,7 +91,6 @@ struct xnselector;
|
|||
({ -EBADF; })
|
||||
#define xnselect_signal(block, state) ({ int __ret = 0; __ret; })
|
||||
#define xnselect_destroy(block)
|
||||
#endif /* !CONFIG_RTAI_RTDM_SELECT */
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
|
@ -30,12 +30,6 @@
|
|||
|
||||
#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_ASSERT(subsystem, cond, action) do { \
|
||||
|
|
@ -370,9 +364,6 @@ typedef struct xnstat_counter {
|
|||
#define xnstat_counter_inc(c) ((c)->counter++)
|
||||
|
||||
typedef struct xnintr {
|
||||
#ifdef CONFIG_RTAI_RTDM_SHIRQ
|
||||
struct xnintr *next;
|
||||
#endif /* CONFIG_RTAI_RTDM_SHIRQ */
|
||||
unsigned unhandled;
|
||||
xnisr_t isr;
|
||||
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) \
|
||||
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)
|
||||
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
|
||||
|
||||
#define __WORK_INITIALIZER(n,f,d) { \
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
OPTDIRS=
|
||||
|
||||
if CONFIG_RTAI_BITS
|
||||
OPTDIRS += bits
|
||||
endif
|
||||
OPTDIRS =
|
||||
|
||||
if CONFIG_RTAI_FIFOS
|
||||
OPTDIRS += fifos
|
||||
|
|
@ -24,10 +20,6 @@ if CONFIG_RTAI_MBX
|
|||
OPTDIRS += mbx
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_TBX
|
||||
OPTDIRS += tbx
|
||||
endif
|
||||
|
||||
if CONFIG_RTAI_MQ
|
||||
OPTDIRS += mq
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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
|
||||
schedulers.
|
||||
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,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ moduledir = @RTAI_MODULE_DIR@
|
|||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
|
||||
|
||||
libnetrpc_a_SOURCES = netrpc.c rtnetP.h
|
||||
|
||||
if CONFIG_KBUILD
|
||||
|
|
@ -27,7 +25,6 @@ libnetrpc_a_AR = ar cru
|
|||
AM_CPPFLAGS = \
|
||||
@RTAI_KMOD_CFLAGS@ \
|
||||
-I$(top_srcdir)/base/include \
|
||||
-I$(top_srcdir)/addons/rtdm \
|
||||
-I$(srcdir)/rtnet \
|
||||
-I../../include
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 */
|
||||
|
|
@ -2,36 +2,21 @@ moduledir = @RTAI_MODULE_DIR@
|
|||
|
||||
modext = @RTAI_MODULE_EXT@
|
||||
|
||||
|
||||
|
||||
if CONFIG_RTAI_MATH_C99
|
||||
|
||||
libmath_a_SOURCES = \
|
||||
ceilfloor.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_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.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_scalb.c e_sinh.c e_sqrt.c fpmacros.c frexpldexp.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 \
|
||||
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 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_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_tan.c s_tanh.c scalb.c sign.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 \
|
||||
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_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_remainder.c w_scalb.c w_sinh.c w_sqrt.c libm.c
|
||||
|
||||
else
|
||||
|
||||
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
|
||||
libmath_a_SOURCES += mathP.h
|
||||
|
||||
if CONFIG_KBUILD
|
||||
rtai_math.ko: @RTAI_KBUILD_ENV@
|
||||
|
|
@ -59,7 +44,6 @@ rtai_math.o: libmath.a
|
|||
endif
|
||||
|
||||
all-local: rtai_math$(modext)
|
||||
if !CONFIG_RTAI_MATH_BUILTIN
|
||||
if CONFIG_RTAI_OLD_FASHIONED_BUILD
|
||||
$(mkinstalldirs) $(top_srcdir)/modules
|
||||
$(INSTALL_DATA) $^ $(top_srcdir)/modules
|
||||
|
|
@ -68,6 +52,5 @@ endif
|
|||
install-exec-local: rtai_math$(modext)
|
||||
$(mkinstalldirs) $(DESTDIR)$(moduledir)
|
||||
$(INSTALL_DATA) $< $(DESTDIR)$(moduledir)
|
||||
endif
|
||||
|
||||
EXTRA_DIST = Makefile.kbuild
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
EXTRA_CFLAGS += -I$(rtai_srctree)/base/include \
|
||||
-I$(src)/../include \
|
||||
-I$(src)/../.. \
|
||||
-I/usr/include \
|
||||
-isystem $(shell $(CC) -print-file-name=include-fixed) \
|
||||
$(rtai_extradef) \
|
||||
-D_IEEE_LIBM \
|
||||
-D_ISOC99_SOURCE \
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
|
||||
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
|
||||
|
|
@ -61,12 +52,7 @@ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
|
|||
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
|
||||
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_acos(double x)
|
||||
#else
|
||||
double __ieee754_acos(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double z,p,q,r,w,s,c,df;
|
||||
int32_t hx,ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.0,
|
||||
ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_acosh(double x)
|
||||
#else
|
||||
double __ieee754_acosh(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double t;
|
||||
int32_t hx;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
huge = 1.000e+300,
|
||||
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
|
||||
|
|
@ -70,12 +60,7 @@ qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
|
|||
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
|
||||
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_asin(double x)
|
||||
#else
|
||||
double __ieee754_asin(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double t,w,p,q,c,r,s;
|
||||
int32_t hx,ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
tiny = 1.0e-300,
|
||||
zero = 0.0,
|
||||
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_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_atan2(double y, double x)
|
||||
#else
|
||||
double __ieee754_atan2(y,x)
|
||||
double y,x;
|
||||
#endif
|
||||
{
|
||||
double z;
|
||||
int32_t k,m,hx,hy,ix,iy;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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"
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
#else
|
||||
static double zero = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_atanh(double x)
|
||||
#else
|
||||
double __ieee754_atanh(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double t;
|
||||
int32_t hx,ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
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)
|
||||
#else
|
||||
double __ieee754_cosh(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double t,w;
|
||||
int32_t ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.0,
|
||||
halF[2] = {0.5,-0.5,},
|
||||
huge = 1.0e+300,
|
||||
|
|
@ -103,12 +94,7 @@ P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
|
|||
P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
int32_t k,xsb;
|
||||
|
|
|
|||
11
base/math/e_fmax.c
Normal file
11
base/math/e_fmax.c
Normal 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
11
base/math/e_fmin.c
Normal 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;
|
||||
}
|
||||
|
|
@ -9,32 +9,17 @@
|
|||
* 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)
|
||||
* Return x mod y in exact arithmetic
|
||||
* Method: shift and subtract
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
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)
|
||||
#else
|
||||
double __ieee754_fmod(x,y)
|
||||
double x,y ;
|
||||
#endif
|
||||
{
|
||||
int32_t n,hx,hy,hz,ix,iy,sx,i;
|
||||
u_int32_t lx,ly,lz;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* @(#)e_gamma.c 5.1 93/09/24 */
|
||||
/*
|
||||
* ====================================================
|
||||
|
|
@ -22,13 +21,7 @@
|
|||
|
||||
extern int signgam;
|
||||
|
||||
#ifdef __STDC__
|
||||
//__private_extern__
|
||||
double __ieee754_gamma(double x)
|
||||
#else
|
||||
double __ieee754_gamma(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
return __ieee754_gamma_r(x,&signgam);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,13 +21,7 @@
|
|||
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
//__private_extern__
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
int32_t j,k,ha,hb;
|
||||
|
|
|
|||
121
base/math/e_j0.c
121
base/math/e_j0.c
|
|
@ -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)
|
||||
* Bessel function of the first and second kinds of order zero.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static double pzero(double), qzero(double);
|
||||
#else
|
||||
static double pzero(), qzero();
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
huge = 1e300,
|
||||
one = 1.0,
|
||||
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
|
||||
|
|
@ -87,18 +74,9 @@ S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */
|
|||
S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
|
||||
S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero = 0.0;
|
||||
#else
|
||||
static double zero = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_j0(double x)
|
||||
#else
|
||||
double __ieee754_j0(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double z, s,c,ss,cc,r,u,v;
|
||||
int32_t hx,ix;
|
||||
|
|
@ -145,11 +123,7 @@ static double zero = 0.0;
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */
|
||||
u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */
|
||||
u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */
|
||||
|
|
@ -162,12 +136,7 @@ v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
|
|||
v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
|
||||
v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_y0(double x)
|
||||
#else
|
||||
double __ieee754_y0(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double z, s,c,ss,cc,u,v;
|
||||
int32_t hx,ix,lx;
|
||||
|
|
@ -228,11 +197,7 @@ v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */
|
|||
* and
|
||||
* | pzero(x)-1-R/S | <= 2 ** ( -60.26)
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
-7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */
|
||||
-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 */
|
||||
-5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double pS8[5] = {
|
||||
#else
|
||||
static double pS8[5] = {
|
||||
#endif
|
||||
1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */
|
||||
3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */
|
||||
4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */
|
||||
|
|
@ -252,11 +214,7 @@ static double pS8[5] = {
|
|||
4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
-7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */
|
||||
-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.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double pS5[5] = {
|
||||
#else
|
||||
static double pS5[5] = {
|
||||
#endif
|
||||
6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */
|
||||
1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */
|
||||
5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */
|
||||
|
|
@ -276,11 +231,7 @@ static double pS5[5] = {
|
|||
2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
-7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */
|
||||
-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 */
|
||||
-3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double pS3[5] = {
|
||||
#else
|
||||
static double pS3[5] = {
|
||||
#endif
|
||||
3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */
|
||||
3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */
|
||||
1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */
|
||||
|
|
@ -300,11 +248,7 @@ static double pS3[5] = {
|
|||
1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
-7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */
|
||||
-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 */
|
||||
-3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double pS2[5] = {
|
||||
#else
|
||||
static double pS2[5] = {
|
||||
#endif
|
||||
2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */
|
||||
1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */
|
||||
2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */
|
||||
|
|
@ -324,18 +265,9 @@ static double pS2[5] = {
|
|||
1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static double pzero(double x)
|
||||
#else
|
||||
static double pzero(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
#ifdef __STDC__
|
||||
const double *p = 0,*q = 0;
|
||||
#else
|
||||
double *p = 0,*q = 0;
|
||||
#endif
|
||||
double z,r,s;
|
||||
int32_t ix;
|
||||
GET_HIGH_WORD(ix,x);
|
||||
|
|
@ -360,11 +292,7 @@ static double pS2[5] = {
|
|||
* and
|
||||
* | 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] */
|
||||
#else
|
||||
static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
|
||||
#endif
|
||||
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
|
||||
7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */
|
||||
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 */
|
||||
3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qS8[6] = {
|
||||
#else
|
||||
static double qS8[6] = {
|
||||
#endif
|
||||
1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */
|
||||
8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */
|
||||
1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */
|
||||
|
|
@ -385,11 +310,7 @@ static double qS8[6] = {
|
|||
-3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */
|
||||
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.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qS5[6] = {
|
||||
#else
|
||||
static double qS5[6] = {
|
||||
#endif
|
||||
8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */
|
||||
2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */
|
||||
1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */
|
||||
|
|
@ -410,11 +328,7 @@ static double qS5[6] = {
|
|||
-5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */
|
||||
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.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qS3[6] = {
|
||||
#else
|
||||
static double qS3[6] = {
|
||||
#endif
|
||||
4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */
|
||||
7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */
|
||||
3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */
|
||||
|
|
@ -435,11 +346,7 @@ static double qS3[6] = {
|
|||
-1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */
|
||||
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 */
|
||||
1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qS2[6] = {
|
||||
#else
|
||||
static double qS2[6] = {
|
||||
#endif
|
||||
3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */
|
||||
2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */
|
||||
8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */
|
||||
|
|
@ -460,18 +364,9 @@ static double qS2[6] = {
|
|||
-5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static double qzero(double x)
|
||||
#else
|
||||
static double qzero(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
#ifdef __STDC__
|
||||
const double *p = 0,*q = 0;
|
||||
#else
|
||||
double *p = 0,*q = 0;
|
||||
#endif
|
||||
double s,r,z;
|
||||
int32_t ix;
|
||||
GET_HIGH_WORD(ix,x);
|
||||
|
|
|
|||
126
base/math/e_j1.c
126
base/math/e_j1.c
|
|
@ -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)
|
||||
* Bessel function of the first and second kinds of order zero.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static double pone(double), qone(double);
|
||||
#else
|
||||
static double pone(), qone();
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
huge = 1e300,
|
||||
one = 1.0,
|
||||
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
|
||||
|
|
@ -88,18 +75,9 @@ s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */
|
|||
s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */
|
||||
s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero = 0.0;
|
||||
#else
|
||||
static double zero = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_j1(double x)
|
||||
#else
|
||||
double __ieee754_j1(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double z, s,c,ss,cc,r,u,v,y;
|
||||
int32_t hx,ix;
|
||||
|
|
@ -140,22 +118,15 @@ static double zero = 0.0;
|
|||
return(x*0.5+r/s);
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double U0[5] = {
|
||||
#else
|
||||
static double U0[5] = {
|
||||
#endif
|
||||
-1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */
|
||||
5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */
|
||||
-1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */
|
||||
2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */
|
||||
-9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double V0[5] = {
|
||||
#else
|
||||
static double V0[5] = {
|
||||
#endif
|
||||
1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */
|
||||
2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */
|
||||
1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */
|
||||
|
|
@ -163,12 +134,7 @@ static double V0[5] = {
|
|||
1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_y1(double x)
|
||||
#else
|
||||
double __ieee754_y1(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double z, s,c,ss,cc,u,v;
|
||||
int32_t hx,ix,lx;
|
||||
|
|
@ -226,11 +192,7 @@ static double V0[5] = {
|
|||
* | pone(x)-1-R/S | <= 2 ** ( -60.06)
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */
|
||||
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 */
|
||||
7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double ps8[5] = {
|
||||
#else
|
||||
static double ps8[5] = {
|
||||
#endif
|
||||
1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */
|
||||
3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */
|
||||
3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */
|
||||
|
|
@ -250,11 +209,7 @@ static double ps8[5] = {
|
|||
3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */
|
||||
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.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double ps5[5] = {
|
||||
#else
|
||||
static double ps5[5] = {
|
||||
#endif
|
||||
5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */
|
||||
9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */
|
||||
5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */
|
||||
|
|
@ -274,11 +226,7 @@ static double ps5[5] = {
|
|||
1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */
|
||||
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 */
|
||||
4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double ps3[5] = {
|
||||
#else
|
||||
static double ps3[5] = {
|
||||
#endif
|
||||
3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */
|
||||
3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */
|
||||
1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */
|
||||
|
|
@ -298,11 +243,7 @@ static double ps3[5] = {
|
|||
1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */
|
||||
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 */
|
||||
5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double ps2[5] = {
|
||||
#else
|
||||
static double ps2[5] = {
|
||||
#endif
|
||||
2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */
|
||||
1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */
|
||||
2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */
|
||||
|
|
@ -322,18 +260,9 @@ static double ps2[5] = {
|
|||
8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static double pone(double x)
|
||||
#else
|
||||
static double pone(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
#ifdef __STDC__
|
||||
const double *p = 0,*q = 0;
|
||||
#else
|
||||
double *p = 0,*q = 0;
|
||||
#endif
|
||||
double z,r,s;
|
||||
int32_t ix;
|
||||
GET_HIGH_WORD(ix,x);
|
||||
|
|
@ -359,11 +288,7 @@ static double ps2[5] = {
|
|||
* | 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] */
|
||||
#else
|
||||
static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
|
||||
#endif
|
||||
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
|
||||
-1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */
|
||||
-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 */
|
||||
-4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qs8[6] = {
|
||||
#else
|
||||
static double qs8[6] = {
|
||||
#endif
|
||||
1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */
|
||||
7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */
|
||||
1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */
|
||||
|
|
@ -384,11 +306,7 @@ static double qs8[6] = {
|
|||
-2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
-1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */
|
||||
-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 */
|
||||
-2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qs5[6] = {
|
||||
#else
|
||||
static double qs5[6] = {
|
||||
#endif
|
||||
8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */
|
||||
1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */
|
||||
1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */
|
||||
|
|
@ -409,11 +324,7 @@ static double qs5[6] = {
|
|||
-4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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 */
|
||||
-1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */
|
||||
-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.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qs3[6] = {
|
||||
#else
|
||||
static double qs3[6] = {
|
||||
#endif
|
||||
4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */
|
||||
6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */
|
||||
3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */
|
||||
|
|
@ -434,11 +342,7 @@ static double qs3[6] = {
|
|||
-1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */
|
||||
-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 */
|
||||
-2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */
|
||||
};
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double qs2[6] = {
|
||||
#else
|
||||
static double qs2[6] = {
|
||||
#endif
|
||||
2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */
|
||||
2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */
|
||||
7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */
|
||||
|
|
@ -459,18 +360,9 @@ static double qs2[6] = {
|
|||
-4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static double qone(double x)
|
||||
#else
|
||||
static double qone(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
#ifdef __STDC__
|
||||
const double *p = 0,*q = 0;
|
||||
#else
|
||||
double *p = 0,*q = 0;
|
||||
#endif
|
||||
double s,r,z;
|
||||
int32_t ix;
|
||||
GET_HIGH_WORD(ix,x);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* 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"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
|
||||
two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
|
||||
one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero = 0.00000000000000000000e+00;
|
||||
#else
|
||||
static double zero = 0.00000000000000000000e+00;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
double a, b, temp, di;
|
||||
|
|
@ -219,12 +201,7 @@ static double zero = 0.00000000000000000000e+00;
|
|||
if(sgn==1) return -b; else return b;
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
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 sign;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/* @(#)e_lgamma.c 5.1 93/09/24 */
|
||||
/*
|
||||
* ====================================================
|
||||
|
|
@ -22,13 +21,7 @@
|
|||
|
||||
extern int signgam;
|
||||
|
||||
#ifdef __STDC__
|
||||
//__private_extern__
|
||||
double __ieee754_lgamma(double x)
|
||||
#else
|
||||
double __ieee754_lgamma(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
return __ieee754_lgamma_r(x,&signgam);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Reentrant version of the logarithm of the Gamma function
|
||||
* 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"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
|
||||
half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
|
||||
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
|
|
@ -156,22 +147,9 @@ w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */
|
|||
w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */
|
||||
w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero= 0.00000000000000000000e+00;
|
||||
#else
|
||||
static double zero= 0.00000000000000000000e+00;
|
||||
#endif
|
||||
|
||||
static
|
||||
#ifdef __GNUC__
|
||||
__inline__
|
||||
#endif
|
||||
#ifdef __STDC__
|
||||
double sin_pi(double x)
|
||||
#else
|
||||
double sin_pi(x)
|
||||
double x;
|
||||
#endif
|
||||
static __inline__ double sin_pi(double x)
|
||||
{
|
||||
double y,z;
|
||||
int n,ix;
|
||||
|
|
@ -215,13 +193,7 @@ __inline__
|
|||
return -y;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
int i,hx,lx,ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
|
||||
ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
|
||||
two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
|
||||
|
|
@ -84,18 +75,9 @@ Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
|
|||
Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
|
||||
Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero = 0.0;
|
||||
#else
|
||||
static double zero = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_log(double x)
|
||||
#else
|
||||
double __ieee754_log(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double hfsq,f,s,z,R,w,t1,t2,dk;
|
||||
int32_t k,hx,i,j;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
|
||||
ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
|
||||
log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
|
||||
log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero = 0.0;
|
||||
#else
|
||||
static double zero = 0.0;
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_log10(double x)
|
||||
#else
|
||||
double __ieee754_log10(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double y,z;
|
||||
int32_t i,k,hx;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
bp[] = {1.0, 1.5,},
|
||||
dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
|
||||
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_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
|
||||
|
||||
#ifdef __STDC__
|
||||
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 y1,t1,t2,r,s,t,u,v,w;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
*
|
||||
* return the remainder of x rem pi/2 in y[0]+y[1]
|
||||
* use __kernel_rem_pio2()
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
/*
|
||||
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
|
||||
*/
|
||||
#ifdef __STDC__
|
||||
static const int32_t two_over_pi[] = {
|
||||
#else
|
||||
static int32_t two_over_pi[] = {
|
||||
#endif
|
||||
0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
|
||||
0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
|
||||
0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
|
||||
|
|
@ -44,11 +35,7 @@ static int32_t two_over_pi[] = {
|
|||
0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static const int32_t npio2_hw[] = {
|
||||
#else
|
||||
static int32_t npio2_hw[] = {
|
||||
#endif
|
||||
0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
|
||||
0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
|
||||
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)
|
||||
*/
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
|
||||
half = 5.00000000000000000000e-01, /* 0x3FE00000, 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_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
|
||||
|
||||
#ifdef __STDC__
|
||||
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 tx[3];
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Return :
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double zero = 0.0;
|
||||
#else
|
||||
static double zero = 0.0;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
double __ieee754_remainder(double x, double p)
|
||||
#else
|
||||
double __ieee754_remainder(x,p)
|
||||
double x,p;
|
||||
#endif
|
||||
{
|
||||
int32_t hx,hp;
|
||||
u_int32_t sx,lx,lp;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* passing various standard test suite. One
|
||||
* should use scalbn() instead.
|
||||
*/
|
||||
|
||||
#include "math.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)
|
||||
#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 (!finite(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);
|
||||
return scalbn(x,(int)fn);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
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)
|
||||
#else
|
||||
double __ieee754_sinh(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double t,w,h;
|
||||
int32_t ix,jx;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* 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"
|
||||
|
||||
#ifdef __STDC__
|
||||
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)
|
||||
#else
|
||||
double __ieee754_sqrt(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double z;
|
||||
int32_t sign = (int)0x80000000;
|
||||
|
|
|
|||
112
base/math/fpP.h
112
base/math/fpP.h
|
|
@ -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
|
||||
*/
|
||||
};
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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__ */
|
||||
|
|
@ -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 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
|
||||
C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
|
||||
|
|
@ -65,12 +56,7 @@ C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
|
|||
C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
|
||||
C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
|
||||
|
||||
#ifdef __STDC__
|
||||
double __kernel_cos(double x, double y)
|
||||
#else
|
||||
double __kernel_cos(x, y)
|
||||
double x,y;
|
||||
#endif
|
||||
{
|
||||
double a,hz,z,r,qx;
|
||||
int32_t ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
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[] = {
|
||||
#else
|
||||
static double PIo2[] = {
|
||||
#endif
|
||||
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
|
||||
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
|
||||
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
|
||||
|
|
@ -154,22 +141,13 @@ static double PIo2[] = {
|
|||
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
zero = 0.0,
|
||||
one = 1.0,
|
||||
two24 = 1.67772160000000000000e+07, /* 0x41700000, 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)
|
||||
#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;
|
||||
double z,fw,f[20],fq[20],q[20];
|
||||
|
|
|
|||
|
|
@ -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 function on [-pi/4, pi/4], pi/4 ~ 0.7854
|
||||
* 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))
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
|
||||
S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
|
||||
S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
|
||||
|
|
@ -58,12 +49,7 @@ S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
|
|||
S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
|
||||
S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
int32_t ix;
|
||||
|
|
|
|||
|
|
@ -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 <linux/errno.h> /* FIXME */
|
||||
|
||||
extern int libm_errno;
|
||||
|
||||
|
|
@ -24,11 +18,7 @@ extern int printk(const char *, ...);
|
|||
|
||||
#define WRITE2(u,v) printk("%.*s",v,u)
|
||||
|
||||
#ifdef __STDC__
|
||||
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.
|
||||
|
|
@ -77,13 +67,7 @@ static double zero = 0.0; /* used as const */
|
|||
* 42-- pow(NaN,0.0)
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
#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.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if(_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("acos: DOMAIN error\n", 19);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
|
@ -118,12 +102,12 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "asin" : "asinf";
|
||||
exc.retval = zero;
|
||||
if(_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if(_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("asin: DOMAIN error\n", 19);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
|
@ -135,12 +119,12 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "atan2" : "atan2f";
|
||||
exc.retval = zero;
|
||||
if(_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if(_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("atan2: DOMAIN error\n", 20);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
|
|
@ -153,9 +137,9 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
|
|
@ -168,9 +152,9 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
|
|
@ -183,9 +167,9 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
|
|
@ -195,9 +179,9 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "exp" : "expf";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
|
|
@ -210,12 +194,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("y0: DOMAIN error\n", 17);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
|
|
@ -228,12 +212,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("y0: DOMAIN error\n", 17);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
|
|
@ -246,12 +230,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("y1: DOMAIN error\n", 17);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
|
|
@ -264,12 +248,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("y1: DOMAIN error\n", 17);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
|
|
@ -282,12 +266,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("yn: DOMAIN error\n", 17);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
|
|
@ -300,12 +284,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("yn: DOMAIN error\n", 17);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
|
|
@ -318,9 +302,9 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
|
|
@ -333,12 +317,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("lgamma: SING error\n", 19);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
|
|
@ -351,12 +335,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("log: SING error\n", 16);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
|
|
@ -369,12 +353,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("log: DOMAIN error\n", 18);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
|
|
@ -387,12 +371,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("log10: SING error\n", 18);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 19:
|
||||
|
|
@ -405,12 +389,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("log10: DOMAIN error\n", 20);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
|
|
@ -423,7 +407,7 @@ static double zero = 0.0; /* used as const */
|
|||
if (_LIB_VERSION != _SVID_) exc.retval = 1.0;
|
||||
else if (!matherr(&exc)) {
|
||||
(void) WRITE2("pow(0,0): DOMAIN error\n", 23);
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
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 (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 22:
|
||||
|
|
@ -453,9 +437,9 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "pow" : "powf";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
|
|
@ -468,12 +452,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("pow(0,neg): DOMAIN error\n", 25);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
|
|
@ -486,12 +470,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = zero/zero; /* X/Open allow NaN */
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("neg**non-integral: DOMAIN error\n", 32);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
|
|
@ -504,9 +488,9 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL);
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 26:
|
||||
|
|
@ -519,12 +503,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = zero/zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("sqrt: DOMAIN error\n", 19);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
|
|
@ -537,12 +521,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = zero/zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("fmod: DOMAIN error\n", 20);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 28:
|
||||
|
|
@ -552,12 +536,12 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "remainder" : "remainderf";
|
||||
exc.retval = zero/zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("remainder: DOMAIN error\n", 24);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 29:
|
||||
|
|
@ -567,12 +551,12 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "acosh" : "acoshf";
|
||||
exc.retval = zero/zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("acosh: DOMAIN error\n", 20);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
|
|
@ -582,12 +566,12 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "atanh" : "atanhf";
|
||||
exc.retval = zero/zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("atanh: DOMAIN error\n", 20);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 31:
|
||||
|
|
@ -597,12 +581,12 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "atanh" : "atanhf";
|
||||
exc.retval = x/zero; /* sign(x)*inf */
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("atanh: SING error\n", 18);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
|
|
@ -612,9 +596,9 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "scalb" : "scalbf";
|
||||
exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 33:
|
||||
|
|
@ -624,9 +608,9 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "scalb" : "scalbf";
|
||||
exc.retval = copysign(zero,x);
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 34:
|
||||
|
|
@ -636,13 +620,13 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "j0" : "j0f";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2(exc.name, 2);
|
||||
(void) WRITE2(": TLOSS error\n", 14);
|
||||
}
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 35:
|
||||
|
|
@ -652,13 +636,13 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "y0" : "y0f";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2(exc.name, 2);
|
||||
(void) WRITE2(": TLOSS error\n", 14);
|
||||
}
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 36:
|
||||
|
|
@ -668,13 +652,13 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "j1" : "j1f";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2(exc.name, 2);
|
||||
(void) WRITE2(": TLOSS error\n", 14);
|
||||
}
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 37:
|
||||
|
|
@ -684,13 +668,13 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "y1" : "y1f";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2(exc.name, 2);
|
||||
(void) WRITE2(": TLOSS error\n", 14);
|
||||
}
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 38:
|
||||
|
|
@ -700,13 +684,13 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "jn" : "jnf";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2(exc.name, 2);
|
||||
(void) WRITE2(": TLOSS error\n", 14);
|
||||
}
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
|
|
@ -716,13 +700,13 @@ static double zero = 0.0; /* used as const */
|
|||
exc.name = type < 100 ? "yn" : "ynf";
|
||||
exc.retval = zero;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2(exc.name, 2);
|
||||
(void) WRITE2(": TLOSS error\n", 14);
|
||||
}
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
|
|
@ -735,9 +719,9 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = ERANGE;
|
||||
libm_errno = 34;
|
||||
}
|
||||
break;
|
||||
case 41:
|
||||
|
|
@ -750,12 +734,12 @@ static double zero = 0.0; /* used as const */
|
|||
else
|
||||
exc.retval = HUGE_VAL;
|
||||
if (_LIB_VERSION == _POSIX_)
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
else if (!matherr(&exc)) {
|
||||
if (_LIB_VERSION == _SVID_) {
|
||||
(void) WRITE2("gamma: SING error\n", 18);
|
||||
}
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
case 42:
|
||||
|
|
@ -768,7 +752,7 @@ static double zero = 0.0; /* used as const */
|
|||
if (_LIB_VERSION == _IEEE_ ||
|
||||
_LIB_VERSION == _POSIX_) exc.retval = 1.0;
|
||||
else if (!matherr(&exc)) {
|
||||
libm_errno = EDOM;
|
||||
libm_errno = 33;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 function on [-pi/4, pi/4], pi/4 ~ 0.7854
|
||||
* 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)))
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
#ifdef __STDC__
|
||||
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
|
||||
pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
|
||||
|
|
@ -74,12 +66,7 @@ T[] = {
|
|||
2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
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;
|
||||
int32_t ix,hx;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#define __USE_MISC
|
||||
#define __USE_SVID
|
||||
#define __USE_ISOC99 1
|
||||
#include <rtai_math.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -44,12 +47,9 @@ void __rtai_math_exit(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_RTAI_MATH_BUILTIN
|
||||
module_init(__rtai_math_init);
|
||||
module_exit(__rtai_math_exit);
|
||||
#endif /* CONFIG_RTAI_MATH_BUILTIN */
|
||||
|
||||
#ifdef CONFIG_KBUILD
|
||||
EXPORT_SYMBOL(acos);
|
||||
EXPORT_SYMBOL(asin);
|
||||
EXPORT_SYMBOL(atan);
|
||||
|
|
@ -61,6 +61,7 @@ EXPORT_SYMBOL(cosh);
|
|||
EXPORT_SYMBOL(exp);
|
||||
EXPORT_SYMBOL(expm1);
|
||||
EXPORT_SYMBOL(fabs);
|
||||
EXPORT_SYMBOL(finite);
|
||||
EXPORT_SYMBOL(floor);
|
||||
EXPORT_SYMBOL(fmod);
|
||||
EXPORT_SYMBOL(frexp);
|
||||
|
|
@ -74,8 +75,6 @@ EXPORT_SYMBOL(sinh);
|
|||
EXPORT_SYMBOL(sqrt);
|
||||
EXPORT_SYMBOL(tan);
|
||||
EXPORT_SYMBOL(tanh);
|
||||
|
||||
#ifdef CONFIG_RTAI_MATH_C99
|
||||
EXPORT_SYMBOL(acosh);
|
||||
EXPORT_SYMBOL(asinh);
|
||||
EXPORT_SYMBOL(atanh);
|
||||
|
|
@ -95,22 +94,14 @@ EXPORT_SYMBOL(ldexp);
|
|||
EXPORT_SYMBOL(lgamma);
|
||||
EXPORT_SYMBOL(lgamma_r);
|
||||
EXPORT_SYMBOL(log1p);
|
||||
EXPORT_SYMBOL(logb);
|
||||
EXPORT_SYMBOL(matherr);
|
||||
EXPORT_SYMBOL(nearbyint);
|
||||
EXPORT_SYMBOL(nextafter);
|
||||
EXPORT_SYMBOL(remainder);
|
||||
EXPORT_SYMBOL(rint);
|
||||
EXPORT_SYMBOL(rinttol);
|
||||
EXPORT_SYMBOL(round);
|
||||
EXPORT_SYMBOL(roundtol);
|
||||
EXPORT_SYMBOL(scalb);
|
||||
EXPORT_SYMBOL(signgam);
|
||||
EXPORT_SYMBOL(significand);
|
||||
EXPORT_SYMBOL(trunc);
|
||||
EXPORT_SYMBOL(y0);
|
||||
EXPORT_SYMBOL(y1);
|
||||
EXPORT_SYMBOL(yn);
|
||||
EXPORT_SYMBOL(libm_errno);
|
||||
#endif /* CONFIG_RTAI_MATH_C99 */
|
||||
#endif /* CONFIG_KBUILD */
|
||||
|
|
|
|||
104
base/math/logb.c
104
base/math/logb.c
|
|
@ -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__ */
|
||||
|
|
@ -17,8 +17,9 @@
|
|||
#ifndef _MATH_PRIVATE_H_
|
||||
#define _MATH_PRIVATE_H_
|
||||
|
||||
#include <endian.h>
|
||||
#include <sys/types.h>
|
||||
#include <asm/types.h>
|
||||
typedef u32 u_int32_t;
|
||||
typedef s32 int32_t;
|
||||
|
||||
/* The original fdlibm code used statements like:
|
||||
n0 = ((*(int*)&one)>>29)^1; * index of high word *
|
||||
|
|
@ -39,7 +40,7 @@
|
|||
* big endian.
|
||||
*/
|
||||
|
||||
#if (__BYTE_ORDER == __BIG_ENDIAN) || defined(__arm__)
|
||||
#if defined(__BIG_ENDIAN)
|
||||
|
||||
typedef union
|
||||
{
|
||||
|
|
@ -51,9 +52,8 @@ typedef union
|
|||
} parts;
|
||||
} ieee_double_shape_type;
|
||||
|
||||
#endif
|
||||
|
||||
#if (__BYTE_ORDER == __LITTLE_ENDIAN) && !defined(__arm__)
|
||||
#else
|
||||
|
||||
typedef union
|
||||
{
|
||||
|
|
@ -153,79 +153,83 @@ do { \
|
|||
} while (0)
|
||||
|
||||
/* ieee style elementary functions */
|
||||
extern double __ieee754_sqrt __P((double));
|
||||
extern double __ieee754_acos __P((double));
|
||||
extern double __ieee754_acosh __P((double));
|
||||
extern double __ieee754_log __P((double));
|
||||
extern double __ieee754_atanh __P((double));
|
||||
extern double __ieee754_asin __P((double));
|
||||
extern double __ieee754_atan2 __P((double,double));
|
||||
extern double __ieee754_exp __P((double));
|
||||
extern double __ieee754_cosh __P((double));
|
||||
extern double __ieee754_fmod __P((double,double));
|
||||
extern double __ieee754_pow __P((double,double));
|
||||
extern double __ieee754_lgamma_r __P((double,int *));
|
||||
extern double __ieee754_gamma_r __P((double,int *));
|
||||
extern double __ieee754_lgamma __P((double));
|
||||
extern double __ieee754_gamma __P((double));
|
||||
extern double __ieee754_log10 __P((double));
|
||||
extern double __ieee754_sinh __P((double));
|
||||
extern double __ieee754_hypot __P((double,double));
|
||||
extern double __ieee754_j0 __P((double));
|
||||
extern double __ieee754_j1 __P((double));
|
||||
extern double __ieee754_y0 __P((double));
|
||||
extern double __ieee754_y1 __P((double));
|
||||
extern double __ieee754_jn __P((int,double));
|
||||
extern double __ieee754_yn __P((int,double));
|
||||
extern double __ieee754_remainder __P((double,double));
|
||||
extern int __ieee754_rem_pio2 __P((double,double*));
|
||||
#if defined(_SCALB_INT)
|
||||
extern double __ieee754_scalb __P((double,int));
|
||||
#else
|
||||
extern double __ieee754_scalb __P((double,double));
|
||||
#endif
|
||||
extern double __ieee754_sqrt(double);
|
||||
extern double __ieee754_acos(double);
|
||||
extern double __ieee754_acosh(double);
|
||||
extern double __ieee754_log(double);
|
||||
extern double __ieee754_atanh(double);
|
||||
extern double __ieee754_asin(double);
|
||||
extern double __ieee754_atan2(double,double);
|
||||
extern double __ieee754_exp(double);
|
||||
extern double __ieee754_cosh(double);
|
||||
extern double __ieee754_fmod(double,double);
|
||||
extern double __ieee754_pow(double,double);
|
||||
extern double __ieee754_lgamma_r(double,int *);
|
||||
extern double __ieee754_gamma_r(double,int *);
|
||||
extern double __ieee754_lgamma(double);
|
||||
extern double __ieee754_gamma(double);
|
||||
extern double __ieee754_log10(double);
|
||||
extern double __ieee754_sinh(double);
|
||||
extern double __ieee754_hypot(double,double);
|
||||
extern double __ieee754_j0(double);
|
||||
extern double __ieee754_j1(double);
|
||||
extern double __ieee754_y0(double);
|
||||
extern double __ieee754_y1(double);
|
||||
extern double __ieee754_jn(int,double);
|
||||
extern double __ieee754_yn(int,double);
|
||||
extern double __ieee754_remainder(double,double);
|
||||
extern int __ieee754_rem_pio2(double,double*);
|
||||
extern double __ieee754_fmin(double,double);
|
||||
extern double __ieee754_fmax(double,double);
|
||||
extern double __ieee754_scalb(double,double);
|
||||
|
||||
/* fdlibm kernel function */
|
||||
extern double __kernel_standard __P((double,double,int));
|
||||
extern double __kernel_sin __P((double,double,int));
|
||||
extern double __kernel_cos __P((double,double));
|
||||
extern double __kernel_tan __P((double,double,int));
|
||||
extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*));
|
||||
|
||||
extern double __kernel_standard(double,double,int);
|
||||
extern double __kernel_sin(double,double,int);
|
||||
extern double __kernel_cos(double,double);
|
||||
extern double __kernel_tan(double,double,int);
|
||||
extern int __kernel_rem_pio2(double*,double*,int,int,int,const int*);
|
||||
|
||||
/* ieee style elementary float functions */
|
||||
extern float __ieee754_sqrtf __P((float));
|
||||
extern float __ieee754_acosf __P((float));
|
||||
extern float __ieee754_acoshf __P((float));
|
||||
extern float __ieee754_logf __P((float));
|
||||
extern float __ieee754_atanhf __P((float));
|
||||
extern float __ieee754_asinf __P((float));
|
||||
extern float __ieee754_atan2f __P((float,float));
|
||||
extern float __ieee754_expf __P((float));
|
||||
extern float __ieee754_coshf __P((float));
|
||||
extern float __ieee754_fmodf __P((float,float));
|
||||
extern float __ieee754_powf __P((float,float));
|
||||
extern float __ieee754_lgammaf_r __P((float,int *));
|
||||
extern float __ieee754_gammaf_r __P((float,int *));
|
||||
extern float __ieee754_lgammaf __P((float));
|
||||
extern float __ieee754_gammaf __P((float));
|
||||
extern float __ieee754_log10f __P((float));
|
||||
extern float __ieee754_sinhf __P((float));
|
||||
extern float __ieee754_hypotf __P((float,float));
|
||||
extern float __ieee754_j0f __P((float));
|
||||
extern float __ieee754_j1f __P((float));
|
||||
extern float __ieee754_y0f __P((float));
|
||||
extern float __ieee754_y1f __P((float));
|
||||
extern float __ieee754_jnf __P((int,float));
|
||||
extern float __ieee754_ynf __P((int,float));
|
||||
extern float __ieee754_remainderf __P((float,float));
|
||||
extern int __ieee754_rem_pio2f __P((float,float*));
|
||||
extern float __ieee754_scalbf __P((float,float));
|
||||
extern float __ieee754_sqrtf(float);
|
||||
extern float __ieee754_acosf(float);
|
||||
extern float __ieee754_acoshf(float);
|
||||
extern float __ieee754_logf(float);
|
||||
extern float __ieee754_atanhf(float);
|
||||
extern float __ieee754_asinf(float);
|
||||
extern float __ieee754_atan2f(float,float);
|
||||
extern float __ieee754_expf(float);
|
||||
extern float __ieee754_coshf(float);
|
||||
extern float __ieee754_fmodf(float,float);
|
||||
extern float __ieee754_powf(float,float);
|
||||
extern float __ieee754_lgammaf_r(float,int *);
|
||||
extern float __ieee754_gammaf_r(float,int *);
|
||||
extern float __ieee754_lgammaf(float);
|
||||
extern float __ieee754_gammaf(float);
|
||||
extern float __ieee754_log10f(float);
|
||||
extern float __ieee754_sinhf(float);
|
||||
extern float __ieee754_hypotf(float,float);
|
||||
extern float __ieee754_j0f(float);
|
||||
extern float __ieee754_j1f(float);
|
||||
extern float __ieee754_y0f(float);
|
||||
extern float __ieee754_y1f(float);
|
||||
extern float __ieee754_jnf(int,float);
|
||||
extern float __ieee754_ynf(int,float);
|
||||
extern float __ieee754_remainderf(float,float);
|
||||
extern int __ieee754_rem_pio2f(float,float*);
|
||||
extern float __ieee754_scalbf(float,float);
|
||||
|
||||
/* float versions of fdlibm kernel functions */
|
||||
extern float __kernel_sinf __P((float,float,int));
|
||||
extern float __kernel_cosf __P((float,float));
|
||||
extern float __kernel_tanf __P((float,float,int));
|
||||
extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const int*));
|
||||
extern float __kernel_sinf(float,float,int);
|
||||
extern float __kernel_cosf(float,float);
|
||||
extern float __kernel_tanf(float,float,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_ */
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
@ -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)
|
||||
* Method :
|
||||
* 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)))
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
|
||||
ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
|
||||
huge= 1.00000000000000000000e+300;
|
||||
|
||||
#ifdef __STDC__
|
||||
double asinh(double x)
|
||||
#else
|
||||
double asinh(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double t,w;
|
||||
int32_t hx,ix;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
* Method
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "math.h"
|
||||
#include "mathP.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double atanhi[] = {
|
||||
#else
|
||||
static double atanhi[] = {
|
||||
#endif
|
||||
4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
|
||||
7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
|
||||
9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
|
||||
1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double atanlo[] = {
|
||||
#else
|
||||
static double atanlo[] = {
|
||||
#endif
|
||||
2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
|
||||
3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
|
||||
1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
|
||||
6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double aT[] = {
|
||||
#else
|
||||
static double aT[] = {
|
||||
#endif
|
||||
3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
|
||||
-1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
|
||||
1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
|
||||
|
|
@ -77,20 +60,11 @@ static double aT[] = {
|
|||
1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
static const double
|
||||
#else
|
||||
static double
|
||||
#endif
|
||||
one = 1.0,
|
||||
huge = 1.0e300;
|
||||
|
||||
#ifdef __STDC__
|
||||
double atan(double x)
|
||||
#else
|
||||
double atan(x)
|
||||
double x;
|
||||
#endif
|
||||
{
|
||||
double w,s1,s2,z;
|
||||
int32_t ix,hx,id;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue